DCA Orders
This commit is contained in:
		
							
								
								
									
										36
									
								
								contracts/zero-ex/contracts/scripts/ApproveMe.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								contracts/zero-ex/contracts/scripts/ApproveMe.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "forge-std/Script.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract DealMe is Test, Script {
 | 
			
		||||
    function setUp() public {}
 | 
			
		||||
 | 
			
		||||
    function run() public {
 | 
			
		||||
        // set approval
 | 
			
		||||
        vm.startBroadcast(0x6879fAb591ed0d62537A3Cac9D7cd41218445a84);
 | 
			
		||||
 | 
			
		||||
        IERC20Token(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48).approve(
 | 
			
		||||
            0xDef1C0ded9bec7F1a1670819833240f027b25EfF,
 | 
			
		||||
            type(uint256).max
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        vm.stopBroadcast();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								contracts/zero-ex/contracts/scripts/DealMe.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								contracts/zero-ex/contracts/scripts/DealMe.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "forge-std/Script.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract DealMe is Test, Script {
 | 
			
		||||
    function setUp() public {}
 | 
			
		||||
 | 
			
		||||
    function run() public {
 | 
			
		||||
        vm.startBroadcast(0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503);
 | 
			
		||||
 | 
			
		||||
        IERC20Token(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48).transfer(
 | 
			
		||||
            0x6879fAb591ed0d62537A3Cac9D7cd41218445a84,
 | 
			
		||||
            1000e6
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        (0x6879fAb591ed0d62537A3Cac9D7cd41218445a84).transfer(1 ether);
 | 
			
		||||
        (0xb985d345c4bb8121cE2d18583b2a28e98D56d04b).transfer(1 ether);
 | 
			
		||||
 | 
			
		||||
        vm.stopBroadcast();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								contracts/zero-ex/contracts/scripts/Debugger.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								contracts/zero-ex/contracts/scripts/Debugger.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6;
 | 
			
		||||
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../utils/ForkUtils.sol";
 | 
			
		||||
import "../utils/TestUtils.sol";
 | 
			
		||||
import "src/IZeroEx.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "src/features/TransformERC20Feature.sol";
 | 
			
		||||
import "src/external/TransformerDeployer.sol";
 | 
			
		||||
import "src/transformers/WethTransformer.sol";
 | 
			
		||||
import "src/transformers/FillQuoteTransformer.sol";
 | 
			
		||||
import "src/transformers/bridges/BridgeProtocols.sol";
 | 
			
		||||
import "src/features/OtcOrdersFeature.sol";
 | 
			
		||||
 | 
			
		||||
contract TraceCalldata is Test, ForkUtils, TestUtils {
 | 
			
		||||
    using LibERC20TokenV06 for IERC20TokenV06;
 | 
			
		||||
 | 
			
		||||
    function setUp() public {
 | 
			
		||||
        _setup();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function test_traceZeroExCall() public {
 | 
			
		||||
        log_string("TraceExchangeProxyCall");
 | 
			
		||||
        for (uint256 i = 0; i < 1; i++) {
 | 
			
		||||
            //skip fantom/avax failing test
 | 
			
		||||
            if (i == 3 || i == 4) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            vm.selectFork(forkIds[chains[i]]);
 | 
			
		||||
            log_named_string("  Selecting Fork On", chains[i]);
 | 
			
		||||
            vm.deal(address(this), 1e18);
 | 
			
		||||
            labelAddresses(
 | 
			
		||||
                chains[i],
 | 
			
		||||
                indexChainsByChain[chains[i]],
 | 
			
		||||
                getTokens(i),
 | 
			
		||||
                getContractAddresses(i),
 | 
			
		||||
                getLiquiditySourceAddresses(i)
 | 
			
		||||
            );
 | 
			
		||||
            swapWithOtcOrder(getTokens(i), getContractAddresses(i), getLiquiditySourceAddresses(i));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* solhint-disable function-max-lines */
 | 
			
		||||
    function swapWithOtcOrder(
 | 
			
		||||
        TokenAddresses memory tokens,
 | 
			
		||||
        ContractAddresses memory addresses,
 | 
			
		||||
        LiquiditySources memory sources
 | 
			
		||||
    ) public onlyForked {
 | 
			
		||||
        IZERO_EX = IZeroEx(addresses.exchangeProxy);
 | 
			
		||||
        address taker = address(0xd00d00cAca000000000000000000000000001337);
 | 
			
		||||
        vm.label(taker, "API Quote Taker");
 | 
			
		||||
        deal(address(tokens.USDT), taker, 100e30);
 | 
			
		||||
        //deal(address(tokens.WrappedNativeToken), taker, 100e30);
 | 
			
		||||
        vm.startPrank(taker);
 | 
			
		||||
        IERC20TokenV06(tokens.USDT).approveIfBelow(address(addresses.exchangeProxy), uint256(-1));
 | 
			
		||||
        //IERC20TokenV06(tokens.WrappedNativeToken).approveIfBelow(address(taker), uint256(-1));
 | 
			
		||||
 | 
			
		||||
        //emit log_address(address(tokens.WrappedNativeToken));
 | 
			
		||||
        IERC20TokenV06(tokens.USDT).balanceOf(taker);
 | 
			
		||||
        IERC20TokenV06(tokens.WrappedNativeToken).balanceOf(taker);
 | 
			
		||||
        (bool success, bytes memory result) = addresses.exchangeProxy.call(
 | 
			
		||||
            hex"7a1eb1b9000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000000000003dd141a0000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000003e711b8000000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000a3f14cb81e6edb7b1249755dd20e2bfb23597fd70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00d00caca0000000000000000000000000013370000000063f50e17000000000000000200000000000000000000000063f50da10000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001c543148f2a2124e690f19ab0042906b437f954a52b9fbef6019c3968befac860466a819bd38bb6c60c5341f65d3e596d17573c80fc78a3a837d7ed6392b66e783000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000003e711b80000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000003e6b1b23900000000000000000000000000000000000000000000000000000003e711b800000000000000000000000000af0b0000f0210d0f421f0009c72406703b50506b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00d00caca0000000000000000000000000013370000000063f50dfb000000000000001f00000000000000000000000063f50da20000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001beb5fbe9aa7694028216b8d81e613a41a9cf8b9135729d33acf77a692c4b0123547884cb6bae49c9ac885204ae11ce6fd4fff3961c04be142933b0c1b2e99072d869584cd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ebba8e3ba63f50e10"
 | 
			
		||||
        );
 | 
			
		||||
        emit log_named_bytes("", result);
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								contracts/zero-ex/contracts/scripts/Deploy.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								contracts/zero-ex/contracts/scripts/Deploy.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "forge-std/Script.sol";
 | 
			
		||||
import "src/features/DCAFeature.sol";
 | 
			
		||||
import "src/IZeroEx.sol";
 | 
			
		||||
import "src/ZeroEx.sol";
 | 
			
		||||
 | 
			
		||||
contract DeployDCAFeature is Test, Script {
 | 
			
		||||
    ZeroEx public ZERO_EX = ZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF);
 | 
			
		||||
    IZeroEx public IZERO_EX = IZeroEx(address(ZERO_EX));
 | 
			
		||||
 | 
			
		||||
    function setUp() public {}
 | 
			
		||||
 | 
			
		||||
    function run() public {
 | 
			
		||||
        vm.startBroadcast(IZERO_EX.owner());
 | 
			
		||||
 | 
			
		||||
        DCAFeature feature = new DCAFeature(address(ZERO_EX));
 | 
			
		||||
 | 
			
		||||
        IZERO_EX.migrate(address(feature), abi.encodeWithSelector(DCAFeature.migrate.selector), IZERO_EX.owner());
 | 
			
		||||
 | 
			
		||||
        vm.stopBroadcast();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								contracts/zero-ex/contracts/scripts/TestDeploy.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								contracts/zero-ex/contracts/scripts/TestDeploy.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "forge-std/Script.sol";
 | 
			
		||||
import "src/features/DCAFeature.sol";
 | 
			
		||||
import "src/features/interfaces/IDCAFeature.sol";
 | 
			
		||||
import "src/IZeroEx.sol";
 | 
			
		||||
import "src/ZeroEx.sol";
 | 
			
		||||
 | 
			
		||||
contract TestDeploy is Test, Script {
 | 
			
		||||
    ZeroEx public ZERO_EX = ZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF);
 | 
			
		||||
    IZeroEx public IZERO_EX = IZeroEx(address(ZERO_EX));
 | 
			
		||||
 | 
			
		||||
    function setUp() public {}
 | 
			
		||||
 | 
			
		||||
    function run() public {
 | 
			
		||||
        uint256 signerPrivateKey = 0xA11CE;
 | 
			
		||||
        address signer = vm.addr(signerPrivateKey);
 | 
			
		||||
 | 
			
		||||
        IDCAFeature.DCAData memory dcaData = IDCAFeature.DCAData({
 | 
			
		||||
            buyToken: IERC20Token(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2),
 | 
			
		||||
            sellToken: IERC20Token(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48),
 | 
			
		||||
            sellAmount: 100,
 | 
			
		||||
            interval: 600,
 | 
			
		||||
            numFills: 12,
 | 
			
		||||
            startTime: block.timestamp,
 | 
			
		||||
            signer: payable(signer)
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        bytes32 dcahash = IDCAFeature(address(ZERO_EX)).getDCAHash(dcaData);
 | 
			
		||||
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, dcahash);
 | 
			
		||||
 | 
			
		||||
        LibSignature.Signature memory signature = LibSignature.Signature({
 | 
			
		||||
            signatureType: LibSignature.SignatureType.EIP712,
 | 
			
		||||
            v: v,
 | 
			
		||||
            r: r,
 | 
			
		||||
            s: s
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](0);
 | 
			
		||||
 | 
			
		||||
        bytes memory swapCalldata = abi.encodeWithSelector(
 | 
			
		||||
            IZERO_EX.transformERC20.selector,
 | 
			
		||||
            dcaData.sellToken,
 | 
			
		||||
            dcaData.buyToken,
 | 
			
		||||
            1e18,
 | 
			
		||||
            1e18,
 | 
			
		||||
            transformations
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        IDCAFeature(address(ZERO_EX)).fillDCATransaction(dcaData, signature, swapCalldata);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										284
									
								
								contracts/zero-ex/contracts/src/features/DCAFeature.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								contracts/zero-ex/contracts/src/features/DCAFeature.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,284 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "../fixins/FixinEIP712.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IDCAFeature.sol";
 | 
			
		||||
import "./libs/LibSignature.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "./interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev DCA feature.
 | 
			
		||||
contract DCAFeature is IFeature, IDCAFeature, FixinCommon, FixinEIP712 {
 | 
			
		||||
    using LibBytesV06 for bytes;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Describes the state of the DCA.
 | 
			
		||||
    struct ExecuteState {
 | 
			
		||||
        // Hash of the DCA order.
 | 
			
		||||
        bytes32 hash;
 | 
			
		||||
        // The DCA order data;
 | 
			
		||||
        DCAData dca;
 | 
			
		||||
        // The DCA signature (by `dca.signer`).
 | 
			
		||||
        LibSignature.Signature signature;
 | 
			
		||||
        // The calldata to fill for the current iteration of the DCA.
 | 
			
		||||
        bytes swapCalldata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Arguments for a `TransformERC20.transformERC20()` call.
 | 
			
		||||
    struct ExternalTransformERC20Args {
 | 
			
		||||
        IERC20Token inputToken;
 | 
			
		||||
        IERC20Token outputToken;
 | 
			
		||||
        uint256 inputTokenAmount;
 | 
			
		||||
        uint256 minOutputTokenAmount;
 | 
			
		||||
        ITransformERC20Feature.Transformation[] transformations;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Name of this feature.
 | 
			
		||||
    string public constant override FEATURE_NAME = "DCA";
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
 | 
			
		||||
    /// @dev EIP712 typehash of the `DCAData` struct.
 | 
			
		||||
    bytes32 public constant DCA_DATA_TYPEHASH =
 | 
			
		||||
        keccak256(
 | 
			
		||||
            "DCAData("
 | 
			
		||||
            "address buyToken,"
 | 
			
		||||
            "address sellToken,"
 | 
			
		||||
            "uint256 sellAmount,"
 | 
			
		||||
            "uint256 interval,"
 | 
			
		||||
            "uint256 numFills,"
 | 
			
		||||
            "uint256 startTime,"
 | 
			
		||||
            "address signer"
 | 
			
		||||
            ")"
 | 
			
		||||
        );
 | 
			
		||||
    /// @dev number of fills executed per DCA order.
 | 
			
		||||
    mapping(bytes32 => uint256) public numFilled;
 | 
			
		||||
 | 
			
		||||
    constructor(address zeroExAddress) public FixinCommon() FixinEIP712(zeroExAddress) {}
 | 
			
		||||
 | 
			
		||||
    function migrate() external returns (bytes4 success) {
 | 
			
		||||
        _registerFeatureFunction(this.fillDCATransaction.selector);
 | 
			
		||||
        _registerFeatureFunction(this.getDCAHash.selector);
 | 
			
		||||
        return LibMigrate.MIGRATE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function fillDCATransaction(
 | 
			
		||||
        DCAData calldata dcaData,
 | 
			
		||||
        LibSignature.Signature calldata signature,
 | 
			
		||||
        bytes calldata swapCallData
 | 
			
		||||
    ) public override returns (bytes memory returnResult) {
 | 
			
		||||
        ExecuteState memory state;
 | 
			
		||||
        state.dca = dcaData;
 | 
			
		||||
        state.hash = getDCAHash(dcaData);
 | 
			
		||||
        state.signature = signature;
 | 
			
		||||
        state.swapCalldata = swapCallData;
 | 
			
		||||
 | 
			
		||||
        returnResult = _fillDCATransaction(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the EIP712 hash of a dca order.
 | 
			
		||||
    /// @param dca The DCA order.
 | 
			
		||||
    /// @return dcaHash the EIP712 hash of 'dca'.
 | 
			
		||||
    function getDCAHash(DCAData memory dca) public view override returns (bytes32 dcaHash) {
 | 
			
		||||
        return
 | 
			
		||||
            _getEIP712Hash(
 | 
			
		||||
                keccak256(
 | 
			
		||||
                    abi.encode(
 | 
			
		||||
                        DCA_DATA_TYPEHASH,
 | 
			
		||||
                        dca.buyToken,
 | 
			
		||||
                        dca.sellToken,
 | 
			
		||||
                        dca.sellAmount,
 | 
			
		||||
                        dca.interval,
 | 
			
		||||
                        dca.numFills,
 | 
			
		||||
                        dca.startTime,
 | 
			
		||||
                        dca.signer
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _fillDCATransaction(ExecuteState memory state) private returns (bytes memory returnResult) {
 | 
			
		||||
        _validateDCATransaction(state);
 | 
			
		||||
 | 
			
		||||
        // get balances of sellToken and buyToken before we execute calldata
 | 
			
		||||
        uint256 sellTokenBalanceBefore = state.dca.sellToken.balanceOf(state.dca.signer);
 | 
			
		||||
        uint256 buyTokenBalanceBefore = state.dca.buyToken.balanceOf(state.dca.signer);
 | 
			
		||||
 | 
			
		||||
        // execute the calldata
 | 
			
		||||
        bytes4 selector = state.swapCalldata.readBytes4(0);
 | 
			
		||||
        if (selector == ITransformERC20Feature.transformERC20.selector) {
 | 
			
		||||
            returnResult = _executeTransformERC20Call(state);
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("Unsupported swap function");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // get the balances of the sellToken and buyToken after we execute the calldata
 | 
			
		||||
        uint256 sellTokenBalanceAfter = state.dca.sellToken.balanceOf(state.dca.signer);
 | 
			
		||||
        uint256 buyTokenBalanceAfter = state.dca.buyToken.balanceOf(state.dca.signer);
 | 
			
		||||
        // validate deltas
 | 
			
		||||
        if (sellTokenBalanceAfter > sellTokenBalanceBefore) {
 | 
			
		||||
            revert("Sell token balance increased");
 | 
			
		||||
        }
 | 
			
		||||
        if (sellTokenBalanceBefore - sellTokenBalanceAfter != state.dca.sellAmount) {
 | 
			
		||||
            revert("Sell token balance delta does not match sell amount");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (buyTokenBalanceAfter < buyTokenBalanceBefore) {
 | 
			
		||||
            revert("Buy token balance decreased");
 | 
			
		||||
        }
 | 
			
		||||
        // TODO query oracle to ensure minslippage is achieved
 | 
			
		||||
 | 
			
		||||
        // update storage to show that we have executed the order
 | 
			
		||||
        numFilled[state.hash] += 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _validateDCATransaction(ExecuteState memory state) private view {
 | 
			
		||||
        // validate that the signature
 | 
			
		||||
        if (LibSignature.getSignerOfHash(state.hash, state.signature) != state.dca.signer) {
 | 
			
		||||
            LibSignatureRichErrors
 | 
			
		||||
                .SignatureValidationError(
 | 
			
		||||
                    LibSignatureRichErrors.SignatureValidationErrorCodes.WRONG_SIGNER,
 | 
			
		||||
                    state.hash,
 | 
			
		||||
                    state.dca.signer,
 | 
			
		||||
                    // TODO: Remove this field from SignatureValidationError
 | 
			
		||||
                    //       when rich reverts are part of the protocol repo.
 | 
			
		||||
                    ""
 | 
			
		||||
                )
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // check if all DCA orders have been executed already
 | 
			
		||||
        if (numFilled[state.hash] == state.dca.numFills) {
 | 
			
		||||
            revert("All DCA orders have been executed already");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check that DCA order is within the right time window
 | 
			
		||||
        uint256 endTime = state.dca.startTime + (state.dca.interval * state.dca.numFills);
 | 
			
		||||
        if (block.timestamp < state.dca.startTime || block.timestamp > endTime) {
 | 
			
		||||
            revert("Invalid time window");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint256 currTime = block.timestamp;
 | 
			
		||||
        uint256 currFill = (state.dca.numFills * (currTime - state.dca.startTime)) / (endTime - state.dca.startTime); // zero-indexed
 | 
			
		||||
        uint256 currWindowMidpoint = ((currFill + 1) * (endTime - state.dca.startTime)) / state.dca.numFills;
 | 
			
		||||
        currWindowMidpoint = currWindowMidpoint + state.dca.startTime;
 | 
			
		||||
        uint256 halfWindowSizeSeconds = 150; // 2.5 minutes
 | 
			
		||||
 | 
			
		||||
        uint256 currWindowStart = currWindowMidpoint < halfWindowSizeSeconds
 | 
			
		||||
            ? 0
 | 
			
		||||
            : currWindowMidpoint - halfWindowSizeSeconds;
 | 
			
		||||
        uint256 currWindowEnd = currWindowMidpoint + halfWindowSizeSeconds;
 | 
			
		||||
 | 
			
		||||
        if (currTime < currWindowStart || currTime > currWindowEnd) {
 | 
			
		||||
            console.log(
 | 
			
		||||
                "currTime=%d, currWindowMidpoint=%d, halfWindow=%d",
 | 
			
		||||
                currTime,
 | 
			
		||||
                currWindowMidpoint,
 | 
			
		||||
                halfWindowSizeSeconds
 | 
			
		||||
            );
 | 
			
		||||
            revert("Invalid time window 2");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `ITransformERC20Feature.transformERC20()` meta-transaction call
 | 
			
		||||
    ///      by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `ITransformERC20Feature._transformERC20()` variant, where we can override
 | 
			
		||||
    ///      the taker address.
 | 
			
		||||
    function _executeTransformERC20Call(ExecuteState memory state) private returns (bytes memory returnResult) {
 | 
			
		||||
        // HACK(dorothy-zbornak): `abi.decode()` with the individual args
 | 
			
		||||
        // will cause a stack overflow. But we can prefix the call data with an
 | 
			
		||||
        // offset to transform it into the encoding for the equivalent single struct arg,
 | 
			
		||||
        // since decoding a single struct arg consumes far less stack space than
 | 
			
		||||
        // decoding multiple struct args.
 | 
			
		||||
 | 
			
		||||
        // Where the encoding for multiple args (with the selector ommitted)
 | 
			
		||||
        // would typically look like:
 | 
			
		||||
        // | argument                 |  offset |
 | 
			
		||||
        // |--------------------------|---------|
 | 
			
		||||
        // | inputToken               |       0 |
 | 
			
		||||
        // | outputToken              |      32 |
 | 
			
		||||
        // | inputTokenAmount         |      64 |
 | 
			
		||||
        // | minOutputTokenAmount     |      96 |
 | 
			
		||||
        // | transformations (offset) |     128 | = 32
 | 
			
		||||
        // | transformations (data)   |     160 |
 | 
			
		||||
 | 
			
		||||
        // We will ABI-decode a single struct arg copy with the layout:
 | 
			
		||||
        // | argument                 |  offset |
 | 
			
		||||
        // |--------------------------|---------|
 | 
			
		||||
        // | (arg 1 offset)           |       0 | = 32
 | 
			
		||||
        // | inputToken               |      32 |
 | 
			
		||||
        // | outputToken              |      64 |
 | 
			
		||||
        // | inputTokenAmount         |      96 |
 | 
			
		||||
        // | minOutputTokenAmount     |     128 |
 | 
			
		||||
        // | transformations (offset) |     160 | = 32
 | 
			
		||||
        // | transformations (data)   |     192 |
 | 
			
		||||
 | 
			
		||||
        ExternalTransformERC20Args memory args;
 | 
			
		||||
        {
 | 
			
		||||
            bytes memory encodedStructArgs = new bytes(state.swapCalldata.length - 4 + 32);
 | 
			
		||||
            // Copy the args data from the original, after the new struct offset prefix.
 | 
			
		||||
            bytes memory fromCallData = state.swapCalldata;
 | 
			
		||||
            assert(fromCallData.length >= 160);
 | 
			
		||||
            uint256 fromMem;
 | 
			
		||||
            uint256 toMem;
 | 
			
		||||
            assembly {
 | 
			
		||||
                // Prefix the calldata with a struct offset,
 | 
			
		||||
                // which points to just one word over.
 | 
			
		||||
                mstore(add(encodedStructArgs, 32), 32)
 | 
			
		||||
                // Copy everything after the selector.
 | 
			
		||||
                fromMem := add(fromCallData, 36)
 | 
			
		||||
                // Start copying after the struct offset.
 | 
			
		||||
                toMem := add(encodedStructArgs, 64)
 | 
			
		||||
            }
 | 
			
		||||
            LibBytesV06.memCopy(toMem, fromMem, fromCallData.length - 4);
 | 
			
		||||
            // Decode call args for `ITransformERC20Feature.transformERC20()` as a struct.
 | 
			
		||||
            args = abi.decode(encodedStructArgs, (ExternalTransformERC20Args));
 | 
			
		||||
        }
 | 
			
		||||
        // Call `ITransformERC20Feature._transformERC20()` (internal variant).
 | 
			
		||||
        return
 | 
			
		||||
            _callSelf(
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    ITransformERC20Feature._transformERC20.selector,
 | 
			
		||||
                    ITransformERC20Feature.TransformERC20Args({
 | 
			
		||||
                        taker: state.dca.signer, // taker is mtx signer
 | 
			
		||||
                        inputToken: args.inputToken,
 | 
			
		||||
                        outputToken: args.outputToken,
 | 
			
		||||
                        inputTokenAmount: args.inputTokenAmount,
 | 
			
		||||
                        minOutputTokenAmount: args.minOutputTokenAmount,
 | 
			
		||||
                        transformations: args.transformations,
 | 
			
		||||
                        useSelfBalance: false,
 | 
			
		||||
                        recipient: state.dca.signer
 | 
			
		||||
                    })
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Make an arbitrary internal, meta-transaction call.
 | 
			
		||||
    ///      Warning: Do not let unadulterated `callData` into this function.
 | 
			
		||||
    function _callSelf(bytes memory callData) private returns (bytes memory returnResult) {
 | 
			
		||||
        bool success;
 | 
			
		||||
        (success, returnResult) = address(this).call(callData);
 | 
			
		||||
        if (!success) {
 | 
			
		||||
            console.logBytes(returnResult);
 | 
			
		||||
            revert("Swap execution failed ");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,47 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev DCA feature.
 | 
			
		||||
interface IDCAFeature {
 | 
			
		||||
    struct DCAData {
 | 
			
		||||
        // The token to buy.
 | 
			
		||||
        IERC20Token buyToken;
 | 
			
		||||
        // The token to sell.
 | 
			
		||||
        IERC20Token sellToken;
 | 
			
		||||
        // The amount of sellToken to sell.
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        // The amount of time between each fill in seconds.
 | 
			
		||||
        uint256 interval;
 | 
			
		||||
        // The number of fills to execute.
 | 
			
		||||
        uint256 numFills;
 | 
			
		||||
        // The start time of the DCA order in Unix epoch seconds.
 | 
			
		||||
        uint256 startTime;
 | 
			
		||||
        // Signer of the DCA. On whose behalf to execute the DCA.
 | 
			
		||||
        address payable signer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function fillDCATransaction(
 | 
			
		||||
        DCAData calldata dcaData,
 | 
			
		||||
        LibSignature.Signature calldata signature,
 | 
			
		||||
        bytes calldata swapCallData
 | 
			
		||||
    ) external returns (bytes memory returnResult);
 | 
			
		||||
 | 
			
		||||
    function getDCAHash(DCAData calldata dcaData) external view returns (bytes32 dcaHash);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										115
									
								
								contracts/zero-ex/tests/DCATest.t.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								contracts/zero-ex/tests/DCATest.t.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "forge-std/StdUtils.sol";
 | 
			
		||||
import "./utils/LocalTest.sol";
 | 
			
		||||
import "../contracts/src/features/DCAFeature.sol";
 | 
			
		||||
import "../contracts/src/features/interfaces/IDCAFeature.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "../contracts/src/fixins/FixinEIP712.sol";
 | 
			
		||||
import "../contracts/src/features/libs/LibSignature.sol";
 | 
			
		||||
 | 
			
		||||
contract DCAFeatureTest is LocalTest {
 | 
			
		||||
    function test_validateSignature() public {
 | 
			
		||||
        uint256 signerPrivateKey = 0xA11CE;
 | 
			
		||||
        address signer = vm.addr(signerPrivateKey);
 | 
			
		||||
 | 
			
		||||
        IDCAFeature.DCAData memory dcaData = IDCAFeature.DCAData({
 | 
			
		||||
            buyToken: IERC20Token(address(0)),
 | 
			
		||||
            sellToken: IERC20Token(address(0)),
 | 
			
		||||
            sellAmount: 100,
 | 
			
		||||
            interval: 100,
 | 
			
		||||
            numFills: 8,
 | 
			
		||||
            startTime: block.timestamp,
 | 
			
		||||
            signer: payable(signer)
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        bytes32 dcaHash = zeroExDeployed.features.dcaFeature.getDCAHash(dcaData);
 | 
			
		||||
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, dcaHash);
 | 
			
		||||
 | 
			
		||||
        LibSignature.Signature memory signature = LibSignature.Signature({
 | 
			
		||||
            signatureType: LibSignature.SignatureType.EIP712,
 | 
			
		||||
            v: v,
 | 
			
		||||
            r: r,
 | 
			
		||||
            s: s
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertEq(LibSignature.getSignerOfHash(dcaHash, signature), dcaData.signer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function test_checkNumFilled() public {
 | 
			
		||||
        // check that if user signed order to execute order two times, we expect
 | 
			
		||||
        // a revert on the third try
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function test_timeWindow() public {
 | 
			
		||||
        // spoof the blockchain timestmap and expect a revert if we're outside
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function test_dcaSwap() public {
 | 
			
		||||
        uint256 signerPrivateKey = 0xA11CE;
 | 
			
		||||
        address signer = vm.addr(signerPrivateKey);
 | 
			
		||||
 | 
			
		||||
        IDCAFeature.DCAData memory dcaData = IDCAFeature.DCAData({
 | 
			
		||||
            // buyToken: IERC20Token(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2),
 | 
			
		||||
            // sellToken: IERC20Token(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48),
 | 
			
		||||
            buyToken: zrx,
 | 
			
		||||
            sellToken: dai,
 | 
			
		||||
            sellAmount: 100,
 | 
			
		||||
            interval: 600,
 | 
			
		||||
            numFills: 12,
 | 
			
		||||
            startTime: block.timestamp,
 | 
			
		||||
            signer: payable(signer)
 | 
			
		||||
        });
 | 
			
		||||
        vm.warp(600); // warp the blockchain 10 minutes into the future
 | 
			
		||||
 | 
			
		||||
        bytes32 dcaHash = zeroExDeployed.features.dcaFeature.getDCAHash(dcaData);
 | 
			
		||||
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, dcaHash);
 | 
			
		||||
 | 
			
		||||
        LibSignature.Signature memory signature = LibSignature.Signature({
 | 
			
		||||
            signatureType: LibSignature.SignatureType.EIP712,
 | 
			
		||||
            v: v,
 | 
			
		||||
            r: r,
 | 
			
		||||
            s: s
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](1);
 | 
			
		||||
        transformations[0] = ITransformERC20Feature.Transformation(
 | 
			
		||||
            uint32(transformerNonce),
 | 
			
		||||
            abi.encode(address(dcaData.sellToken), address(dcaData.buyToken), 0, 1e18, 0)
 | 
			
		||||
        );
 | 
			
		||||
        console.log(transformerNonce);
 | 
			
		||||
 | 
			
		||||
        _mintTo(address(dcaData.sellToken), signer, 1e18);
 | 
			
		||||
        vm.prank(signer);
 | 
			
		||||
        dcaData.sellToken.approve(address(zeroExDeployed.zeroEx), 1e18);
 | 
			
		||||
 | 
			
		||||
        bytes memory swapCalldata = abi.encodeWithSelector(
 | 
			
		||||
            zeroExDeployed.zeroEx.transformERC20.selector,
 | 
			
		||||
            dcaData.sellToken,
 | 
			
		||||
            dcaData.buyToken,
 | 
			
		||||
            1e18,
 | 
			
		||||
            1e18,
 | 
			
		||||
            transformations
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assertEq(dai.balanceOf(signer), 1e18);
 | 
			
		||||
 | 
			
		||||
        IDCAFeature(address(zeroExDeployed.zeroEx)).fillDCATransaction(dcaData, signature, swapCalldata);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -29,6 +29,7 @@ import "src/features/TransformERC20Feature.sol";
 | 
			
		||||
import "src/features/OtcOrdersFeature.sol";
 | 
			
		||||
import "src/features/MetaTransactionsFeature.sol";
 | 
			
		||||
import "src/features/MetaTransactionsFeatureV2.sol";
 | 
			
		||||
import "src/features/DCAFeature.sol";
 | 
			
		||||
import "src/features/nft_orders/ERC1155OrdersFeature.sol";
 | 
			
		||||
import "src/features/nft_orders/ERC721OrdersFeature.sol";
 | 
			
		||||
import "src/features/UniswapFeature.sol";
 | 
			
		||||
@@ -70,6 +71,7 @@ contract DeployZeroEx is Test {
 | 
			
		||||
        TransformERC20Feature transformERC20Feature;
 | 
			
		||||
        MetaTransactionsFeature metaTransactionsFeature;
 | 
			
		||||
        MetaTransactionsFeatureV2 metaTransactionsFeatureV2;
 | 
			
		||||
        DCAFeature dcaFeature;
 | 
			
		||||
        ERC1155OrdersFeature erc1155OrdersFeature;
 | 
			
		||||
        ERC721OrdersFeature erc721OrdersFeature;
 | 
			
		||||
        MultiplexFeature multiplexFeature;
 | 
			
		||||
@@ -139,6 +141,7 @@ contract DeployZeroEx is Test {
 | 
			
		||||
            "MetaTransactionsFeatureV2",
 | 
			
		||||
            address(ZERO_EX_DEPLOYED.features.metaTransactionsFeatureV2)
 | 
			
		||||
        );
 | 
			
		||||
        emit log_named_address("DCAFeature", address(ZERO_EX_DEPLOYED.features.dcaFeature));
 | 
			
		||||
        emit log_named_address("ERC1155OrdersFeature", address(ZERO_EX_DEPLOYED.features.erc1155OrdersFeature));
 | 
			
		||||
        emit log_named_address("ERC721OrdersFeature", address(ZERO_EX_DEPLOYED.features.erc721OrdersFeature));
 | 
			
		||||
        emit log_named_address("TransformERC20Feature", address(ZERO_EX_DEPLOYED.features.transformERC20Feature));
 | 
			
		||||
@@ -229,6 +232,8 @@ contract DeployZeroEx is Test {
 | 
			
		||||
            ZERO_EX_DEPLOY_CONFIG.sushiswapPairInitCodeHash
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        ZERO_EX_DEPLOYED.features.dcaFeature = new DCAFeature(address(ZERO_EX));
 | 
			
		||||
 | 
			
		||||
        initialMigration.initializeZeroEx(
 | 
			
		||||
            payable(address(this)),
 | 
			
		||||
            ZERO_EX,
 | 
			
		||||
@@ -285,6 +290,11 @@ contract DeployZeroEx is Test {
 | 
			
		||||
            abi.encodeWithSelector(MetaTransactionsFeatureV2.migrate.selector),
 | 
			
		||||
            address(this)
 | 
			
		||||
        );
 | 
			
		||||
        IZERO_EX.migrate(
 | 
			
		||||
            address(ZERO_EX_DEPLOYED.features.dcaFeature),
 | 
			
		||||
            abi.encodeWithSelector(DCAFeature.migrate.selector),
 | 
			
		||||
            address(this)
 | 
			
		||||
        );
 | 
			
		||||
        IZERO_EX.migrate(
 | 
			
		||||
            address(ZERO_EX_DEPLOYED.features.erc1155OrdersFeature),
 | 
			
		||||
            abi.encodeWithSelector(ERC1155OrdersFeature.migrate.selector),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user