add multiplex TokenForEth functions to metatransactions
This commit is contained in:
parent
90b826da61
commit
2507028612
@ -15,6 +15,7 @@
|
|||||||
pragma solidity ^0.6.5;
|
pragma solidity ^0.6.5;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
|
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||||
@ -92,6 +93,9 @@ contract MetaTransactionsFeature is
|
|||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// @dev The WETH token contract.
|
||||||
|
IEtherTokenV06 private immutable WETH;
|
||||||
|
|
||||||
/// @dev Refunds up to `msg.value` leftover ETH at the end of the call.
|
/// @dev Refunds up to `msg.value` leftover ETH at the end of the call.
|
||||||
modifier refundsAttachedEth() {
|
modifier refundsAttachedEth() {
|
||||||
_;
|
_;
|
||||||
@ -109,7 +113,12 @@ contract MetaTransactionsFeature is
|
|||||||
require(initialBalance <= address(this).balance, "MetaTransactionsFeature/ETH_LEAK");
|
require(initialBalance <= address(this).balance, "MetaTransactionsFeature/ETH_LEAK");
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(address zeroExAddress) public FixinCommon() FixinEIP712(zeroExAddress) {}
|
constructor(
|
||||||
|
address zeroExAddress,
|
||||||
|
IEtherTokenV06 weth
|
||||||
|
) public FixinCommon() FixinEIP712(zeroExAddress) {
|
||||||
|
WETH = weth;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Initialize and register this feature.
|
/// @dev Initialize and register this feature.
|
||||||
/// Should be delegatecalled by `Migrate.migrate()`.
|
/// Should be delegatecalled by `Migrate.migrate()`.
|
||||||
@ -248,8 +257,12 @@ contract MetaTransactionsFeature is
|
|||||||
returnResult = _executeFillRfqOrderCall(state);
|
returnResult = _executeFillRfqOrderCall(state);
|
||||||
} else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForToken.selector) {
|
} else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForToken.selector) {
|
||||||
returnResult = _executeMultiplexBatchSellTokenForTokenCall(state);
|
returnResult = _executeMultiplexBatchSellTokenForTokenCall(state);
|
||||||
|
} else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForEth.selector) {
|
||||||
|
returnResult = _executeMultiplexBatchSellTokenForEthCall(state);
|
||||||
} else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForToken.selector) {
|
} else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForToken.selector) {
|
||||||
returnResult = _executeMultiplexMultiHopSellTokenForTokenCall(state);
|
returnResult = _executeMultiplexMultiHopSellTokenForTokenCall(state);
|
||||||
|
} else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForEth.selector) {
|
||||||
|
returnResult = _executeMultiplexMultiHopSellTokenForEthCall(state);
|
||||||
} else {
|
} else {
|
||||||
LibMetaTransactionsRichErrors.MetaTransactionUnsupportedFunctionError(state.hash, state.selector).rrevert();
|
LibMetaTransactionsRichErrors.MetaTransactionUnsupportedFunctionError(state.hash, state.selector).rrevert();
|
||||||
}
|
}
|
||||||
@ -497,6 +510,46 @@ contract MetaTransactionsFeature is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Execute a `IMultiplexFeature.multiplexBatchSellTokenForEth()` meta-transaction
|
||||||
|
/// call by decoding the call args and translating the call to the internal
|
||||||
|
/// `IMultiplexFeature._multiplexBatchSellTokenForEth()` variant, where we can override the
|
||||||
|
/// msgSender address.
|
||||||
|
function _executeMultiplexBatchSellTokenForEthCall(ExecuteState memory state) private returns (bytes memory returnResult) {
|
||||||
|
IERC20TokenV06 inputToken;
|
||||||
|
IMultiplexFeature.BatchSellSubcall[] memory calls;
|
||||||
|
uint256 sellAmount;
|
||||||
|
uint256 minBuyAmount;
|
||||||
|
|
||||||
|
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||||
|
(inputToken, calls, sellAmount, minBuyAmount) = abi.decode(
|
||||||
|
args,
|
||||||
|
(IERC20TokenV06, IMultiplexFeature.BatchSellSubcall[], uint256, uint256)
|
||||||
|
);
|
||||||
|
|
||||||
|
returnResult = _callSelf(
|
||||||
|
state.hash,
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IMultiplexFeature._multiplexBatchSell.selector,
|
||||||
|
IMultiplexFeature.BatchSellParams({
|
||||||
|
inputToken: inputToken,
|
||||||
|
outputToken: IERC20TokenV06(WETH),
|
||||||
|
sellAmount: sellAmount,
|
||||||
|
calls: calls,
|
||||||
|
useSelfBalance: false,
|
||||||
|
recipient: address(this),
|
||||||
|
msgSender: state.mtx.signer
|
||||||
|
}),
|
||||||
|
minBuyAmount
|
||||||
|
),
|
||||||
|
state.mtx.value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unwrap and transfer WETH
|
||||||
|
uint256 boughtAmount = abi.decode(returnResult, (uint256));
|
||||||
|
WETH.withdraw(boughtAmount);
|
||||||
|
_transferEth(state.mtx.signer, boughtAmount);
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForToken()` meta-transaction
|
/// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForToken()` meta-transaction
|
||||||
/// call by decoding the call args and translating the call to the internal
|
/// call by decoding the call args and translating the call to the internal
|
||||||
/// `IMultiplexFeature._multiplexMultiHopSell()` variant, where we can override the
|
/// `IMultiplexFeature._multiplexMultiHopSell()` variant, where we can override the
|
||||||
@ -532,6 +585,50 @@ contract MetaTransactionsFeature is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForEth()` meta-transaction
|
||||||
|
/// call by decoding the call args and translating the call to the internal
|
||||||
|
/// `IMultiplexFeature._multiplexMultiHopSellTokenForEth()` variant, where we can override the
|
||||||
|
/// msgSender address.
|
||||||
|
function _executeMultiplexMultiHopSellTokenForEthCall(ExecuteState memory state) private returns (bytes memory returnResult) {
|
||||||
|
address[] memory tokens;
|
||||||
|
IMultiplexFeature.MultiHopSellSubcall[] memory calls;
|
||||||
|
uint256 sellAmount;
|
||||||
|
uint256 minBuyAmount;
|
||||||
|
|
||||||
|
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||||
|
(tokens, calls, sellAmount, minBuyAmount) = abi.decode(
|
||||||
|
args,
|
||||||
|
(address[], IMultiplexFeature.MultiHopSellSubcall[], uint256, uint256)
|
||||||
|
);
|
||||||
|
|
||||||
|
require(
|
||||||
|
tokens[tokens.length - 1] == address(WETH),
|
||||||
|
"MetaTransactionsFeature::multiplexMultiHopSellTokenForEth/NOT_WETH"
|
||||||
|
);
|
||||||
|
|
||||||
|
returnResult = _callSelf(
|
||||||
|
state.hash,
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IMultiplexFeature._multiplexMultiHopSell.selector,
|
||||||
|
IMultiplexFeature.MultiHopSellParams({
|
||||||
|
tokens: tokens,
|
||||||
|
sellAmount: sellAmount,
|
||||||
|
calls: calls,
|
||||||
|
useSelfBalance: false,
|
||||||
|
recipient: address(this),
|
||||||
|
msgSender: state.mtx.signer
|
||||||
|
}),
|
||||||
|
minBuyAmount
|
||||||
|
),
|
||||||
|
state.mtx.value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unwrap and transfer WETH
|
||||||
|
uint256 boughtAmount = abi.decode(returnResult, (uint256));
|
||||||
|
WETH.withdraw(boughtAmount);
|
||||||
|
_transferEth(state.mtx.signer, boughtAmount);
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Make an arbitrary internal, meta-transaction call.
|
/// @dev Make an arbitrary internal, meta-transaction call.
|
||||||
/// Warning: Do not let unadulterated `callData` into this function.
|
/// Warning: Do not let unadulterated `callData` into this function.
|
||||||
function _callSelf(bytes32 hash, bytes memory callData, uint256 value) private returns (bytes memory returnResult) {
|
function _callSelf(bytes32 hash, bytes memory callData, uint256 value) private returns (bytes memory returnResult) {
|
||||||
|
@ -331,9 +331,7 @@ contract MultiplexFeature is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Executes a multi-hop sell and checks that at least
|
/// @dev Executes a multi-hop sell. Internal variant.
|
||||||
/// `minBuyAmount` of output tokens were bought. Internal
|
|
||||||
/// variant.
|
|
||||||
/// @param params Multi-hop sell parameters.
|
/// @param params Multi-hop sell parameters.
|
||||||
/// @param minBuyAmount The minimum amount of output tokens that
|
/// @param minBuyAmount The minimum amount of output tokens that
|
||||||
/// must be bought for this function to not revert.
|
/// must be bought for this function to not revert.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user