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/LibRichErrors.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/Ownable.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
||||
@ -35,6 +36,7 @@ contract MixinAssets is
|
||||
IAssets
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Withdraws assets from this contract. It may be used by the owner to withdraw assets
|
||||
/// that were accidentally sent to this contract.
|
||||
@ -95,7 +97,9 @@ contract MixinAssets is
|
||||
_transferERC20Token(assetData, amount);
|
||||
} else if (proxyId == IAssetData(address(0)).ERC721Token.selector) {
|
||||
_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(
|
||||
proxyId
|
||||
));
|
||||
@ -141,4 +145,23 @@ contract MixinAssets is
|
||||
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
|
||||
)
|
||||
{
|
||||
bool noTakerFee = _noTakerFee(order.takerFee, order.takerFeeAssetData);
|
||||
// No taker fee or percentage fee
|
||||
if (
|
||||
order.takerFee == 0 ||
|
||||
noTakerFee ||
|
||||
_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.makerAssetData)
|
||||
) {
|
||||
// Attempt to sell the remaining amount of WETH
|
||||
@ -105,7 +106,7 @@ contract MixinExchangeWrapper is
|
||||
|
||||
// Subtract fee from makerAssetFilledAmount for the net amount acquired.
|
||||
makerAssetAcquiredAmount = singleFillResults.makerAssetFilledAmount
|
||||
.safeSub(singleFillResults.takerFeePaid);
|
||||
.safeSub(noTakerFee ? 0 : singleFillResults.takerFeePaid);
|
||||
|
||||
// WETH fee
|
||||
} else if (_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.takerAssetData)) {
|
||||
@ -230,9 +231,10 @@ contract MixinExchangeWrapper is
|
||||
uint256 makerAssetAcquiredAmount
|
||||
)
|
||||
{
|
||||
bool noTakerFee = _noTakerFee(order.takerFee, order.takerFeeAssetData);
|
||||
// No taker fee or WETH fee
|
||||
if (
|
||||
order.takerFee == 0 ||
|
||||
noTakerFee ||
|
||||
_areUnderlyingAssetsEqual(order.takerFeeAssetData, order.takerAssetData)
|
||||
) {
|
||||
// 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.
|
||||
wethSpentAmount = singleFillResults.takerAssetFilledAmount
|
||||
.safeAdd(singleFillResults.takerFeePaid)
|
||||
.safeAdd(noTakerFee ? 0 : singleFillResults.takerFeePaid)
|
||||
.safeAdd(singleFillResults.protocolFeePaid);
|
||||
|
||||
makerAssetAcquiredAmount = singleFillResults.makerAssetFilledAmount;
|
||||
@ -480,7 +482,7 @@ contract MixinExchangeWrapper is
|
||||
address token2 = assetData2.readAddress(16);
|
||||
return (token1 == token2);
|
||||
} 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;
|
||||
}
|
||||
|
||||
/// @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