ETH Price: $3,107.51 (+0.97%)
Gas: 14 Gwei

Contract

0xf9b30557AfcF76eA82C04015D80057Fa2147Dfa9
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Sell To Uniswap143341682022-03-06 15:34:11805 days ago1646580851IN
0xf9b30557...a2147Dfa9
0 ETH0.0033883930.85238889
Sell To Uniswap143341632022-03-06 15:33:27806 days ago1646580807IN
0xf9b30557...a2147Dfa9
0 ETH0.0036668931.3630002
Sell To Uniswap143341542022-03-06 15:31:52806 days ago1646580712IN
0xf9b30557...a2147Dfa9
0 ETH0.0048716341.46815311
Sell To Uniswap143341512022-03-06 15:31:08806 days ago1646580668IN
0xf9b30557...a2147Dfa9
0 ETH0.0044131742.17810627
Sell To Uniswap143341422022-03-06 15:28:03806 days ago1646580483IN
0xf9b30557...a2147Dfa9
0 ETH0.0067273638.30461658
Sell To Uniswap143341392022-03-06 15:27:09806 days ago1646580429IN
0xf9b30557...a2147Dfa9
0 ETH0.0069236838.20280926
Sell To Uniswap143341272022-03-06 15:24:16806 days ago1646580256IN
0xf9b30557...a2147Dfa9
0 ETH0.0036584232.42770852
Sell To Uniswap143341122022-03-06 15:21:17806 days ago1646580077IN
0xf9b30557...a2147Dfa9
0 ETH0.0049354743.74256118
Sell To Uniswap143341082022-03-06 15:19:28806 days ago1646579968IN
0xf9b30557...a2147Dfa9
0 ETH0.0047202237.8362645
Sell To Uniswap143340792022-03-06 15:13:48806 days ago1646579628IN
0xf9b30557...a2147Dfa9
0 ETH0.0048549638.91628449
Sell To Uniswap143340672022-03-06 15:10:50806 days ago1646579450IN
0xf9b30557...a2147Dfa9
0 ETH0.0043852838.87042069
Sell To Uniswap143340532022-03-06 15:07:56806 days ago1646579276IN
0xf9b30557...a2147Dfa9
0 ETH0.0050106442.34321564
Sell To Uniswap143340402022-03-06 15:04:40806 days ago1646579080IN
0xf9b30557...a2147Dfa9
0 ETH0.0016458943.14831035
Sell To Uniswap143340282022-03-06 15:01:36806 days ago1646578896IN
0xf9b30557...a2147Dfa9
0 ETH0.0015300939.72928977
Sell To Uniswap143338722022-03-06 14:26:35806 days ago1646576795IN
0xf9b30557...a2147Dfa9
0 ETH0.0012746433.41575157
Sell To Uniswap143338612022-03-06 14:24:20806 days ago1646576660IN
0xf9b30557...a2147Dfa9
0 ETH0.001377735.77235204
0x61012060116105252021-01-07 23:37:591228 days ago1610062679IN
 Create: UniswapFeature
0 ETH0.0718393100

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
138639332021-12-23 21:42:26878 days ago1640295746
0xf9b30557...a2147Dfa9
0.14925 ETH
138639332021-12-23 21:42:26878 days ago1640295746
0xf9b30557...a2147Dfa9
0.14925 ETH
138568262021-12-22 19:19:49879 days ago1640200789
0xf9b30557...a2147Dfa9
0.02089307 ETH
138568262021-12-22 19:19:49879 days ago1640200789
0xf9b30557...a2147Dfa9
0.02089307 ETH
138455422021-12-21 1:06:36881 days ago1640048796
0xf9b30557...a2147Dfa9
0.11114005 ETH
138455422021-12-21 1:06:36881 days ago1640048796
0xf9b30557...a2147Dfa9
0.11114005 ETH
138455402021-12-21 1:06:13881 days ago1640048773
0xf9b30557...a2147Dfa9
0.11114005 ETH
138455402021-12-21 1:06:13881 days ago1640048773
0xf9b30557...a2147Dfa9
0.11114005 ETH
138431532021-12-20 16:32:44881 days ago1640017964
0xf9b30557...a2147Dfa9
0.04975 ETH
138431532021-12-20 16:32:44881 days ago1640017964
0xf9b30557...a2147Dfa9
0.04975 ETH
138431332021-12-20 16:29:00881 days ago1640017740
0xf9b30557...a2147Dfa9
0.0995 ETH
138431332021-12-20 16:29:00881 days ago1640017740
0xf9b30557...a2147Dfa9
0.0995 ETH
138384002021-12-19 22:59:57882 days ago1639954797
0xf9b30557...a2147Dfa9
0.01908549 ETH
138384002021-12-19 22:59:57882 days ago1639954797
0xf9b30557...a2147Dfa9
0.01908549 ETH
138383922021-12-19 22:58:19882 days ago1639954699
0xf9b30557...a2147Dfa9
0.00624767 ETH
138383922021-12-19 22:58:19882 days ago1639954699
0xf9b30557...a2147Dfa9
0.00624767 ETH
138307772021-12-18 18:38:43883 days ago1639852723
0xf9b30557...a2147Dfa9
0.43502173 ETH
138307772021-12-18 18:38:43883 days ago1639852723
0xf9b30557...a2147Dfa9
0.43502173 ETH
138307602021-12-18 18:35:02883 days ago1639852502
0xf9b30557...a2147Dfa9
0.44318029 ETH
138307602021-12-18 18:35:02883 days ago1639852502
0xf9b30557...a2147Dfa9
0.44318029 ETH
138289492021-12-18 11:46:20884 days ago1639827980
0xf9b30557...a2147Dfa9
0.24875 ETH
138289492021-12-18 11:46:20884 days ago1639827980
0xf9b30557...a2147Dfa9
0.24875 ETH
138206422021-12-17 5:04:56885 days ago1639717496
0xf9b30557...a2147Dfa9
0.09064045 ETH
138206422021-12-17 5:04:56885 days ago1639717496
0xf9b30557...a2147Dfa9
0.09064045 ETH
138205592021-12-17 4:44:55885 days ago1639716295
0xf9b30557...a2147Dfa9
0.0995 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UniswapFeature

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion, Apache-2.0 license
File 1 of 15 : UniswapFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "../migrations/LibMigrate.sol";
import "../external/IAllowanceTarget.sol";
import "../fixins/FixinCommon.sol";
import "./IFeature.sol";
import "./IUniswapFeature.sol";


/// @dev VIP uniswap fill functions.
contract UniswapFeature is
    IFeature,
    IUniswapFeature,
    FixinCommon
{
    /// @dev Name of this feature.
    string public constant override FEATURE_NAME = "UniswapFeature";
    /// @dev Version of this feature.
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1);
    /// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails.
    bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER;
    /// @dev WETH contract.
    IEtherTokenV06 private immutable WETH;
    /// @dev AllowanceTarget instance.
    IAllowanceTarget private immutable ALLOWANCE_TARGET;

    // 0xFF + address of the UniswapV2Factory contract.
    uint256 constant private FF_UNISWAP_FACTORY = 0xFF5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f0000000000000000000000;
    // 0xFF + address of the (Sushiswap) UniswapV2Factory contract.
    uint256 constant private FF_SUSHISWAP_FACTORY = 0xFFC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac0000000000000000000000;
    // Init code hash of the UniswapV2Pair contract.
    uint256 constant private UNISWAP_PAIR_INIT_CODE_HASH = 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
    // Init code hash of the (Sushiswap) UniswapV2Pair contract.
    uint256 constant private SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303;
    // Mask of the lower 20 bytes of a bytes32.
    uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
    // ETH pseudo-token address.
    uint256 constant private ETH_TOKEN_ADDRESS_32 = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;
    // Maximum token quantity that can be swapped against the UniswapV2Pair contract.
    uint256 constant private MAX_SWAP_AMOUNT = 2**112;

    // bytes4(keccak256("executeCall(address,bytes)"))
    uint256 constant private ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32 = 0xbca8c7b500000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("getReserves()"))
    uint256 constant private UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32 = 0x0902f1ac00000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("swap(uint256,uint256,address,bytes)"))
    uint256 constant private UNISWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x022c0d9f00000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("transferFrom(address,address,uint256)"))
    uint256 constant private TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("allowance(address,address)"))
    uint256 constant private ALLOWANCE_CALL_SELECTOR_32 = 0xdd62ed3e00000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("withdraw(uint256)"))
    uint256 constant private WETH_WITHDRAW_CALL_SELECTOR_32 = 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("deposit()"))
    uint256 constant private WETH_DEPOSIT_CALL_SELECTOR_32 = 0xd0e30db000000000000000000000000000000000000000000000000000000000;
    // bytes4(keccak256("transfer(address,uint256)"))
    uint256 constant private ERC20_TRANSFER_CALL_SELECTOR_32 = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;

    /// @dev Construct this contract.
    /// @param weth The WETH contract.
    /// @param allowanceTarget The AllowanceTarget contract.
    /// @param greedyTokensBloomFilter The bloom filter for greedy tokens.
    constructor(
        IEtherTokenV06 weth,
        IAllowanceTarget allowanceTarget,
        bytes32 greedyTokensBloomFilter
    ) public {
        WETH = weth;
        ALLOWANCE_TARGET = allowanceTarget;
        GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter;
    }

    /// @dev Initialize and register this feature.
    ///      Should be delegatecalled by `Migrate.migrate()`.
    /// @return success `LibMigrate.SUCCESS` on success.
    function migrate()
        external
        returns (bytes4 success)
    {
        _registerFeatureFunction(this.sellToUniswap.selector);
        return LibMigrate.MIGRATE_SUCCESS;
    }

    /// @dev Efficiently sell directly to uniswap/sushiswap.
    /// @param tokens Sell path.
    /// @param sellAmount of `tokens[0]` Amount to sell.
    /// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
    /// @param isSushi Use sushiswap if true.
    /// @return buyAmount Amount of `tokens[-1]` bought.
    function sellToUniswap(
        IERC20TokenV06[] calldata tokens,
        uint256 sellAmount,
        uint256 minBuyAmount,
        bool isSushi
    )
        external
        payable
        override
        returns (uint256 buyAmount)
    {
        require(tokens.length > 1, "UniswapFeature/InvalidTokensLength");
        {
            // Load immutables onto the stack.
            IEtherTokenV06 weth = WETH;
            IAllowanceTarget allowanceTarget = ALLOWANCE_TARGET;
            bytes32 greedyTokensBloomFilter = GREEDY_TOKENS_BLOOM_FILTER;

            // Store some vars in memory to get around stack limits.
            assembly {
                // calldataload(mload(0xA00)) == first element of `tokens` array
                mstore(0xA00, add(calldataload(0x04), 0x24))
                // mload(0xA20) == isSushi
                mstore(0xA20, isSushi)
                // mload(0xA40) == WETH
                mstore(0xA40, weth)
                // mload(0xA60) == ALLOWANCE_TARGET
                mstore(0xA60, allowanceTarget)
                // mload(0xA80) == GREEDY_TOKENS_BLOOM_FILTER
                mstore(0xA80, greedyTokensBloomFilter)
            }
        }

        assembly {
            // numPairs == tokens.length - 1
            let numPairs := sub(calldataload(add(calldataload(0x04), 0x4)), 1)
            // We use the previous buy amount as the sell amount for the next
            // pair in a path. So for the first swap we want to set it to `sellAmount`.
            buyAmount := sellAmount
            let buyToken
            let nextPair := 0

            for {let i := 0} lt(i, numPairs) {i := add(i, 1)} {
                // sellToken = tokens[i]
                let sellToken := loadTokenAddress(i)
                // buyToken = tokens[i+1]
                buyToken := loadTokenAddress(add(i, 1))
                // The canonical ordering of this token pair.
                let pairOrder := lt(normalizeToken(sellToken), normalizeToken(buyToken))

                // Compute the pair address if it hasn't already been computed
                // from the last iteration.
                let pair := nextPair
                if iszero(pair) {
                    pair := computePairAddress(sellToken, buyToken)
                    nextPair := 0
                }

                if iszero(i) {
                    // This is the first token in the path.
                    switch eq(sellToken, ETH_TOKEN_ADDRESS_32)
                        case 0 { // Not selling ETH. Selling an ERC20 instead.
                            // Make sure ETH was not attached to the call.
                            if gt(callvalue(), 0) {
                                revert(0, 0)
                            }
                            // For the first pair we need to transfer sellTokens into the
                            // pair contract.
                            moveTakerTokensTo(sellToken, pair, sellAmount)
                        }
                        default {
                            // If selling ETH, we need to wrap it to WETH and transfer to the
                            // pair contract.
                            if iszero(eq(callvalue(), sellAmount)) {
                                revert(0, 0)
                            }
                            sellToken := mload(0xA40)// Re-assign to WETH
                            // Call `WETH.deposit{value: sellAmount}()`
                            mstore(0xB00, WETH_DEPOSIT_CALL_SELECTOR_32)
                            if iszero(call(gas(), sellToken, sellAmount, 0xB00, 0x4, 0x00, 0x0)) {
                                bubbleRevert()
                            }
                            // Call `WETH.transfer(pair, sellAmount)`
                            mstore(0xB00, ERC20_TRANSFER_CALL_SELECTOR_32)
                            mstore(0xB04, pair)
                            mstore(0xB24, sellAmount)
                            if iszero(call(gas(), sellToken, 0, 0xB00, 0x44, 0x00, 0x0)) {
                                bubbleRevert()
                            }
                        }
                    // No need to check results, if deposit/transfers failed the UniswapV2Pair will
                    // reject our trade (or it may succeed if somehow the reserve was out of sync)
                    // this is fine for the taker.
                }

                // Call pair.getReserves(), store the results at `0xC00`
                mstore(0xB00, UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32)
                if iszero(staticcall(gas(), pair, 0xB00, 0x4, 0xC00, 0x40)) {
                    bubbleRevert()
                }
                // Revert if the pair contract does not return at least two words.
                if lt(returndatasize(), 0x40) {
                    revert(0,0)
                }

                // Sell amount for this hop is the previous buy amount.
                let pairSellAmount := buyAmount
                // Compute the buy amount based on the pair reserves.
                {
                    let sellReserve
                    let buyReserve
                    switch iszero(pairOrder)
                        case 0 {
                            // Transpose if pair order is different.
                            sellReserve := mload(0xC00)
                            buyReserve := mload(0xC20)
                        }
                        default {
                            sellReserve := mload(0xC20)
                            buyReserve := mload(0xC00)
                        }
                    // Ensure that the sellAmount is < 2B9B9B2.
                    if gt(pairSellAmount, MAX_SWAP_AMOUNT) {
                        revert(0, 0)
                    }
                    // Pairs are in the range (0, 2B9B9B2) so this shouldn't overflow.
                    // buyAmount = (pairSellAmount * 997 * buyReserve) /
                    //     (pairSellAmount * 997 + sellReserve * 1000);
                    let sellAmountWithFee := mul(pairSellAmount, 997)
                    buyAmount := div(
                        mul(sellAmountWithFee, buyReserve),
                        add(sellAmountWithFee, mul(sellReserve, 1000))
                    )
                }

                let receiver
                // Is this the last pair contract?
                switch eq(add(i, 1), numPairs)
                    case 0 {
                        // Not the last pair contract, so forward bought tokens to
                        // the next pair contract.
                        nextPair := computePairAddress(
                            buyToken,
                            loadTokenAddress(add(i, 2))
                        )
                        receiver := nextPair
                    }
                    default {
                        // The last pair contract.
                        // Forward directly to taker UNLESS they want ETH back.
                        switch eq(buyToken, ETH_TOKEN_ADDRESS_32)
                            case 0 {
                                receiver := caller()
                            }
                            default {
                                receiver := address()
                            }
                    }

                // Call pair.swap()
                mstore(0xB00, UNISWAP_PAIR_SWAP_CALL_SELECTOR_32)
                switch pairOrder
                    case 0 {
                        mstore(0xB04, buyAmount)
                        mstore(0xB24, 0)
                    }
                    default {
                        mstore(0xB04, 0)
                        mstore(0xB24, buyAmount)
                    }
                mstore(0xB44, receiver)
                mstore(0xB64, 0x80)
                mstore(0xB84, 0)
                if iszero(call(gas(), pair, 0, 0xB00, 0xA4, 0, 0)) {
                    bubbleRevert()
                }
            } // End for-loop.

            // If buying ETH, unwrap the WETH first
            if eq(buyToken, ETH_TOKEN_ADDRESS_32) {
                // Call `WETH.withdraw(buyAmount)`
                mstore(0xB00, WETH_WITHDRAW_CALL_SELECTOR_32)
                mstore(0xB04, buyAmount)
                if iszero(call(gas(), mload(0xA40), 0, 0xB00, 0x24, 0x00, 0x0)) {
                    bubbleRevert()
                }
                // Transfer ETH to the caller.
                if iszero(call(gas(), caller(), buyAmount, 0xB00, 0x0, 0x00, 0x0)) {
                    bubbleRevert()
                }
            }

            // Functions ///////////////////////////////////////////////////////

            // Load a token address from the `tokens` calldata argument.
            function loadTokenAddress(idx) -> addr {
                addr := and(ADDRESS_MASK, calldataload(add(mload(0xA00), mul(idx, 0x20))))
            }

            // Convert ETH pseudo-token addresses to WETH.
            function normalizeToken(token) -> normalized {
                normalized := token
                // Translate ETH pseudo-tokens to WETH.
                if eq(token, ETH_TOKEN_ADDRESS_32) {
                    normalized := mload(0xA40)
                }
            }

            // Compute the address of the UniswapV2Pair contract given two
            // tokens.
            function computePairAddress(tokenA, tokenB) -> pair {
                // Convert ETH pseudo-token addresses to WETH.
                tokenA := normalizeToken(tokenA)
                tokenB := normalizeToken(tokenB)
                // There is one contract for every combination of tokens,
                // which is deployed using CREATE2.
                // The derivation of this address is given by:
                //   address(keccak256(abi.encodePacked(
                //       bytes(0xFF),
                //       address(UNISWAP_FACTORY_ADDRESS),
                //       keccak256(abi.encodePacked(
                //           tokenA < tokenB ? tokenA : tokenB,
                //           tokenA < tokenB ? tokenB : tokenA,
                //       )),
                //       bytes32(UNISWAP_PAIR_INIT_CODE_HASH),
                //   )));

                // Compute the salt (the hash of the sorted tokens).
                // Tokens are written in reverse memory order to packed encode
                // them as two 20-byte values in a 40-byte chunk of memory
                // starting at 0xB0C.
                switch lt(tokenA, tokenB)
                    case 0 {
                        mstore(0xB14, tokenA)
                        mstore(0xB00, tokenB)
                    }
                    default {
                        mstore(0xB14, tokenB)
                        mstore(0xB00, tokenA)
                    }
                let salt := keccak256(0xB0C, 0x28)
                // Compute the pair address by hashing all the components together.
                switch mload(0xA20) // isSushi
                    case 0 {
                        mstore(0xB00, FF_UNISWAP_FACTORY)
                        mstore(0xB15, salt)
                        mstore(0xB35, UNISWAP_PAIR_INIT_CODE_HASH)
                    }
                    default {
                        mstore(0xB00, FF_SUSHISWAP_FACTORY)
                        mstore(0xB15, salt)
                        mstore(0xB35, SUSHISWAP_PAIR_INIT_CODE_HASH)
                    }
                pair := and(ADDRESS_MASK, keccak256(0xB00, 0x55))
            }

            // Revert with the return data from the most recent call.
            function bubbleRevert() {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }

            // Move `amount` tokens from the taker/caller to `to`.
            function moveTakerTokensTo(token, to, amount) {

                // If the token is possibly greedy, we check the allowance rather
                // than relying on letting the transferFrom() call fail and
                // falling through to legacy allowance target because the token
                // will eat all our gas.
                if isTokenPossiblyGreedy(token) {
                    // Check if we have enough direct allowance by calling
                    // `token.allowance()``
                    mstore(0xB00, ALLOWANCE_CALL_SELECTOR_32)
                    mstore(0xB04, caller())
                    mstore(0xB24, address())
                    let success := staticcall(gas(), token, 0xB00, 0x44, 0xC00, 0x20)
                    if iszero(success) {
                        // Call to allowance() failed.
                        bubbleRevert()
                    }
                    // Make sure the allowance call returned at least a word.
                    if lt(returndatasize(), 0x20) {
                        revert(0, 0)
                    }
                    // Call succeeded.
                    // Result is stored in 0xC00-0xC20.
                    if lt(mload(0xC00), amount) {
                        // We don't have enough direct allowance, so try
                        // going through the legacy allowance taregt.
                        moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount)
                        leave
                    }
                }

                // Otherwise we will optimistically try to perform a `transferFrom()`
                // directly then if it fails we will go through the legacy allowance target.
                mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32)
                mstore(0xB04, caller())
                mstore(0xB24, to)
                mstore(0xB44, amount)

                let success := call(
                    gas(),
                    token,
                    0,
                    0xB00,
                    0x64,
                    0xC00,
                    // Copy only the first 32 bytes of return data. We
                    // only care about reading a boolean in the success
                    // case, and we discard the return data in the
                    // failure case.
                    0x20
                )

                let rdsize := returndatasize()

                // Check for ERC20 success. ERC20 tokens should
                // return a boolean, but some return nothing or
                // extra data. We accept 0-length return data as
                // success, or at least 32 bytes that starts with
                // a 32-byte boolean true.
                success := and(
                    success,                         // call itself succeeded
                    or(
                        iszero(rdsize),              // no return data, or
                        and(
                            iszero(lt(rdsize, 32)),  // at least 32 bytes
                            eq(mload(0xC00), 1)      // starts with uint256(1)
                        )
                    )
                )

                if iszero(success) {
                    // Try to fall back to the allowance target.
                    moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount)
                }
            }

            // Move tokens by going through the legacy allowance target contract.
            function moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount) {
                mstore(0xB00, ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32)
                mstore(0xB04, token)
                mstore(0xB24, 0x40)
                mstore(0xB44, 0x64)
                mstore(0xB64, TRANSFER_FROM_CALL_SELECTOR_32)
                mstore(0xB68, caller())
                mstore(0xB88, to)
                mstore(0xBA8, amount)
                if iszero(call(gas(), mload(0xA60), 0, 0xB00, 0xC8, 0x00, 0x0)) {
                    bubbleRevert()
                }
                // If this fall back failed, the swap will most likely fail
                // so there's no need to validate the result.
            }

            // Checks if a token possibly belongs to the GREEDY_TOKENS_BLOOM_FILTER
            // bloom filter.
            function isTokenPossiblyGreedy(token) -> isPossiblyGreedy {
                // The hash is given by:
                // (1 << (keccak256(token) % 256)) | (1 << (token % 256))
                mstore(0, token)
                let h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1))
                isPossiblyGreedy := eq(and(h, mload(0xA80)), h)
            }
        }

        // Revert if we bought too little.
        // TODO: replace with rich revert?
        require(buyAmount >= minBuyAmount, "UniswapFeature/UnderBought");
    }
}

File 3 of 15 : IERC20TokenV06.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


interface IERC20TokenV06 {

    // solhint-disable no-simple-event-func-name
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 value
    );

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    /// @dev send `value` token to `to` from `msg.sender`
    /// @param to The address of the recipient
    /// @param value The amount of token to be transferred
    /// @return True if transfer was successful
    function transfer(address to, uint256 value)
        external
        returns (bool);

    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
    /// @param from The address of the sender
    /// @param to The address of the recipient
    /// @param value The amount of token to be transferred
    /// @return True if transfer was successful
    function transferFrom(
        address from,
        address to,
        uint256 value
    )
        external
        returns (bool);

    /// @dev `msg.sender` approves `spender` to spend `value` tokens
    /// @param spender The address of the account able to transfer the tokens
    /// @param value The amount of wei to be approved for transfer
    /// @return Always true if the call has enough gas to complete execution
    function approve(address spender, uint256 value)
        external
        returns (bool);

    /// @dev Query total supply of token
    /// @return Total supply of token
    function totalSupply()
        external
        view
        returns (uint256);

    /// @dev Get the balance of `owner`.
    /// @param owner The address from which the balance will be retrieved
    /// @return Balance of owner
    function balanceOf(address owner)
        external
        view
        returns (uint256);

    /// @dev Get the allowance for `spender` to spend from `owner`.
    /// @param owner The address of the account owning tokens
    /// @param spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    /// @dev Get the number of decimals this token has.
    function decimals()
        external
        view
        returns (uint8);
}

File 4 of 15 : IEtherTokenV06.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;

import "./IERC20TokenV06.sol";


interface IEtherTokenV06 is
    IERC20TokenV06
{
    /// @dev Wrap ether.
    function deposit() external payable;

    /// @dev Unwrap ether.
    function withdraw(uint256 amount) external;
}

File 5 of 15 : LibMigrate.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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/errors/LibRichErrorsV06.sol";
import "../errors/LibOwnableRichErrors.sol";


library LibMigrate {

    /// @dev Magic bytes returned by a migrator to indicate success.
    ///      This is `keccack('MIGRATE_SUCCESS')`.
    bytes4 internal constant MIGRATE_SUCCESS = 0x2c64c5ef;

    using LibRichErrorsV06 for bytes;

    /// @dev Perform a delegatecall and ensure it returns the magic bytes.
    /// @param target The call target.
    /// @param data The call data.
    function delegatecallMigrateFunction(
        address target,
        bytes memory data
    )
        internal
    {
        (bool success, bytes memory resultData) = target.delegatecall(data);
        if (!success ||
            resultData.length != 32 ||
            abi.decode(resultData, (bytes4)) != MIGRATE_SUCCESS)
        {
            LibOwnableRichErrors.MigrateCallFailedError(target, resultData).rrevert();
        }
    }
}

File 6 of 15 : LibRichErrorsV06.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


library LibRichErrorsV06 {

    // bytes4(keccak256("Error(string)"))
    bytes4 internal constant STANDARD_ERROR_SELECTOR = 0x08c379a0;

    // solhint-disable func-name-mixedcase
    /// @dev ABI encode a standard, string revert error payload.
    ///      This is the same payload that would be included by a `revert(string)`
    ///      solidity statement. It has the function signature `Error(string)`.
    /// @param message The error string.
    /// @return The ABI encoded error.
    function StandardError(string memory message)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            STANDARD_ERROR_SELECTOR,
            bytes(message)
        );
    }
    // solhint-enable func-name-mixedcase

    /// @dev Reverts an encoded rich revert reason `errorData`.
    /// @param errorData ABI encoded error data.
    function rrevert(bytes memory errorData)
        internal
        pure
    {
        assembly {
            revert(add(errorData, 0x20), mload(errorData))
        }
    }
}

File 7 of 15 : LibOwnableRichErrors.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


library LibOwnableRichErrors {

    // solhint-disable func-name-mixedcase

    function OnlyOwnerError(
        address sender,
        address owner
    )
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            bytes4(keccak256("OnlyOwnerError(address,address)")),
            sender,
            owner
        );
    }

    function TransferOwnerToZeroError()
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            bytes4(keccak256("TransferOwnerToZeroError()"))
        );
    }

    function MigrateCallFailedError(address target, bytes memory resultData)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            bytes4(keccak256("MigrateCallFailedError(address,bytes)")),
            target,
            resultData
        );
    }
}

File 8 of 15 : IAllowanceTarget.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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/interfaces/IAuthorizableV06.sol";


/// @dev The allowance target for the TokenSpender feature.
interface IAllowanceTarget is
    IAuthorizableV06
{
    /// @dev Execute an arbitrary call. Only an authority can call this.
    /// @param target The call target.
    /// @param callData The call data.
    /// @return resultData The data returned by the call.
    function executeCall(
        address payable target,
        bytes calldata callData
    )
        external
        returns (bytes memory resultData);
}

File 9 of 15 : IAuthorizableV06.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;

import "./IOwnableV06.sol";


interface IAuthorizableV06 is
    IOwnableV06
{
    // Event logged when a new address is authorized.
    event AuthorizedAddressAdded(
        address indexed target,
        address indexed caller
    );

    // Event logged when a currently authorized address is unauthorized.
    event AuthorizedAddressRemoved(
        address indexed target,
        address indexed caller
    );

    /// @dev Authorizes an address.
    /// @param target Address to authorize.
    function addAuthorizedAddress(address target)
        external;

    /// @dev Removes authorizion of an address.
    /// @param target Address to remove authorization from.
    function removeAuthorizedAddress(address target)
        external;

    /// @dev Removes authorizion of an address.
    /// @param target Address to remove authorization from.
    /// @param index Index of target in authorities array.
    function removeAuthorizedAddressAtIndex(
        address target,
        uint256 index
    )
        external;

    /// @dev Gets all authorized addresses.
    /// @return authorizedAddresses Array of authorized addresses.
    function getAuthorizedAddresses()
        external
        view
        returns (address[] memory authorizedAddresses);

    /// @dev Whether an adderss is authorized to call privileged functions.
    /// @param addr Address to query.
    /// @return isAuthorized Whether the address is authorized.
    function authorized(address addr) external view returns (bool isAuthorized);

    /// @dev All addresseses authorized to call privileged functions.
    /// @param idx Index of authorized address.
    /// @return addr Authorized address.
    function authorities(uint256 idx) external view returns (address addr);

}

File 10 of 15 : IOwnableV06.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


interface IOwnableV06 {

    /// @dev Emitted by Ownable when ownership is transferred.
    /// @param previousOwner The previous owner of the contract.
    /// @param newOwner The new owner of the contract.
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @dev Transfers ownership of the contract to a new address.
    /// @param newOwner The address that will become the owner.
    function transferOwnership(address newOwner) external;

    /// @dev The owner of this contract.
    /// @return ownerAddress The owner address.
    function owner() external view returns (address ownerAddress);
}

File 11 of 15 : FixinCommon.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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/errors/LibRichErrorsV06.sol";
import "../errors/LibCommonRichErrors.sol";
import "../errors/LibOwnableRichErrors.sol";
import "../features/IOwnableFeature.sol";
import "../features/ISimpleFunctionRegistryFeature.sol";


/// @dev Common feature utilities.
abstract contract FixinCommon {

    using LibRichErrorsV06 for bytes;

    /// @dev The implementation address of this feature.
    address internal immutable _implementation;

    /// @dev The caller must be this contract.
    modifier onlySelf() virtual {
        if (msg.sender != address(this)) {
            LibCommonRichErrors.OnlyCallableBySelfError(msg.sender).rrevert();
        }
        _;
    }

    /// @dev The caller of this function must be the owner.
    modifier onlyOwner() virtual {
        {
            address owner = IOwnableFeature(address(this)).owner();
            if (msg.sender != owner) {
                LibOwnableRichErrors.OnlyOwnerError(
                    msg.sender,
                    owner
                ).rrevert();
            }
        }
        _;
    }

    constructor() internal {
        // Remember this feature's original address.
        _implementation = address(this);
    }

    /// @dev Registers a function implemented by this feature at `_implementation`.
    ///      Can and should only be called within a `migrate()`.
    /// @param selector The selector of the function whose implementation
    ///        is at `_implementation`.
    function _registerFeatureFunction(bytes4 selector)
        internal
    {
        ISimpleFunctionRegistryFeature(address(this)).extend(selector, _implementation);
    }

    /// @dev Encode a feature version as a `uint256`.
    /// @param major The major version number of the feature.
    /// @param minor The minor version number of the feature.
    /// @param revision The revision number of the feature.
    /// @return encodedVersion The encoded version number.
    function _encodeVersion(uint32 major, uint32 minor, uint32 revision)
        internal
        pure
        returns (uint256 encodedVersion)
    {
        return (uint256(major) << 64) | (uint256(minor) << 32) | uint256(revision);
    }
}

File 12 of 15 : LibCommonRichErrors.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


library LibCommonRichErrors {

    // solhint-disable func-name-mixedcase

    function OnlyCallableBySelfError(address sender)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            bytes4(keccak256("OnlyCallableBySelfError(address)")),
            sender
        );
    }

    function IllegalReentrancyError(bytes4 selector, uint256 reentrancyFlags)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodeWithSelector(
            bytes4(keccak256("IllegalReentrancyError(bytes4,uint256)")),
            selector,
            reentrancyFlags
        );
    }
}

File 13 of 15 : IOwnableFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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/interfaces/IOwnableV06.sol";


// solhint-disable no-empty-blocks
/// @dev Owner management and migration features.
interface IOwnableFeature is
    IOwnableV06
{
    /// @dev Emitted when `migrate()` is called.
    /// @param caller The caller of `migrate()`.
    /// @param migrator The migration contract.
    /// @param newOwner The address of the new owner.
    event Migrated(address caller, address migrator, address newOwner);

    /// @dev Execute a migration function in the context of the ZeroEx contract.
    ///      The result of the function being called should be the magic bytes
    ///      0x2c64c5ef (`keccack('MIGRATE_SUCCESS')`). Only callable by the owner.
    ///      The owner will be temporarily set to `address(this)` inside the call.
    ///      Before returning, the owner will be set to `newOwner`.
    /// @param target The migrator contract address.
    /// @param newOwner The address of the new owner.
    /// @param data The call data.
    function migrate(address target, bytes calldata data, address newOwner) external;
}

File 14 of 15 : ISimpleFunctionRegistryFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


/// @dev Basic registry management features.
interface ISimpleFunctionRegistryFeature {

    /// @dev A function implementation was updated via `extend()` or `rollback()`.
    /// @param selector The function selector.
    /// @param oldImpl The implementation contract address being replaced.
    /// @param newImpl The replacement implementation contract address.
    event ProxyFunctionUpdated(bytes4 indexed selector, address oldImpl, address newImpl);

    /// @dev Roll back to a prior implementation of a function.
    /// @param selector The function selector.
    /// @param targetImpl The address of an older implementation of the function.
    function rollback(bytes4 selector, address targetImpl) external;

    /// @dev Register or replace a function.
    /// @param selector The function selector.
    /// @param impl The implementation contract for the function.
    function extend(bytes4 selector, address impl) external;

    /// @dev Retrieve the length of the rollback history for a function.
    /// @param selector The function selector.
    /// @return rollbackLength The number of items in the rollback history for
    ///         the function.
    function getRollbackLength(bytes4 selector)
        external
        view
        returns (uint256 rollbackLength);

    /// @dev Retrieve an entry in the rollback history for a function.
    /// @param selector The function selector.
    /// @param idx The index in the rollback history.
    /// @return impl An implementation address for the function at
    ///         index `idx`.
    function getRollbackEntryAtIndex(bytes4 selector, uint256 idx)
        external
        view
        returns (address impl);
}

File 15 of 15 : IFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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;


/// @dev Basic interface for a feature contract.
interface IFeature {

    // solhint-disable func-name-mixedcase

    /// @dev The name of this feature set.
    function FEATURE_NAME() external view returns (string memory name);

    /// @dev The version of this feature set.
    function FEATURE_VERSION() external view returns (uint256 version);
}

File 16 of 15 : IUniswapFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2020 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/contracts/src/v06/IERC20TokenV06.sol";


/// @dev VIP uniswap fill functions.
interface IUniswapFeature {

    /// @dev Efficiently sell directly to uniswap/sushiswap.
    /// @param tokens Sell path.
    /// @param sellAmount of `tokens[0]` Amount to sell.
    /// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
    /// @param isSushi Use sushiswap if true.
    /// @return buyAmount Amount of `tokens[-1]` bought.
    function sellToUniswap(
        IERC20TokenV06[] calldata tokens,
        uint256 sellAmount,
        uint256 minBuyAmount,
        bool isSushi
    )
        external
        payable
        returns (uint256 buyAmount);
}

Settings
{
  "remappings": [
    "@0x/contracts-utils=/home/cluracan/code/0x-protocol/node_modules/@0x/contracts-utils",
    "@0x/contracts-erc20=/home/cluracan/code/0x-protocol/contracts/zero-ex/node_modules/@0x/contracts-erc20"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000,
    "details": {
      "yul": true,
      "deduplicate": true,
      "cse": true,
      "constantOptimizer": true
    }
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "istanbul"
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IEtherTokenV06","name":"weth","type":"address"},{"internalType":"contract IAllowanceTarget","name":"allowanceTarget","type":"address"},{"internalType":"bytes32","name":"greedyTokensBloomFilter","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FEATURE_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEATURE_VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GREEDY_TOKENS_BLOOM_FILTER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrate","outputs":[{"internalType":"bytes4","name":"success","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20TokenV06[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"minBuyAmount","type":"uint256"},{"internalType":"bool","name":"isSushi","type":"bool"}],"name":"sellToUniswap","outputs":[{"internalType":"uint256","name":"buyAmount","type":"uint256"}],"stateMutability":"payable","type":"function"}]

6101206040526100116001808061006b565b60a05234801561002057600080fd5b50604051610d59380380610d5983398101604081905261003f9161009d565b30606090811b60805292831b6001600160601b031990811660e0529190921b166101005260c0526100f7565b6bffffffff0000000000000000604084901b1667ffffffff00000000602084901b161763ffffffff8216179392505050565b6000806000606084860312156100b1578283fd5b83516100bc816100df565b60208501519093506100cd816100df565b80925050604084015190509250925092565b6001600160a01b03811681146100f457600080fd5b50565b60805160601c60a05160c05160e05160601c6101005160601c610c16610143600039806102465250806102215250806101a5528061026b52508060f85250806109685250610c166000f3fe60806040526004361061005a5760003560e01c80638fd3ab80116100435780638fd3ab80146100ac578063d925a56d146100ce578063d9627aa4146100e35761005a565b8063031b905c1461005f5780636ae4b4f71461008a575b600080fd5b34801561006b57600080fd5b506100746100f6565b6040516100819190610a5d565b60405180910390f35b34801561009657600080fd5b5061009f61011a565b6040516100819190610adb565b3480156100b857600080fd5b506100c1610153565b6040516100819190610a66565b3480156100da57600080fd5b506100746101a3565b6100746100f13660046109c5565b6101c7565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280600e81526020017f556e69737761704665617475726500000000000000000000000000000000000081525081565b600061017e7fd9627aa400000000000000000000000000000000000000000000000000000000610932565b507f2c64c5ef0000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006001851161020c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020390610b4c565b60405180910390fd5b506004803560248101610a0052610a208390527f0000000000000000000000000000000000000000000000000000000000000000610a40527f0000000000000000000000000000000000000000000000000000000000000000610a60527f0000000000000000000000000000000000000000000000000000000000000000610a805284917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91013501600080805b8381101561055e576102cb816105e1565b6102d7600183016105e1565b93506102e284610606565b6102eb82610606565b108380610303576102fc868461062e565b9050600094505b836103d95773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee831480156103c1578b341461033157600080fd5b610a405193507fd0e30db000000000000000000000000000000000000000000000000000000000610b00526000806004610b008f885af161037457610374610743565b7fa9059cbb00000000000000000000000000000000000000000000000000000000610b005281610b04528b610b24526000806044610b006000885af16103bc576103bc610743565b6103d7565b34156103cc57600080fd5b6103d78c838661074d565b505b7f0902f1ac00000000000000000000000000000000000000000000000000000000610b00526040610c006004610b00845afa61041757610417610743565b60403d101561042557600080fd5b8792506000808315801561044457610c20519250610c00519150610451565b610c00519250610c205191505b506e01000000000000000000000000000085111561046e57600080fd5b6103e585026103e883028101828202049a5050505060009250866001850114600081146104c45773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee871480156104ba573094506104be565b3394505b506104df565b6104d96104d3600287016105e1565b8861062e565b95508593505b507f022c0d9f00000000000000000000000000000000000000000000000000000000610b005281801561051c576000610b045288610b2452610528565b88610b04526000610b24525b5082610b44526080610b64526000610b845260008060a4610b006000855af161055357610553610743565b5050506001016102ba565b505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8114156105da577f2e1a7d4d00000000000000000000000000000000000000000000000000000000610b005282610b04526000806024610b006000610a40515af16105c2576105c2610743565b6000806000610b0086335af16105da576105da610743565b50506108ef565b610a005173ffffffffffffffffffffffffffffffffffffffff60209290920201351690565b8073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8114156106295750610a40515b919050565b600061063982610606565b915061064483610606565b9250828210801561065e5783610b145282610b0052610669565b82610b145283610b00525b506028610b0c20610a205180156106ce577fffc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac0000000000000000000000610b005281610b15527fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303610b355261071e565b7fff5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000610b005281610b15527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f610b35525b50506055610b002073ffffffffffffffffffffffffffffffffffffffff169392505050565b3d6000803e3d6000fd5b610756816108c4565b156107ce577fdd62ed3e00000000000000000000000000000000000000000000000000000000610b005233610b045230610b24526020610c006044610b00845afa806107a4576107a4610743565b5060203d10156107b357600080fd5b82610c005110156107ce576107c983838361083e565b610839565b7f23b872dd00000000000000000000000000000000000000000000000000000000610b005233610b045281610b245282610b44526020610c006064610b006000855af13d6001610c0051146020821015168115178216915050806108375761083784848461083e565b505b505050565b7fbca8c7b500000000000000000000000000000000000000000000000000000000610b005280610b04526040610b24526064610b44527f23b872dd00000000000000000000000000000000000000000000000000000000610b645233610b685281610b885282610ba85260008060c8610b006000610a60515af161083957610839610743565b600081600052600161010083061b60016101006020600020061b1780610a8051821614915050919050565b82811015610929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020390610ba9565b95945050505050565b6040517f6eb224cb0000000000000000000000000000000000000000000000000000000081523090636eb224cb906109909084907f000000000000000000000000000000000000000000000000000000000000000090600401610a93565b600060405180830381600087803b1580156109aa57600080fd5b505af11580156109be573d6000803e3d6000fd5b5050505050565b6000806000806000608086880312156109dc578081fd5b853567ffffffffffffffff808211156109f3578283fd5b818801915088601f830112610a06578283fd5b813581811115610a14578384fd5b8960208083028501011115610a27578384fd5b6020928301975095505086013592506040860135915060608601358015158114610a4f578182fd5b809150509295509295909350565b90815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000092909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b6000602080835283518082850152825b81811015610b0757858101830151858201604001528201610aeb565b81811115610b185783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60208082526022908201527f556e6973776170466561747572652f496e76616c6964546f6b656e734c656e6760408201527f7468000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f556e6973776170466561747572652f556e646572426f7567687400000000000060408201526060019056fea2646970667358221220db2978db29758b0bdede9f7148568a66b29027c69f656f56ad4e3b624415657864736f6c634300060c0033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f740b67da229f2f10bcbd38a7979992fcc71b8eb0000100800000480002c00401000000820000000000000020000001010800001

Deployed Bytecode

0x60806040526004361061005a5760003560e01c80638fd3ab80116100435780638fd3ab80146100ac578063d925a56d146100ce578063d9627aa4146100e35761005a565b8063031b905c1461005f5780636ae4b4f71461008a575b600080fd5b34801561006b57600080fd5b506100746100f6565b6040516100819190610a5d565b60405180910390f35b34801561009657600080fd5b5061009f61011a565b6040516100819190610adb565b3480156100b857600080fd5b506100c1610153565b6040516100819190610a66565b3480156100da57600080fd5b506100746101a3565b6100746100f13660046109c5565b6101c7565b7f000000000000000000000000000000000000000000000001000000010000000181565b6040518060400160405280600e81526020017f556e69737761704665617475726500000000000000000000000000000000000081525081565b600061017e7fd9627aa400000000000000000000000000000000000000000000000000000000610932565b507f2c64c5ef0000000000000000000000000000000000000000000000000000000090565b7f0000100800000480002c0040100000082000000000000002000000101080000181565b60006001851161020c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020390610b4c565b60405180910390fd5b506004803560248101610a0052610a208390527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2610a40527f000000000000000000000000f740b67da229f2f10bcbd38a7979992fcc71b8eb610a60527f0000100800000480002c00401000000820000000000000020000001010800001610a805284917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91013501600080805b8381101561055e576102cb816105e1565b6102d7600183016105e1565b93506102e284610606565b6102eb82610606565b108380610303576102fc868461062e565b9050600094505b836103d95773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee831480156103c1578b341461033157600080fd5b610a405193507fd0e30db000000000000000000000000000000000000000000000000000000000610b00526000806004610b008f885af161037457610374610743565b7fa9059cbb00000000000000000000000000000000000000000000000000000000610b005281610b04528b610b24526000806044610b006000885af16103bc576103bc610743565b6103d7565b34156103cc57600080fd5b6103d78c838661074d565b505b7f0902f1ac00000000000000000000000000000000000000000000000000000000610b00526040610c006004610b00845afa61041757610417610743565b60403d101561042557600080fd5b8792506000808315801561044457610c20519250610c00519150610451565b610c00519250610c205191505b506e01000000000000000000000000000085111561046e57600080fd5b6103e585026103e883028101828202049a5050505060009250866001850114600081146104c45773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee871480156104ba573094506104be565b3394505b506104df565b6104d96104d3600287016105e1565b8861062e565b95508593505b507f022c0d9f00000000000000000000000000000000000000000000000000000000610b005281801561051c576000610b045288610b2452610528565b88610b04526000610b24525b5082610b44526080610b64526000610b845260008060a4610b006000855af161055357610553610743565b5050506001016102ba565b505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8114156105da577f2e1a7d4d00000000000000000000000000000000000000000000000000000000610b005282610b04526000806024610b006000610a40515af16105c2576105c2610743565b6000806000610b0086335af16105da576105da610743565b50506108ef565b610a005173ffffffffffffffffffffffffffffffffffffffff60209290920201351690565b8073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8114156106295750610a40515b919050565b600061063982610606565b915061064483610606565b9250828210801561065e5783610b145282610b0052610669565b82610b145283610b00525b506028610b0c20610a205180156106ce577fffc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac0000000000000000000000610b005281610b15527fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303610b355261071e565b7fff5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000610b005281610b15527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f610b35525b50506055610b002073ffffffffffffffffffffffffffffffffffffffff169392505050565b3d6000803e3d6000fd5b610756816108c4565b156107ce577fdd62ed3e00000000000000000000000000000000000000000000000000000000610b005233610b045230610b24526020610c006044610b00845afa806107a4576107a4610743565b5060203d10156107b357600080fd5b82610c005110156107ce576107c983838361083e565b610839565b7f23b872dd00000000000000000000000000000000000000000000000000000000610b005233610b045281610b245282610b44526020610c006064610b006000855af13d6001610c0051146020821015168115178216915050806108375761083784848461083e565b505b505050565b7fbca8c7b500000000000000000000000000000000000000000000000000000000610b005280610b04526040610b24526064610b44527f23b872dd00000000000000000000000000000000000000000000000000000000610b645233610b685281610b885282610ba85260008060c8610b006000610a60515af161083957610839610743565b600081600052600161010083061b60016101006020600020061b1780610a8051821614915050919050565b82811015610929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020390610ba9565b95945050505050565b6040517f6eb224cb0000000000000000000000000000000000000000000000000000000081523090636eb224cb906109909084907f000000000000000000000000f9b30557afcf76ea82c04015d80057fa2147dfa990600401610a93565b600060405180830381600087803b1580156109aa57600080fd5b505af11580156109be573d6000803e3d6000fd5b5050505050565b6000806000806000608086880312156109dc578081fd5b853567ffffffffffffffff808211156109f3578283fd5b818801915088601f830112610a06578283fd5b813581811115610a14578384fd5b8960208083028501011115610a27578384fd5b6020928301975095505086013592506040860135915060608601358015158114610a4f578182fd5b809150509295509295909350565b90815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000092909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b6000602080835283518082850152825b81811015610b0757858101830151858201604001528201610aeb565b81811115610b185783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60208082526022908201527f556e6973776170466561747572652f496e76616c6964546f6b656e734c656e6760408201527f7468000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f556e6973776170466561747572652f556e646572426f7567687400000000000060408201526060019056fea2646970667358221220db2978db29758b0bdede9f7148568a66b29027c69f656f56ad4e3b624415657864736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f740b67da229f2f10bcbd38a7979992fcc71b8eb0000100800000480002c00401000000820000000000000020000001010800001

-----Decoded View---------------
Arg [0] : weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : allowanceTarget (address): 0xF740B67dA229f2f10bcBd38A7979992fCC71B8Eb
Arg [2] : greedyTokensBloomFilter (bytes32): 0x0000100800000480002c00401000000820000000000000020000001010800001

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 000000000000000000000000f740b67da229f2f10bcbd38a7979992fcc71b8eb
Arg [2] : 0000100800000480002c00401000000820000000000000020000001010800001


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.