Files
protocol/contracts/zero-ex/script/MetaTx.s.sol

122 lines
4.8 KiB
Solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "forge-std/Script.sol";
import "src/IZeroEx.sol";
import "src/features/MetaTransactionsFeature.sol";
import "src/features/interfaces/IMetaTransactionsFeature.sol";
import "src/features/libs/LibSignature.sol";
import "src/transformers/FillQuoteTransformer.sol";
import "src/transformers/PayTakerTransformer.sol";
contract MetaTxScript is Script {
IZeroEx private constant exchangeProxy = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF);
IERC20TokenV06 private constant wethToken = IERC20TokenV06(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20TokenV06 private constant usdcToken = IERC20TokenV06(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
uint256 private constant oneEth = 1e18;
address private constant ZERO_ADDRESS = 0x0000000000000000000000000000000000000000;
address private constant USER_ADDRESS = 0x6dc3a54FeAE57B65d185A7B159c5d3FA7fD7FD0F;
uint256 private constant USER_KEY = 0x1fc1630343b31e60b7a197a53149ca571ed9d9791e2833337bbd8110c30710ec;
uint32 private constant PAYTAKER_TFM_NONCE = 7;
uint32 private constant FILLQUOTE_TFM_NONCE = 25;
function mtxCall(bytes memory callData) private returns (bytes memory) {
IMetaTransactionsFeature.MetaTransactionFeeData[] memory fees = new IMetaTransactionsFeature.MetaTransactionFeeData[](1);
fees[0] = IMetaTransactionsFeature.MetaTransactionFeeData({
recipient: address(123),
amount: oneEth
});
IMetaTransactionsFeature.MetaTransactionData memory mtx = IMetaTransactionsFeature.MetaTransactionData({
signer: payable(USER_ADDRESS),
sender: ZERO_ADDRESS,
minGasPrice: 0,
maxGasPrice: 100000000000,
expirationTimeSeconds: block.timestamp + 600,
salt: 123,
callData: callData,
value: 0,
feeToken: wethToken,
fees: fees
});
bytes32 mtxHash = exchangeProxy.getMetaTransactionHash(mtx);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(USER_KEY, mtxHash);
LibSignature.Signature memory sig = LibSignature.Signature(LibSignature.SignatureType.EIP712, v, r, s);
return abi.encodeWithSelector(
exchangeProxy.executeMetaTransaction.selector,
mtx,
sig
);
}
function transformERC20Call() private pure returns (bytes memory) {
FillQuoteTransformer.OrderType[] memory fillSequence = new FillQuoteTransformer.OrderType[](1);
fillSequence[0] = FillQuoteTransformer.OrderType.Bridge;
FillQuoteTransformer.TransformData memory fillQuoteTransformData = FillQuoteTransformer.TransformData({
side: FillQuoteTransformer.Side.Sell,
sellToken: wethToken,
buyToken: usdcToken,
bridgeOrders: new IBridgeAdapter.BridgeOrder[](0),
limitOrders: new FillQuoteTransformer.LimitOrderInfo[](0),
rfqOrders: new FillQuoteTransformer.RfqOrderInfo[](0),
fillSequence: new FillQuoteTransformer.OrderType[](0),
fillAmount: 0,
refundReceiver: address(0),
otcOrders: new FillQuoteTransformer.OtcOrderInfo[](0)
});
IERC20TokenV06[] memory payTakerTokens = new IERC20TokenV06[](1);
payTakerTokens[0] = wethToken;
PayTakerTransformer.TransformData memory payTakerTransformData = PayTakerTransformer.TransformData(
payTakerTokens,
new uint256[](0)
);
ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](2);
transformations[0] = ITransformERC20Feature.Transformation(
FILLQUOTE_TFM_NONCE,
abi.encode(fillQuoteTransformData)
);
transformations[1] = ITransformERC20Feature.Transformation(
PAYTAKER_TFM_NONCE,
abi.encode(payTakerTransformData)
);
return abi.encodeWithSelector(
exchangeProxy.transformERC20.selector,
wethToken,
usdcToken,
0,
0,
transformations
);
}
function deploy() private {
address mtxFeature = address(new MetaTransactionsFeature(address(exchangeProxy)));
address owner = exchangeProxy.owner();
vm.prank(owner);
exchangeProxy.migrate(mtxFeature, abi.encodeWithSignature("migrate()"), owner);
}
function run() public {
deploy();
bytes memory transformCalldata = transformERC20Call();
bytes memory mtxCalldata = mtxCall(transformCalldata);
vm.prank(ZERO_ADDRESS);
wethToken.transfer(USER_ADDRESS, oneEth);
vm.prank(USER_ADDRESS);
wethToken.approve(address(exchangeProxy), oneEth);
vm.prank(USER_ADDRESS);
(address(exchangeProxy).call(mtxCalldata));
}
}