122 lines
4.8 KiB
Solidity
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));
|
|
}
|
|
}
|