working bridge Fills through weth transformer
This commit is contained in:
		
				
					committed by
					
						
						elenadimitrova
					
				
			
			
				
	
			
			
			
						parent
						
							cea47f5719
						
					
				
				
					commit
					bf3e9991d1
				
			@@ -209,7 +209,6 @@ contract FillQuoteTransformer is Transformer {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        state.ethRemaining = address(this).balance;
 | 
			
		||||
 | 
			
		||||
        // Fill the orders.
 | 
			
		||||
        for (uint256 i = 0; i < data.fillSequence.length; ++i) {
 | 
			
		||||
            // Check if we've hit our targets.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,207 +0,0 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2022 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 "src/IZeroEx.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.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/transformers/bridges/EthereumBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/PolygonBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/ArbitrumBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/OptimismBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/AvalancheBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/FantomBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/BSCBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/CeloBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/IBridgeAdapter.sol";
 | 
			
		||||
import "src/features/OtcOrdersFeature.sol";
 | 
			
		||||
import "forge-std/StdJson.sol";
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "./utils/ForkUtils.sol";
 | 
			
		||||
import "./utils/TestUtils.sol";
 | 
			
		||||
 | 
			
		||||
contract OtcBridgeSettlement is 
 | 
			
		||||
  TestUtils,
 | 
			
		||||
  ForkUtils
 | 
			
		||||
{
 | 
			
		||||
  IBridgeAdapter bridgeAdapter;
 | 
			
		||||
  FillQuoteTransformer fillQuoteTransformer;
 | 
			
		||||
  OtcOrdersFeature otcOrdersFeature;
 | 
			
		||||
  IZeroEx IZERO_EX;
 | 
			
		||||
    function createBridgeAdapter(IEtherTokenV06 weth) public returns(IBridgeAdapter bridgeAdapter) {
 | 
			
		||||
      uint chainId;
 | 
			
		||||
 | 
			
		||||
      assembly {
 | 
			
		||||
        chainId := chainid()
 | 
			
		||||
      }
 | 
			
		||||
      if(chainId == 1) {return IBridgeAdapter(new EthereumBridgeAdapter(weth));}
 | 
			
		||||
      else if( chainId == 56){ return IBridgeAdapter(new BSCBridgeAdapter(weth));}
 | 
			
		||||
      else if( chainId == 137){return IBridgeAdapter(new PolygonBridgeAdapter(weth));}
 | 
			
		||||
      else if( chainId == 43114){return IBridgeAdapter(new AvalancheBridgeAdapter(weth));}
 | 
			
		||||
      else if( chainId == 250){return IBridgeAdapter(new FantomBridgeAdapter(weth));}
 | 
			
		||||
      else if( chainId == 10){return IBridgeAdapter(new OptimismBridgeAdapter(weth));}
 | 
			
		||||
      else if( chainId == 42161){return IBridgeAdapter(new ArbitrumBridgeAdapter(weth));}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createFillQuoteTransformer(IBridgeAdapter bridgeAdapter, IZeroEx exchangeProxy) public returns (FillQuoteTransformer fqt){
 | 
			
		||||
      return new FillQuoteTransformer(bridgeAdapter, exchangeProxy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function deployAndLabel(TokenAddresses memory tokens, Addresses memory contracts) public{
 | 
			
		||||
      bridgeAdapter = createBridgeAdapter(IEtherTokenV06(tokens.WrappedNativeToken));
 | 
			
		||||
      fillQuoteTransformer = createFillQuoteTransformer(bridgeAdapter, IZeroEx(contracts.exchangeProxy));
 | 
			
		||||
      otcOrdersFeature = new OtcOrdersFeature(contracts.exchangeProxy, tokens.WrappedNativeToken);
 | 
			
		||||
 | 
			
		||||
      vm.prank(IZeroEx(contracts.exchangeProxy).owner());
 | 
			
		||||
      IZeroEx(contracts.exchangeProxy).migrate(
 | 
			
		||||
        address(otcOrdersFeature),
 | 
			
		||||
        abi.encodeWithSelector(otcOrdersFeature.migrate.selector, address(otcOrdersFeature)),
 | 
			
		||||
        address(this)
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      IZERO_EX = IZeroEx(contracts.exchangeProxy);
 | 
			
		||||
 | 
			
		||||
      vm.label(address(bridgeAdapter), "zeroEx/BridgeAdapter");
 | 
			
		||||
      vm.label(address(fillQuoteTransformer), "zeroEx/FillQuoteTransformer");
 | 
			
		||||
      vm.label(address(contracts.exchangeProxy), "zeroEx/ExchangeProxy");
 | 
			
		||||
      vm.label(address(otcOrdersFeature), "zeroEx/OtcOrdersFeature");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _fillOtcOrder(string memory chainName, string memory chainId, TokenAddresses memory tokens, Addresses memory contracts, LiquiditySources memory sources) public returns (uint boughtAmount) {
 | 
			
		||||
        log_named_address("WETH/NATIVE_ASSET", address(tokens.WrappedNativeToken));
 | 
			
		||||
        log_named_address("EP", address(contracts.exchangeProxy));
 | 
			
		||||
        //IBridgeAdapter temp = FillQuoteTransformer(contracts.transformers.fillQuoteTransformer).bridgeAdapter();
 | 
			
		||||
        //log_named_address("Bridge Adapter", address(temp));
 | 
			
		||||
        uint256 _chainId;
 | 
			
		||||
        assembly {
 | 
			
		||||
            _chainId := chainid()
 | 
			
		||||
        }
 | 
			
		||||
        log_named_uint("ChainId", _chainId);
 | 
			
		||||
 | 
			
		||||
        deployAndLabel(tokens, contracts);
 | 
			
		||||
        
 | 
			
		||||
        buildTransform(tokens,contracts);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function buildTransform(TokenAddresses memory tokens, Addresses memory contracts) public {
 | 
			
		||||
        ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](2);
 | 
			
		||||
        // Use our cheeky search helper to find the nonce rather than hardcode it
 | 
			
		||||
        //  hint: it's 6 for WethTransformer and 22 for this FillQuoteTransformer
 | 
			
		||||
        transformations[0].deploymentNonce = _findTransformerNonce(address(contracts.transformers.wethTransformer), address(contracts.exchangeProxyTransformerDeployer));
 | 
			
		||||
        transformations[1].deploymentNonce = _findTransformerNonce(address(fillQuoteTransformer), address(contracts.exchangeProxyTransformerDeployer));
 | 
			
		||||
 | 
			
		||||
        transformations[0].data = abi.encode(LibERC20Transformer.ETH_TOKEN_ADDRESS, 1e9);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Set up the FillQuoteTransformer data
 | 
			
		||||
        FillQuoteTransformer.TransformData memory fqtData;
 | 
			
		||||
        fqtData.side = FillQuoteTransformer.Side.Sell;
 | 
			
		||||
        // FQT deals with tokens, not ETH, so it needs a WETH transformer
 | 
			
		||||
        // to be applied beforehand
 | 
			
		||||
        fqtData.sellToken = IERC20TokenV06(address(tokens.WrappedNativeToken));
 | 
			
		||||
        fqtData.buyToken =  IERC20TokenV06(address(tokens.USDC));
 | 
			
		||||
        // the FQT has a sequence, e.g first RFQ then Limit then Bridge
 | 
			
		||||
        // since solidity doesn't support arrays of different types, this is one simple solution
 | 
			
		||||
        // We use a Bridge order type here as we will fill on UniswapV2
 | 
			
		||||
        fqtData.fillSequence = new FillQuoteTransformer.OrderType[](2);
 | 
			
		||||
        fqtData.fillSequence[0] = FillQuoteTransformer.OrderType.Bridge;
 | 
			
		||||
        fqtData.fillSequence[1] = FillQuoteTransformer.OrderType.Otc;
 | 
			
		||||
        // The amount to fill
 | 
			
		||||
        fqtData.fillAmount = 2e18;
 | 
			
		||||
        // Now let's set up an OTC fill
 | 
			
		||||
        fqtData.otcOrders = new FillQuoteTransformer.OtcOrderInfo[](1);
 | 
			
		||||
 | 
			
		||||
        LibNativeOrder.OtcOrder memory order;
 | 
			
		||||
        FillQuoteTransformer.OtcOrderInfo memory orderInfo;
 | 
			
		||||
        //build up the otc order info for a 0.1 weth swap to usdc
 | 
			
		||||
        order.makerToken = IERC20TokenV06(address(tokens.USDC));
 | 
			
		||||
        order.takerToken = IERC20TokenV06(address(tokens.WrappedNativeToken));
 | 
			
		||||
        order.makerAmount = 1e4;
 | 
			
		||||
        order.takerAmount = 1e18;
 | 
			
		||||
        order.maker = address(0xAc3c9f9a125F569a3112d1C60e008fA55e159B92);
 | 
			
		||||
        order.taker = address(0);
 | 
			
		||||
        order.txOrigin = address(tx.origin);
 | 
			
		||||
        order.expiryAndNonce = uint256(10414516026389248070289760349785577643365704380554799766852394287105);
 | 
			
		||||
 | 
			
		||||
        string memory mnemonic = "test test test test test test test test test test test junk";
 | 
			
		||||
        uint256 privateKey = vm.deriveKey(mnemonic, 0);
 | 
			
		||||
        address signer = vm.addr(privateKey);
 | 
			
		||||
        log_named_address("Signing with address", signer);
 | 
			
		||||
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey,IZeroEx(contracts.exchangeProxy).getOtcOrderHash(order));
 | 
			
		||||
        log_named_address("recoveredSigner", ecrecover(IZeroEx(contracts.exchangeProxy).getOtcOrderHash(order), v,r,s));
 | 
			
		||||
 | 
			
		||||
        orderInfo.signature.signatureType = LibSignature.SignatureType.EIP712;
 | 
			
		||||
        orderInfo.signature.v = v;
 | 
			
		||||
        orderInfo.signature.r = r;
 | 
			
		||||
        orderInfo.signature.s = s;
 | 
			
		||||
        
 | 
			
		||||
        emit log_named_address("Signer Of Hash", LibSignature.getSignerOfHash(IZeroEx(contracts.exchangeProxy).getOtcOrderHash(order), orderInfo.signature));
 | 
			
		||||
        orderInfo.maxTakerTokenFillAmount = 1e18;
 | 
			
		||||
        fqtData.otcOrders[0] = orderInfo;
 | 
			
		||||
        transformations[1].data = abi.encode(getBridgeOrder(fqtData));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //fillOrder(transformations);
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    function getBridgeOrder( FillQuoteTransformer.TransformData memory fqtData) public returns (FillQuoteTransformer.TransformData memory _data){
 | 
			
		||||
 | 
			
		||||
      fqtData.bridgeOrders = new IBridgeAdapter.BridgeOrder[](1);
 | 
			
		||||
      IBridgeAdapter.BridgeOrder memory bridgeOrder;
 | 
			
		||||
      bridgeOrder.source = bytes32(uint256(BridgeProtocols.UNISWAPV2) << 128);
 | 
			
		||||
      // How much we want to fill on this order, which can be different to the total
 | 
			
		||||
      // e.g 50/50 split this would be half
 | 
			
		||||
      bridgeOrder.takerTokenAmount = 1e18;
 | 
			
		||||
      // Set this low as the price of ETH/USDC can change
 | 
			
		||||
      bridgeOrder.makerTokenAmount = 1;
 | 
			
		||||
 | 
			
		||||
      address[] memory uniPath = new address[](2);
 | 
			
		||||
      uniPath[0] = address(tokens.WrappedNativeToken);
 | 
			
		||||
      uniPath[1] = address(tokens.USDC);
 | 
			
		||||
      bridgeOrder.bridgeData = abi.encode(address(sources.UniswapV2Router), uniPath);
 | 
			
		||||
      fqtData.bridgeOrders[0] = bridgeOrder;
 | 
			
		||||
      return (fqtData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function fillOrder(ITransformERC20Feature.Transformation[] memory _transformations) public {
 | 
			
		||||
    vm.deal(address(this), 5e19);
 | 
			
		||||
    IZERO_EX.transformERC20{value: 2e18}(
 | 
			
		||||
        // input token
 | 
			
		||||
        IERC20TokenV06(LibERC20Transformer.ETH_TOKEN_ADDRESS),
 | 
			
		||||
        // output token
 | 
			
		||||
        IERC20TokenV06(address(tokens.USDC)),
 | 
			
		||||
        // input token amount
 | 
			
		||||
        2e18,
 | 
			
		||||
        // min output token amount, set this low as ETH/USDC price will move
 | 
			
		||||
        1,
 | 
			
		||||
        // list of transform
 | 
			
		||||
        _transformations
 | 
			
		||||
    );
 | 
			
		||||
    // Hoollly heck we bought some USDC
 | 
			
		||||
    assertGt(tokens.USDC.balanceOf(address(this)), 0);
 | 
			
		||||
    emit log_named_uint("USDC bought", tokens.USDC.balanceOf(address(this)));
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										166
									
								
								contracts/zero-ex/contracts/test/foundry/OtcOrderTest.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								contracts/zero-ex/contracts/test/foundry/OtcOrderTest.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
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 "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";
 | 
			
		||||
import "forge-std/StdJson.sol";
 | 
			
		||||
 | 
			
		||||
contract ETHToERC20TransformTest is Test, ForkUtils, TestUtils {
 | 
			
		||||
    //use forge-std json library for strings
 | 
			
		||||
    using stdJson for string;
 | 
			
		||||
   
 | 
			
		||||
    //utility mapping to get chainId by name
 | 
			
		||||
    mapping(string => string) public chainsByChainId;
 | 
			
		||||
    //utility mapping to get indexingChainId by Chain
 | 
			
		||||
    mapping(string => string) public indexChainsByChain;
 | 
			
		||||
 | 
			
		||||
    string json;
 | 
			
		||||
 | 
			
		||||
    IBridgeAdapter bridgeAdapter;
 | 
			
		||||
    FillQuoteTransformer fillQuoteTransformer;
 | 
			
		||||
   
 | 
			
		||||
    /*//////////////////////////////////////////////////////////////
 | 
			
		||||
                                 Rpc Setup
 | 
			
		||||
    //////////////////////////////////////////////////////////////*/
 | 
			
		||||
    function setUp() public {
 | 
			
		||||
        //get out addresses.json file that defines contract addresses for each chain we are currently deployed on
 | 
			
		||||
        createForks();
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < chains.length; i++) {
 | 
			
		||||
            chainsByChainId[chains[i]] = chainIds[i];
 | 
			
		||||
            indexChainsByChain[chains[i]] = indexChainIds[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*//////////////////////////////////////////////////////////////
 | 
			
		||||
                                 Dispatch
 | 
			
		||||
    //////////////////////////////////////////////////////////////*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function testSwapEthForERC20OnUniswap() public {
 | 
			
		||||
        log_string("SwapEthForERC20OnUniswap");
 | 
			
		||||
        for (uint256 i = 0; i < chains.length; i++) {
 | 
			
		||||
            //skip fantom failing test
 | 
			
		||||
            if( i == 3 || i == 4 ){
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            vm.selectFork(forkIds[chains[i]]);
 | 
			
		||||
            log_named_string("  Selecting Fork On", chains[i]);
 | 
			
		||||
            labelAddresses(chains[i], indexChainsByChain[chains[i]], getTokens(i), getContractAddresses(i), getLiquiditySourceAddresses(i));
 | 
			
		||||
            swapOnUniswap(chains[i], indexChainsByChain[chains[i]], getTokens(i), getContractAddresses(i), getLiquiditySourceAddresses(i));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
   
 | 
			
		||||
    /*//////////////////////////////////////////////////////////////
 | 
			
		||||
                                 Settlement
 | 
			
		||||
    //////////////////////////////////////////////////////////////*/
 | 
			
		||||
 | 
			
		||||
    function swapOnUniswap(string memory chainName, string memory chainId, TokenAddresses memory tokens, Addresses memory addresses, LiquiditySources memory sources) public onlyForked {
 | 
			
		||||
        if(sources.UniswapV2Router != address(0)) {
 | 
			
		||||
        // Create our list of transformations, let's do WethTransformer and FillQuoteTransformer
 | 
			
		||||
        ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](2);
 | 
			
		||||
 | 
			
		||||
        createNewFQT(tokens.WrappedNativeToken, addresses.exchangeProxy, addresses.exchangeProxyTransformerDeployer);
 | 
			
		||||
 | 
			
		||||
        vm.label(address(fillQuoteTransformer), "zeroEx/FillQuoteTransformer");
 | 
			
		||||
        // Use our cheeky search helper to find the nonce rather than hardcode it
 | 
			
		||||
        //  hint: it's 6 for WethTransformer and 22 for this FillQuoteTransformer
 | 
			
		||||
        transformations[0].deploymentNonce = _findTransformerNonce(address(addresses.wethTransformer), address(addresses.exchangeProxyTransformerDeployer));
 | 
			
		||||
        transformations[1].deploymentNonce = _findTransformerNonce(address(fillQuoteTransformer), address(addresses.exchangeProxyTransformerDeployer));
 | 
			
		||||
 | 
			
		||||
        emit log_named_uint("           WethTransformer nonce", transformations[0].deploymentNonce);
 | 
			
		||||
        emit log_named_uint("           FillQuoteTransformer nonce", transformations[1].deploymentNonce);
 | 
			
		||||
 | 
			
		||||
        // Set the first transformation to transform ETH into WETH
 | 
			
		||||
        transformations[0].data = abi.encode(LibERC20Transformer.ETH_TOKEN_ADDRESS, 1e18);
 | 
			
		||||
 | 
			
		||||
        // Set up the FillQuoteTransformer data
 | 
			
		||||
        FillQuoteTransformer.TransformData memory fqtData;
 | 
			
		||||
        fqtData.side = FillQuoteTransformer.Side.Sell;
 | 
			
		||||
        // FQT deals with tokens, not ETH, so it needs a WETH transformer
 | 
			
		||||
        // to be applied beforehand
 | 
			
		||||
        fqtData.sellToken = IERC20TokenV06(address(tokens.WrappedNativeToken));
 | 
			
		||||
        fqtData.buyToken =  IERC20TokenV06(address(tokens.USDT));
 | 
			
		||||
        // the FQT has a sequence, e.g first RFQ then Limit then Bridge
 | 
			
		||||
        // since solidity doesn't support arrays of different types, this is one simple solution
 | 
			
		||||
        // We use a Bridge order type here as we will fill on UniswapV2
 | 
			
		||||
        fqtData.fillSequence = new FillQuoteTransformer.OrderType[](1);
 | 
			
		||||
        fqtData.fillSequence[0] = FillQuoteTransformer.OrderType.Bridge;
 | 
			
		||||
        // The amount to fill
 | 
			
		||||
        fqtData.fillAmount = 1e18;
 | 
			
		||||
        // Now let's set up a UniswapV2 fill
 | 
			
		||||
        fqtData.bridgeOrders = new IBridgeAdapter.BridgeOrder[](1);
 | 
			
		||||
        IBridgeAdapter.BridgeOrder memory order;
 | 
			
		||||
        // The ID is shifted so we can concat <PROTOCOL><NAME>
 | 
			
		||||
        // e.g <UniswapV2Protocol><UniswapV2>
 | 
			
		||||
        // or  <UniswapV2Protocol><SushiSwap> for forks
 | 
			
		||||
        order.source = bytes32(uint256(BridgeProtocols.UNISWAPV2) << 128);
 | 
			
		||||
        // How much we want to fill on this order, which can be different to the total
 | 
			
		||||
        // e.g 50/50 split this would be half
 | 
			
		||||
        order.takerTokenAmount = 1e18;
 | 
			
		||||
        // Set this low as the price of ETH/USDT can change
 | 
			
		||||
        order.makerTokenAmount = 1;
 | 
			
		||||
        // The data needed specifically for the source to fill,
 | 
			
		||||
        // e.g for UniswapV2 it is the router contract and a path. See MixinUniswapV2
 | 
			
		||||
        address[] memory uniPath = new address[](2);
 | 
			
		||||
        uniPath[0] = address(tokens.WrappedNativeToken);
 | 
			
		||||
        uniPath[1] = address(tokens.USDT);
 | 
			
		||||
        order.bridgeData = abi.encode(address(sources.UniswapV2Router), uniPath);
 | 
			
		||||
        fqtData.bridgeOrders[0] = order;
 | 
			
		||||
        // Now encode the FQT data into the transformation
 | 
			
		||||
        transformations[1].data = abi.encode(fqtData);
 | 
			
		||||
 | 
			
		||||
        vm.deal(address(this), 1e18);
 | 
			
		||||
        uint256 balanceETHBefore = address(this).balance;
 | 
			
		||||
        uint256 balanceERC20Before = IERC20TokenV06(tokens.USDT).balanceOf(address(this));
 | 
			
		||||
        
 | 
			
		||||
        IZeroEx(payable(addresses.exchangeProxy)).transformERC20{value: 1e18}(
 | 
			
		||||
            // input token
 | 
			
		||||
            IERC20TokenV06(LibERC20Transformer.ETH_TOKEN_ADDRESS),
 | 
			
		||||
            // output token
 | 
			
		||||
            IERC20TokenV06(address(tokens.USDT)),
 | 
			
		||||
            // input token amount
 | 
			
		||||
            1e18,
 | 
			
		||||
            // min output token amount
 | 
			
		||||
            1,
 | 
			
		||||
            // list of transform
 | 
			
		||||
            transformations
 | 
			
		||||
        );
 | 
			
		||||
        log_named_uint("        NativeAsset balance before", balanceETHBefore);
 | 
			
		||||
        log_named_uint("        ERC-20 balance before",  balanceERC20Before);
 | 
			
		||||
        log_named_uint("        NativeAsset balance after", balanceETHBefore - address(this).balance);
 | 
			
		||||
        log_named_uint("        ERC-20 balance after",  IERC20TokenV06(tokens.USDT).balanceOf(address(this)) - balanceERC20Before);
 | 
			
		||||
        assert(IERC20TokenV06(tokens.USDT).balanceOf(address(this)) > 0);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            log_string("    Liquidity Source Not available on this chain");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*//////////////////////////////////////////////////////////////
 | 
			
		||||
                                 HELPERS
 | 
			
		||||
    //////////////////////////////////////////////////////////////*/
 | 
			
		||||
 | 
			
		||||
    function createNewFQT(IEtherTokenV06 wrappedNativeToken, address payable exchangeProxy, address transformerDeployer) public {
 | 
			
		||||
        vm.startPrank(transformerDeployer);
 | 
			
		||||
 | 
			
		||||
        // deploy a new instance of the bridge adapter from the transformerDeployer
 | 
			
		||||
        bridgeAdapter = createBridgeAdapter(IEtherTokenV06(wrappedNativeToken));
 | 
			
		||||
        // deploy a new instance of the fill quote transformer from the transformerDeployer
 | 
			
		||||
        fillQuoteTransformer = new FillQuoteTransformer(IBridgeAdapter(bridgeAdapter), IZeroEx(exchangeProxy));
 | 
			
		||||
 | 
			
		||||
        vm.label(address(fillQuoteTransformer), "zeroEx/FillQuoteTransformer");
 | 
			
		||||
        vm.label(address(fillQuoteTransformer), "zeroEx/FillQuoteTransformer");
 | 
			
		||||
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,149 @@
 | 
			
		||||
{
 | 
			
		||||
    "1": {
 | 
			
		||||
        "zrxToken": "0xe41d2489571d322189246dafa5ebde1f4699f498",
 | 
			
		||||
        "etherToken": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
 | 
			
		||||
        "zeroExGovernor": "0x7d3455421bbc5ed534a83c88fd80387dc8271392",
 | 
			
		||||
        "zrxVault": "0xba7f8b5fb1b19c1211c5d49550fcd149177a5eaf",
 | 
			
		||||
        "staking": "0x2a17c35ff147b32f13f19f2e311446eeb02503f3",
 | 
			
		||||
        "stakingProxy": "0xa26e80e7dea86279c6d778d702cc413e6cffa777",
 | 
			
		||||
        "erc20BridgeProxy": "0x8ed95d1746bf1e4dab58d8ed4724f1ef95b20db0",
 | 
			
		||||
        "erc20BridgeSampler": "0xd8c38704c9937ea3312de29f824b4ad3450a5e61",
 | 
			
		||||
        "exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
 | 
			
		||||
        "exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
 | 
			
		||||
        "zrxTreasury": "0x0bb1810061c2f5b2088054ee184e6c79e1591101",
 | 
			
		||||
        "wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7",
 | 
			
		||||
        "payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e",
 | 
			
		||||
        "affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f",
 | 
			
		||||
        "fillQuoteTransformer": "0xd75a9019a2a1782ea670e4f4a55f04b43514ed53",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0xa9416ce1dbde8d331210c07b5c253d94ee4cc3fd"
 | 
			
		||||
    },
 | 
			
		||||
    "56": {
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0xccc9769c1a58766e79423a34b2cc5052d65c1983",
 | 
			
		||||
        "exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0x8224aa8fe5c9f07d5a59c735386ff6cc6aaeb568",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0xde7b2747624a647600fdb349184d0448ab954929",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "wethTransformer": "0xac3d95668c092e895cd83a9cbafe9c7d9906471f",
 | 
			
		||||
        "payTakerTransformer": "0x4f5e8ca2cadecd4a467ae441e4b03de4278a4574",
 | 
			
		||||
        "affiliateFeeTransformer": "0x1be34ab9b2acb5c4ddd89454bdce637967e65230",
 | 
			
		||||
        "fillQuoteTransformer": "0xbd7fd6e116fc8589bb658fba3a2cc6273050bcf2",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0x7f5c79ad1788573b1145f4651a248523c54f5d1f"
 | 
			
		||||
    },
 | 
			
		||||
    "137": {
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0x4d3e56c56a55d23fc7aa9a9ffad61631cf7d1ae6",
 | 
			
		||||
        "exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0xe6d9207df11c55bce2f7a189ae95e3222d5484d3",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0x4dd97080adf36103bd3db822f9d3c0e44890fd69",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "wethTransformer": "0xe309d011cc6f189a3e8dcba85922715a019fed38",
 | 
			
		||||
        "payTakerTransformer": "0x5ba7b9be86cda01cfbf56e0fb97184783be9dda1",
 | 
			
		||||
        "affiliateFeeTransformer": "0xbed27284b42e5684e987169cf1da09c5d6c49fa8",
 | 
			
		||||
        "fillQuoteTransformer": "0x01c082e47c8dc6dedd01e3fcb07bfd3eb72e044d",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0x4cd8f1c0df4d40fcc1e073845d5f6f4ed5cc8dab"
 | 
			
		||||
    },
 | 
			
		||||
    "43114": {
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0xca7bab1b2d1ec7d81710b7f9e2ab4e6788930588",
 | 
			
		||||
        "exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0xa60b57833dce6260f4f2411c811755dd980bc0a7",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0x8953c63d0858d286cc407cd6f8e26b9cbd02a511",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "wethTransformer": "0x9b8b52391071d71cd4ad1e61d7f273268fa34c6c",
 | 
			
		||||
        "payTakerTransformer": "0x898c6fde239d646c73f0a57e3570b6f86a3d62a3",
 | 
			
		||||
        "affiliateFeeTransformer": "0x34617b855411e52fbc05899435f44cbd0503022c",
 | 
			
		||||
        "fillQuoteTransformer": "0xcee9118bc14e1fe740c54c754b901629b322ee4f",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0x470ba89da18a6db6e8a0567b3c9214b960861857"
 | 
			
		||||
    },
 | 
			
		||||
    "250": {
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0xf760c5b88d970d6f97e64e264dac5a3767dafd74",
 | 
			
		||||
        "exchangeProxy": "0xdef189deaef76e379df891899eb5a00a94cbc250",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0x47f01db18a38261e4cb153bae6db7d3743acb33c",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xb4d961671cadfed687e040b076eee29840c142e5",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0xca64d4225804f2ae069760cb5ff2f1d8bac1c2f9",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "wethTransformer": "0x9b6aa8f26a92108e7d1f66373d757bb955112703",
 | 
			
		||||
        "payTakerTransformer": "0x32df54951d33d7460e15fa59b1fcc262183ce4c2",
 | 
			
		||||
        "affiliateFeeTransformer": "0x67efa679a4b56c38713d478e649c88247f4f8e88",
 | 
			
		||||
        "fillQuoteTransformer": "0xe40f81ef6e9c95ba04c659b8d032eab73152aafd",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0xe87d69b285005cc82b53b844322652c49ed64600"
 | 
			
		||||
    },
 | 
			
		||||
    "10": {
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0x4200000000000000000000000000000000000006",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0x6d506b2847df0c6f04d2628da1adaf4d8fb2e81b",
 | 
			
		||||
        "exchangeProxy": "0xdef1abe32c034e558cdd535791643c58a13acc10",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0x3a539ed6bd42de8fbaf3899fb490c792e153d647",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xa3128d9b7cca7d5af29780a56abeec12b05a6740",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "wethTransformer": "0x02ce7af6520e2862f961f5d7eda746642865179c",
 | 
			
		||||
        "payTakerTransformer": "0x085d10a34f14f6a631ea8ff7d016782ee3ffaa11",
 | 
			
		||||
        "affiliateFeeTransformer": "0x55cf1d7535250db75bf0190493f55781ee583553",
 | 
			
		||||
        "fillQuoteTransformer": "0x845c75a791cceb1a451f4ca5778c011226dda95c",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0xb11e14565dfbeb702dea9bc0cb47f1a8b32f4783"
 | 
			
		||||
    },
 | 
			
		||||
    "42161": {
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0x1fe80d5ad9464dba2d60b88e449305f184823f8a",
 | 
			
		||||
        "exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0x29f80c1f685e19ae1807063eda432f431ac623d0",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "wethTransformer": "0x10e968968f49dd66a5efeebbb2edcb9c49c4fc49",
 | 
			
		||||
        "payTakerTransformer": "0xae3e8cf7bf340d7084f312dfae2aa8b01c885b02",
 | 
			
		||||
        "affiliateFeeTransformer": "0x05a24978471869327904ea13da3c4322128e2aaa",
 | 
			
		||||
        "fillQuoteTransformer": "0x466b00a77662245c2cc7b093a7102a687afc16f3",
 | 
			
		||||
        "positiveSlippageFeeTransformer": "0xd56b9c014b45ed95e2a048a0c28121db30265f13"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
{
 | 
			
		||||
    "1": {
 | 
			
		||||
        "UniswapV2Router": "0xf164fc0ec4e93095b804a4795bbe1e041497b92a"
 | 
			
		||||
    },
 | 
			
		||||
    "56": {
 | 
			
		||||
        "UniswapV2Router": "0x10ed43c718714eb63d5aa57b78b54704e256024e"
 | 
			
		||||
    },
 | 
			
		||||
    "137": {
 | 
			
		||||
        "UniswapV2Router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506"
 | 
			
		||||
    },
 | 
			
		||||
    "43114": {
 | 
			
		||||
        "UniswapV2Router": "0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10"
 | 
			
		||||
    },
 | 
			
		||||
    "250": {
 | 
			
		||||
        "UniswapV2Router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506"
 | 
			
		||||
    },
 | 
			
		||||
    "10": {
 | 
			
		||||
        "UniswapV2Router": "0x0000000000000000000000000000000000000000"
 | 
			
		||||
    },
 | 
			
		||||
    "42161": {
 | 
			
		||||
        "UniswapV2Router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,44 @@
 | 
			
		||||
{
 | 
			
		||||
    "1": {
 | 
			
		||||
        "WrappedNativeToken": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
 | 
			
		||||
        "DAI": "0x6b175474e89094c44da98b954eedeac495271d0f",
 | 
			
		||||
        "USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
 | 
			
		||||
        "USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7"
 | 
			
		||||
    },
 | 
			
		||||
    "56": {
 | 
			
		||||
        "WrappedNativeToken": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
 | 
			
		||||
        "DAI": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3",
 | 
			
		||||
        "USDC": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d",
 | 
			
		||||
        "USDT": "0x55d398326f99059ff775485246999027b3197955"
 | 
			
		||||
    },
 | 
			
		||||
    "137": {
 | 
			
		||||
        "WrappedNativeToken": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270",
 | 
			
		||||
        "DAI": "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063",
 | 
			
		||||
        "USDC": "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
 | 
			
		||||
        "USDT": "0xc2132d05d31c914a87c6611c10748aeb04b58e8f"
 | 
			
		||||
    },
 | 
			
		||||
    "43114": {
 | 
			
		||||
        "WrappedNativeToken": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7",
 | 
			
		||||
        "DAI": "0xd586e7f844cea2f87f50152665bcbc2c279d8d70",
 | 
			
		||||
        "USDC": "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664",
 | 
			
		||||
        "USDT": "0xc7198437980c041c805A1EDcbA50c1Ce5db95118"
 | 
			
		||||
    },
 | 
			
		||||
    "250": {
 | 
			
		||||
        "WrappedNativeToken": "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83",
 | 
			
		||||
        "DAI": "0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e",
 | 
			
		||||
        "USDC": "0x04068da6c83afcfa0e13ba15a6696662335d5b75",
 | 
			
		||||
        "USDT": "0x049d68029688eabf473097a2fc38ef61633a3c7a"
 | 
			
		||||
    },
 | 
			
		||||
    "10": {
 | 
			
		||||
        "WrappedNativeToken": "0x4200000000000000000000000000000000000006",
 | 
			
		||||
        "DAI": "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1",
 | 
			
		||||
        "USDC": "0x7f5c764cbc14f9669b88837ca1490cca17c31607",
 | 
			
		||||
        "USDT": "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58"
 | 
			
		||||
    },
 | 
			
		||||
    "42161": {
 | 
			
		||||
        "WrappedNativeToken": "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
 | 
			
		||||
        "DAI": "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1",
 | 
			
		||||
        "USDC": "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8",
 | 
			
		||||
        "USDT": "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										111
									
								
								contracts/zero-ex/contracts/test/foundry/transformERC20Tests.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								contracts/zero-ex/contracts/test/foundry/transformERC20Tests.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
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 "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/transformers/bridges/EthereumBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/PolygonBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/ArbitrumBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/OptimismBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/AvalancheBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/FantomBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/CeloBridgeAdapter.sol";
 | 
			
		||||
import "src/features/OtcOrdersFeature.sol";
 | 
			
		||||
import "forge-std/StdJson.sol";
 | 
			
		||||
 | 
			
		||||
contract transformERC20Tests is Test, ForkUtils, TestUtils {
 | 
			
		||||
    //use forge-std json library for strings
 | 
			
		||||
    using stdJson for string;
 | 
			
		||||
   
 | 
			
		||||
    //utility mapping to get chainId by name
 | 
			
		||||
    mapping(string => string) public chainsByChainId;
 | 
			
		||||
    //utility mapping to get indexingChainId by Chain
 | 
			
		||||
    mapping(string => string) public indexChainsByChain;
 | 
			
		||||
 | 
			
		||||
    string json;
 | 
			
		||||
 | 
			
		||||
    function setUp() public {
 | 
			
		||||
        //get out addresses.json file that defines contract addresses for each chain we are currently deployed on
 | 
			
		||||
        string memory root = vm.projectRoot();
 | 
			
		||||
        string memory path = string(abi.encodePacked(root, "/", "contracts/test/foundry/addresses/addresses.json"));
 | 
			
		||||
        json = vm.readFile(path);
 | 
			
		||||
        createForks();
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < chains.length; i++) {
 | 
			
		||||
            chainsByChainId[chains[i]] = chainIds[i];
 | 
			
		||||
            indexChainsByChain[chains[i]] = indexChainIds[i];
 | 
			
		||||
            bytes memory details = json.parseRaw(indexChainIds[i]);
 | 
			
		||||
            addresses = abi.decode(details, (Addresses));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testTransformERC20Forked() public {
 | 
			
		||||
        log_string("TransformERC20Tests");
 | 
			
		||||
        for (uint256 i = 0; i < chains.length; i++) {
 | 
			
		||||
            vm.selectFork(forkIds[chains[i]]);
 | 
			
		||||
            log_named_string("  Selecting Fork On", chains[i]);
 | 
			
		||||
            _wrapNativeToken(chains[i], indexChainsByChain[chains[i]]);
 | 
			
		||||
            _swapERC20ForERC20(chains[i], indexChainsByChain[chains[i]]);
 | 
			
		||||
            //_transformERC20Forked(chains[i], indexChainsByChain[chains[i]]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    function logAddresses(string memory chainName, string memory chainId) public {
 | 
			
		||||
        bytes memory details = json.parseRaw(chainId);
 | 
			
		||||
        addresses = abi.decode(details, (Addresses));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _wrapNativeToken(string memory chainName, string memory chainId) public onlyForked {
 | 
			
		||||
        bytes memory details = json.parseRaw(chainId);
 | 
			
		||||
        addresses = abi.decode(details, (Addresses));
 | 
			
		||||
 | 
			
		||||
        vm.deal(address(this), 1e19);
 | 
			
		||||
 | 
			
		||||
        emit log_string("-----Preparing ETH->WETH transformation through TransformERC20()-----");
 | 
			
		||||
        emit log_string("   --Building Up Transformations--");
 | 
			
		||||
        ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](1);
 | 
			
		||||
 | 
			
		||||
        emit log_named_address(
 | 
			
		||||
            "    Finding TransformerDeployer nonce @", address(addresses.exchangeProxyTransformerDeployer)
 | 
			
		||||
            );
 | 
			
		||||
        emit log_named_uint(
 | 
			
		||||
            "       Deployer nonce",
 | 
			
		||||
            _findTransformerNonce(
 | 
			
		||||
                address(addresses.wethTransformer), address(addresses.exchangeProxyTransformerDeployer)
 | 
			
		||||
            )
 | 
			
		||||
            );
 | 
			
		||||
        transformations[0].deploymentNonce = _findTransformerNonce(
 | 
			
		||||
            address(addresses.wethTransformer), address(addresses.exchangeProxyTransformerDeployer)
 | 
			
		||||
        );
 | 
			
		||||
        transformations[0].data = abi.encode(LibERC20Transformer.ETH_TOKEN_ADDRESS, 1e18);
 | 
			
		||||
 | 
			
		||||
        emit log_string("   ---Calling TransformERC20()---");
 | 
			
		||||
        uint256 balanceETHBefore = address(this).balance;
 | 
			
		||||
        uint256 balanceWETHBefore = IERC20TokenV06(addresses.etherToken).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        IZeroEx(payable(addresses.exchangeProxy)).transformERC20{value: 1e18}(
 | 
			
		||||
            // input token
 | 
			
		||||
            IERC20TokenV06(LibERC20Transformer.ETH_TOKEN_ADDRESS),
 | 
			
		||||
            // output token
 | 
			
		||||
            IERC20TokenV06(address(addresses.etherToken)),
 | 
			
		||||
            // input token amount
 | 
			
		||||
            1e18,
 | 
			
		||||
            // min output token amount
 | 
			
		||||
            1e18,
 | 
			
		||||
            // list of transform
 | 
			
		||||
            transformations
 | 
			
		||||
        );
 | 
			
		||||
        log_named_uint("        NativeAsset balance before", balanceETHBefore);
 | 
			
		||||
        log_named_uint("        ERC-20 balance before",  balanceWETHBefore);
 | 
			
		||||
        log_named_uint("        NativeAsset balance after", balanceETHBefore - address(this).balance);
 | 
			
		||||
        log_named_uint("        ERC-20 balance after",  IERC20TokenV06(addresses.etherToken).balanceOf(address(this)) - balanceWETHBefore);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -21,11 +21,69 @@ pragma solidity ^0.6;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
 | 
			
		||||
=======
 | 
			
		||||
import "src/features/TransformERC20Feature.sol";
 | 
			
		||||
import "src/external/TransformerDeployer.sol";
 | 
			
		||||
import "src/transformers/WethTransformer.sol";
 | 
			
		||||
import "src/transformers/FillQuoteTransformer.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "src/transformers/bridges/BridgeProtocols.sol";
 | 
			
		||||
import "src/transformers/bridges/EthereumBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/PolygonBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/BSCBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/ArbitrumBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/OptimismBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/AvalancheBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/FantomBridgeAdapter.sol";
 | 
			
		||||
import "src/transformers/bridges/CeloBridgeAdapter.sol";
 | 
			
		||||
import "src/IZeroEx.sol";
 | 
			
		||||
 | 
			
		||||
//contract-addresses/addresses.json interfaces
 | 
			
		||||
//need to be alphebetized in solidity but not in addresses.json
 | 
			
		||||
struct Addresses {
 | 
			
		||||
    address affiliateFeeTransformer;
 | 
			
		||||
    address erc20BridgeProxy;
 | 
			
		||||
    address erc20BridgeSampler;
 | 
			
		||||
    address etherToken;
 | 
			
		||||
    address payable exchangeProxy;
 | 
			
		||||
    address exchangeProxyFlashWallet;
 | 
			
		||||
    address exchangeProxyGovernor;
 | 
			
		||||
    address exchangeProxyLiquidityProviderSandbox;
 | 
			
		||||
    address exchangeProxyTransformerDeployer;
 | 
			
		||||
    address fillQuoteTransformer;
 | 
			
		||||
    address payTakerTransformer;
 | 
			
		||||
    address positiveSlippageFeeTransformer;
 | 
			
		||||
    address staking;
 | 
			
		||||
    address stakingProxy;
 | 
			
		||||
    address wethTransformer;
 | 
			
		||||
    address zeroExGovernor;
 | 
			
		||||
    address zrxToken;
 | 
			
		||||
    address zrxTreasury;
 | 
			
		||||
    address zrxVault;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct TokenAddresses {
 | 
			
		||||
  IERC20TokenV06 DAI;
 | 
			
		||||
  IERC20TokenV06 USDC;
 | 
			
		||||
  IERC20TokenV06 USDT;
 | 
			
		||||
  IEtherTokenV06 WrappedNativeToken;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct LiquiditySources {
 | 
			
		||||
  address UniswapV2Router;
 | 
			
		||||
}
 | 
			
		||||
interface IFQT{
 | 
			
		||||
  function bridgeAdapter() external returns (address);
 | 
			
		||||
}
 | 
			
		||||
>>>>>>> 725dfe4db (working bridge Fills through weth transformer)
 | 
			
		||||
 | 
			
		||||
contract ForkUtils is Test {
 | 
			
		||||
    /// Only run this function if the block number
 | 
			
		||||
    // is greater than some constant for Ethereum Mainnet
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
    modifier onlyForked {
 | 
			
		||||
        if (block.number >= 14206900) {
 | 
			
		||||
            _;
 | 
			
		||||
@@ -34,3 +92,112 @@ contract ForkUtils is Test {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
    string addressesJson;
 | 
			
		||||
    string tokensJson;
 | 
			
		||||
    string sourcesJson;
 | 
			
		||||
 | 
			
		||||
    function createForks() public returns (uint256[] memory) {
 | 
			
		||||
      for (uint256 i = 0; i < chains.length; i++) {
 | 
			
		||||
          forkIds[chains[i]] = vm.createFork(vm.rpcUrl(chains[i]), blockNumber[i]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function readLiquiditySourceAddresses() public returns (string memory) {
 | 
			
		||||
      string memory root = vm.projectRoot();
 | 
			
		||||
      string memory path = string(abi.encodePacked(root, "/", "contracts/test/foundry/addresses/sourceAddresses.json"));
 | 
			
		||||
      sourcesJson = vm.readFile(path);
 | 
			
		||||
      return vm.readFile(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getLiquiditySourceAddresses(uint index) public returns (LiquiditySources memory sources ) {
 | 
			
		||||
      readLiquiditySourceAddresses();
 | 
			
		||||
      bytes memory liquiditySources = sourcesJson.parseRaw(indexChainIds[index]);
 | 
			
		||||
      return abi.decode(liquiditySources, (LiquiditySources));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function readAddresses() public returns (string memory){
 | 
			
		||||
        string memory root = vm.projectRoot();
 | 
			
		||||
        string memory path = string(abi.encodePacked(root, "/", "contracts/test/foundry/addresses/addresses.json"));
 | 
			
		||||
        addressesJson = vm.readFile(path);
 | 
			
		||||
        return vm.readFile(path);
 | 
			
		||||
    }
 | 
			
		||||
    function getContractAddresses(uint index) public returns (Addresses memory addresses){
 | 
			
		||||
      readAddresses();
 | 
			
		||||
      bytes memory contractAddresses = addressesJson.parseRaw(indexChainIds[index]);
 | 
			
		||||
      return abi.decode(contractAddresses, (Addresses));
 | 
			
		||||
      //log_named_address("WETH/NATIVE_ASSET", address(tokens.WrappedNativeToken));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function readTokens() public returns (string memory){
 | 
			
		||||
      string memory root = vm.projectRoot();
 | 
			
		||||
      string memory path = string(abi.encodePacked(root, "/", "contracts/test/foundry/addresses/tokenAddresses.json"));
 | 
			
		||||
      tokensJson = vm.readFile(path);
 | 
			
		||||
      return vm.readFile(path);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getTokens(uint index) public returns (TokenAddresses memory addresses){
 | 
			
		||||
      readTokens();
 | 
			
		||||
      bytes memory chainTokens = tokensJson.parseRaw(indexChainIds[index]);
 | 
			
		||||
      return abi.decode(chainTokens, (TokenAddresses));
 | 
			
		||||
      //log_named_address("WETH/NATIVE_ASSET", address(tokens.WrappedNativeToken));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function createBridgeAdapter(IEtherTokenV06 weth) public returns(IBridgeAdapter bridgeAdapter) {
 | 
			
		||||
    uint chainId;
 | 
			
		||||
 | 
			
		||||
    assembly {
 | 
			
		||||
      chainId := chainid()
 | 
			
		||||
    }
 | 
			
		||||
    if(chainId == 1) {return IBridgeAdapter(new EthereumBridgeAdapter(weth));}
 | 
			
		||||
    else if( chainId == 56){ return IBridgeAdapter(new BSCBridgeAdapter(weth));}
 | 
			
		||||
    else if( chainId == 137){return IBridgeAdapter(new PolygonBridgeAdapter(weth));}
 | 
			
		||||
    else if( chainId == 43114){return IBridgeAdapter(new AvalancheBridgeAdapter(weth));}
 | 
			
		||||
    else if( chainId == 250){return IBridgeAdapter(new FantomBridgeAdapter(weth));}
 | 
			
		||||
    else if( chainId == 10){return IBridgeAdapter(new OptimismBridgeAdapter(weth));}
 | 
			
		||||
    else if( chainId == 42161){return IBridgeAdapter(new ArbitrumBridgeAdapter(weth));}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function labelAddresses(string memory chainName, string memory chainId, TokenAddresses memory tokens, Addresses memory addresses, LiquiditySources memory sources) public {
 | 
			
		||||
    log_named_string("   Using contract addresses on chain",chainName);
 | 
			
		||||
    // log_named_address("     zeroEx/exchangeProxy",addresses.exchangeProxy);
 | 
			
		||||
    // log_named_address("     zeroEx/fillQuoteTransformer",addresses.fillQuoteTransformer);
 | 
			
		||||
    // log_named_address("     zeroEx/payTakerTransformer",addresses.payTakerTransformer);
 | 
			
		||||
    // log_named_address("     zeroEx/positiveSlippageFeeTransformer",addresses.positiveSlippageFeeTransformer);
 | 
			
		||||
    // log_named_address("     zeroEx/wethTransformer",addresses.wethTransformer);
 | 
			
		||||
    // vm.label(addresses.affiliateFeeTransformer, "zeroEx/affiliateFeeTransformer");
 | 
			
		||||
    vm.label(addresses.erc20BridgeProxy, "zeroEx/erc20BridgeProxy");
 | 
			
		||||
    vm.label(addresses.erc20BridgeSampler, "zeroEx/erc20BridgeSampler");
 | 
			
		||||
    vm.label(addresses.etherToken, "zeroEx/etherToken");
 | 
			
		||||
    vm.label(addresses.exchangeProxy, "zeroEx/exchangeProxy");
 | 
			
		||||
    vm.label(addresses.exchangeProxyFlashWallet, "zeroEx/exchangeProxyFlashWallet");
 | 
			
		||||
    vm.label(addresses.exchangeProxyGovernor, "zeroEx/exchangeProxyGovernor");
 | 
			
		||||
    vm.label(addresses.exchangeProxyLiquidityProviderSandbox, "zeroEx/exchangeProxyLiquidityProviderSandbox");
 | 
			
		||||
    vm.label(addresses.exchangeProxyTransformerDeployer, "zeroEx/exchangeProxyTransformerDeployer");
 | 
			
		||||
    vm.label(addresses.fillQuoteTransformer, "zeroEx/fillQuoteTransformer");
 | 
			
		||||
    vm.label(addresses.payTakerTransformer, "zeroEx/payTakerTransformer");
 | 
			
		||||
    vm.label(addresses.positiveSlippageFeeTransformer, "zeroEx/positiveSlippageFeeTransformer");
 | 
			
		||||
    vm.label(addresses.staking, "zeroEx/staking");
 | 
			
		||||
    vm.label(addresses.stakingProxy, "zeroEx/stakingProxy");
 | 
			
		||||
    vm.label(addresses.wethTransformer, "zeroEx/wethTransformer");
 | 
			
		||||
    vm.label(addresses.zeroExGovernor, "zeroEx/zeroExGovernor");
 | 
			
		||||
    vm.label(addresses.zrxToken, "zeroEx/zrxToken");
 | 
			
		||||
    vm.label(addresses.zrxTreasury, "zeroEx/zrxTreasury");
 | 
			
		||||
    vm.label(addresses.zrxVault, "zeroEx/zrxVault");
 | 
			
		||||
    vm.label(address(tokens.WrappedNativeToken), "WrappedNativeToken");
 | 
			
		||||
    vm.label(address(tokens.USDT), "USDT");
 | 
			
		||||
    vm.label(address(tokens.USDC), "USDC");
 | 
			
		||||
    vm.label(address(tokens.DAI), "DAI");
 | 
			
		||||
    vm.label(address(sources.UniswapV2Router), "UniswapRouter");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  modifier onlyForked() {
 | 
			
		||||
      if (block.number >= 15000000) {
 | 
			
		||||
          _;
 | 
			
		||||
      } else {
 | 
			
		||||
          emit log_string("Requires fork mode, skipping");
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
>>>>>>> 725dfe4db (working bridge Fills through weth transformer)
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,7 @@ contract TestUtils is Test {
 | 
			
		||||
        return nstr;
 | 
			
		||||
    }    
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
    function _findTransformerNonce(
 | 
			
		||||
        address transformer,
 | 
			
		||||
        address deployer
 | 
			
		||||
@@ -68,6 +69,9 @@ contract TestUtils is Test {
 | 
			
		||||
        pure
 | 
			
		||||
        returns (uint32)
 | 
			
		||||
    {
 | 
			
		||||
=======
 | 
			
		||||
    function _findTransformerNonce(address transformer, address deployer) internal returns (uint32) {
 | 
			
		||||
>>>>>>> 725dfe4db (working bridge Fills through weth transformer)
 | 
			
		||||
        address current;
 | 
			
		||||
        for (uint32 i = 0; i < 1024; i++) {
 | 
			
		||||
            current = LibERC20Transformer.getDeployedAddress(deployer, i);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user