Forwarder StaticCall and MultiAsset buy support
This commit is contained in:
parent
8b27380feb
commit
2b8c6dc8f9
@ -20,6 +20,7 @@ pragma solidity ^0.5.9;
|
|||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/Ownable.sol";
|
import "@0x/contracts-utils/contracts/src/Ownable.sol";
|
||||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
||||||
@ -35,6 +36,7 @@ contract MixinAssets is
|
|||||||
IAssets
|
IAssets
|
||||||
{
|
{
|
||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
/// @dev Withdraws assets from this contract. It may be used by the owner to withdraw assets
|
/// @dev Withdraws assets from this contract. It may be used by the owner to withdraw assets
|
||||||
/// that were accidentally sent to this contract.
|
/// that were accidentally sent to this contract.
|
||||||
@ -95,7 +97,9 @@ contract MixinAssets is
|
|||||||
_transferERC20Token(assetData, amount);
|
_transferERC20Token(assetData, amount);
|
||||||
} else if (proxyId == IAssetData(address(0)).ERC721Token.selector) {
|
} else if (proxyId == IAssetData(address(0)).ERC721Token.selector) {
|
||||||
_transferERC721Token(assetData, amount);
|
_transferERC721Token(assetData, amount);
|
||||||
} else {
|
} else if (proxyId == IAssetData(address(0)).MultiAsset.selector) {
|
||||||
|
_transferMultiAsset(assetData, amount);
|
||||||
|
} else if (proxyId != IAssetData(address(0)).StaticCall.selector) {
|
||||||
LibRichErrors.rrevert(LibForwarderRichErrors.UnsupportedAssetProxyError(
|
LibRichErrors.rrevert(LibForwarderRichErrors.UnsupportedAssetProxyError(
|
||||||
proxyId
|
proxyId
|
||||||
));
|
));
|
||||||
@ -141,4 +145,23 @@ contract MixinAssets is
|
|||||||
tokenId
|
tokenId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _transferMultiAsset(
|
||||||
|
bytes memory assetData,
|
||||||
|
uint256 amount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
// solhint-disable indent
|
||||||
|
(uint256[] memory nestedAmounts, bytes[] memory nestedAssetData) = abi.decode(
|
||||||
|
assetData.slice(4, assetData.length),
|
||||||
|
(uint256[], bytes[])
|
||||||
|
);
|
||||||
|
// solhint-enable indent
|
||||||
|
|
||||||
|
uint256 numNestedAssets = nestedAssetData.length;
|
||||||
|
for (uint256 i = 0; i != numNestedAssets; i++) {
|
||||||
|
_transferAssetToSender(nestedAssetData[i], amount.safeMul(nestedAmounts[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,10 @@ contract MixinExchangeWrapper is
|
|||||||
uint256 makerAssetAcquiredAmount
|
uint256 makerAssetAcquiredAmount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
bool noTakerFee = _noTakerFee(order.takerFee, order.takerFeeAssetData);
|
||||||
// No taker fee or percentage fee
|
// No taker fee or percentage fee
|
||||||
if (
|
if (
|
||||||
order.takerFee == 0 ||
|
noTakerFee ||
|
||||||
_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.makerAssetData)
|
_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.makerAssetData)
|
||||||
) {
|
) {
|
||||||
// Attempt to sell the remaining amount of WETH
|
// Attempt to sell the remaining amount of WETH
|
||||||
@ -105,7 +106,7 @@ contract MixinExchangeWrapper is
|
|||||||
|
|
||||||
// Subtract fee from makerAssetFilledAmount for the net amount acquired.
|
// Subtract fee from makerAssetFilledAmount for the net amount acquired.
|
||||||
makerAssetAcquiredAmount = singleFillResults.makerAssetFilledAmount
|
makerAssetAcquiredAmount = singleFillResults.makerAssetFilledAmount
|
||||||
.safeSub(singleFillResults.takerFeePaid);
|
.safeSub(noTakerFee ? 0 : singleFillResults.takerFeePaid);
|
||||||
|
|
||||||
// WETH fee
|
// WETH fee
|
||||||
} else if (_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.takerAssetData)) {
|
} else if (_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.takerAssetData)) {
|
||||||
@ -230,9 +231,10 @@ contract MixinExchangeWrapper is
|
|||||||
uint256 makerAssetAcquiredAmount
|
uint256 makerAssetAcquiredAmount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
bool noTakerFee = _noTakerFee(order.takerFee, order.takerFeeAssetData);
|
||||||
// No taker fee or WETH fee
|
// No taker fee or WETH fee
|
||||||
if (
|
if (
|
||||||
order.takerFee == 0 ||
|
noTakerFee ||
|
||||||
_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.takerAssetData)
|
_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.takerAssetData)
|
||||||
) {
|
) {
|
||||||
// Calculate the remaining amount of takerAsset to sell
|
// Calculate the remaining amount of takerAsset to sell
|
||||||
@ -251,7 +253,7 @@ contract MixinExchangeWrapper is
|
|||||||
|
|
||||||
// WETH is also spent on the protocol and taker fees, so we add it here.
|
// WETH is also spent on the protocol and taker fees, so we add it here.
|
||||||
wethSpentAmount = singleFillResults.takerAssetFilledAmount
|
wethSpentAmount = singleFillResults.takerAssetFilledAmount
|
||||||
.safeAdd(singleFillResults.takerFeePaid)
|
.safeAdd(noTakerFee ? 0 : singleFillResults.takerFeePaid)
|
||||||
.safeAdd(singleFillResults.protocolFeePaid);
|
.safeAdd(singleFillResults.protocolFeePaid);
|
||||||
|
|
||||||
makerAssetAcquiredAmount = singleFillResults.makerAssetFilledAmount;
|
makerAssetAcquiredAmount = singleFillResults.makerAssetFilledAmount;
|
||||||
@ -480,7 +482,7 @@ contract MixinExchangeWrapper is
|
|||||||
address token2 = assetData2.readAddress(16);
|
address token2 = assetData2.readAddress(16);
|
||||||
return (token1 == token2);
|
return (token1 == token2);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return assetData1.equals(assetData2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,4 +496,24 @@ contract MixinExchangeWrapper is
|
|||||||
{
|
{
|
||||||
return order.makerFeeAssetData.length > 3 && order.makerFeeAssetData.readBytes4(0) == EXCHANGE_V2_ORDER_ID;
|
return order.makerFeeAssetData.length > 3 && order.makerFeeAssetData.readBytes4(0) == EXCHANGE_V2_ORDER_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Checks whether one asset is effectively equal to another asset.
|
||||||
|
/// This is the case if they have the same ERC20Proxy/ERC20BridgeProxy asset data, or if
|
||||||
|
/// one is the ERC20Bridge equivalent of the other.
|
||||||
|
/// @param takerFee Byte array encoded for the takerFee asset proxy.
|
||||||
|
/// @param takerFeeAssetData Byte array encoded for the maker asset proxy.
|
||||||
|
/// @return Whether or not the underlying assets are equal.
|
||||||
|
function _noTakerFee(
|
||||||
|
uint256 takerFee,
|
||||||
|
bytes memory takerFeeAssetData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
takerFee == 0 ||
|
||||||
|
takerFeeAssetData.readBytes4(0) == IAssetData(address(0)).StaticCall.selector
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user