ETH Price: $1,852.57 (-0.56%)
Gas: 0.05 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Zap In166903172023-02-23 9:51:111097 days ago1677145871IN
0xb2d75b4c...f684F3032
0.01 ETH0.0061250323.97630035
Zap In166902952023-02-23 9:46:471097 days ago1677145607IN
0xb2d75b4c...f684F3032
0 ETH0.0082556125.64674422
Zap In164915492023-01-26 14:20:471125 days ago1674742847IN
0xb2d75b4c...f684F3032
0.01 ETH0.0051136121.45874217
Zap In164915492023-01-26 14:20:471125 days ago1674742847IN
0xb2d75b4c...f684F3032
0.01 ETH0.0054805621.45874217
Zap In159795102022-11-16 2:08:471196 days ago1668564527IN
0xb2d75b4c...f684F3032
0.11 ETH0.0036188314.16629418
Zap In155669842022-09-19 10:31:231254 days ago1663583483IN
0xb2d75b4c...f684F3032
15 ETH0.001869426.87203919
Zap In155357782022-09-15 0:00:311258 days ago1663200031IN
0xb2d75b4c...f684F3032
0 ETH0.0066028219.66313096
Zap In154757182022-09-05 4:17:431268 days ago1662351463IN
0xb2d75b4c...f684F3032
0 ETH0.00284746.70467775
Zap In154519132022-09-01 8:47:511272 days ago1662022071IN
0xb2d75b4c...f684F3032
0.01 ETH0.0035445413.02852479
Set Approvals Fo...154353902022-08-29 17:20:561275 days ago1661793656IN
0xb2d75b4c...f684F3032
0 ETH0.0019125830.74295909
Set Approvals Fo...154352402022-08-29 16:44:341275 days ago1661791474IN
0xb2d75b4c...f684F3032
0 ETH0.0007576716.79547524
Zap In152861252022-08-06 2:38:191298 days ago1659753499IN
0xb2d75b4c...f684F3032
0 ETH0.003603078.08347503
Zap In152623882022-08-02 9:52:581302 days ago1659433978IN
0xb2d75b4c...f684F3032
0 ETH0.003944688.75530428
Zap In152484282022-07-31 5:42:241304 days ago1659246144IN
0xb2d75b4c...f684F3032
0 ETH0.001776876.33296721
Zap In152481112022-07-31 4:30:091304 days ago1659241809IN
0xb2d75b4c...f684F3032
0 ETH0.001767433.96569777
Zap In152059892022-07-24 15:01:411311 days ago1658674901IN
0xb2d75b4c...f684F3032
0 ETH0.0048922816.24807861
Zap In151821762022-07-20 22:27:091314 days ago1658356029IN
0xb2d75b4c...f684F3032
0 ETH0.0066974921.85003127
Zap In151577052022-07-17 3:12:551318 days ago1658027575IN
0xb2d75b4c...f684F3032
0 ETH0.00373898.81390538
Zap In151390302022-07-14 6:19:041321 days ago1657779544IN
0xb2d75b4c...f684F3032
0.005 ETH0.0056351112.42883843
Zap In151387242022-07-14 5:02:441321 days ago1657774964IN
0xb2d75b4c...f684F3032
0 ETH0.00803318.59250384
Zap In151238142022-07-11 21:37:521323 days ago1657575472IN
0xb2d75b4c...f684F3032
0.01 ETH0.0153951642.15163295
Zap In151238112022-07-11 21:37:291323 days ago1657575449IN
0xb2d75b4c...f684F3032
0.01 ETH0.0187858141.93064798
Zap In151064462022-07-09 5:26:041326 days ago1657344364IN
0xb2d75b4c...f684F3032
0 ETH0.002764448.15905288
Zap In150432952022-06-29 4:41:521336 days ago1656477712IN
0xb2d75b4c...f684F3032
0.2 ETH0.0150179433.91004146
Zap In150203272022-06-24 21:28:491340 days ago1656106129IN
0xb2d75b4c...f684F3032
0 ETH0.0107187323.71528184
View all transactions

Latest 20 internal transactions

Advanced mode:
Parent Transaction Hash Method Block
From
To
Add_liquidity166903172023-02-23 9:51:111097 days ago1677145871
0xb2d75b4c...f684F3032
0.01 ETH
Add_liquidity164915492023-01-26 14:20:471125 days ago1674742847
0xb2d75b4c...f684F3032
0.01 ETH
Add_liquidity164915492023-01-26 14:20:471125 days ago1674742847
0xb2d75b4c...f684F3032
0.01 ETH
Add_liquidity159795102022-11-16 2:08:471196 days ago1668564527
0xb2d75b4c...f684F3032
0.11 ETH
Add_liquidity155669842022-09-19 10:31:231254 days ago1663583483
0xb2d75b4c...f684F3032
15 ETH
Add_liquidity154519132022-09-01 8:47:511272 days ago1662022071
0xb2d75b4c...f684F3032
0.01 ETH
Add_liquidity151390302022-07-14 6:19:041321 days ago1657779544
0xb2d75b4c...f684F3032
0.005 ETH
Add_liquidity151238142022-07-11 21:37:521323 days ago1657575472
0xb2d75b4c...f684F3032
0.01 ETH
Add_liquidity151238112022-07-11 21:37:291323 days ago1657575449
0xb2d75b4c...f684F3032
0.01 ETH
Add_liquidity150432952022-06-29 4:41:521336 days ago1656477712
0xb2d75b4c...f684F3032
0.2 ETH
-149662922022-06-15 7:22:591350 days ago1655277779
0xb2d75b4c...f684F3032
0.01 ETH
-148899272022-06-02 8:26:011363 days ago1654158361
0xb2d75b4c...f684F3032
0.05 ETH
-147361752022-05-08 12:49:541388 days ago1652014194
0xb2d75b4c...f684F3032
0.01 ETH
-147361362022-05-08 12:41:091388 days ago1652013669
0xb2d75b4c...f684F3032
0.01 ETH
-147359192022-05-08 11:51:001388 days ago1652010660
0xb2d75b4c...f684F3032
0.04 ETH
-147331792022-05-08 1:20:431388 days ago1651972843
0xb2d75b4c...f684F3032
1 ETH
-146715652022-04-28 7:37:151398 days ago1651131435
0xb2d75b4c...f684F3032
0.002 ETH
-146660302022-04-27 10:46:261399 days ago1651056386
0xb2d75b4c...f684F3032
0.002 ETH
-146631302022-04-26 23:47:201399 days ago1651016840
0xb2d75b4c...f684F3032
0.25 ETH
-146492422022-04-24 19:17:181402 days ago1650827838
0xb2d75b4c...f684F3032
0.4 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ZapSwapCurve

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 7500 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.0;

import "../libraries/Authorizable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../interfaces/IVault.sol";
import "../interfaces/ICurvePool.sol";

// TODO Due to the nature of the curve contracts, there are a number of design
// decisions made in this contract which primarily aim to generalize integration
// with curve. Curve contracts have often an inconsistent interface to many
// functions in their contracts which has influenced the design of this contract
// to target curve pool functions using function signatures computed off-chain.
// The validation of this and other features of this contract stem from this
// problem, for instance, the curve pool contracts target their underlying
// tokens using fixed-length dimensional arrays of length 2 or 3. We could
// harden this contract further by utilizing the "coins" function on the curve
// contract which would enable this contract validate that our input structure
// is correct. However, this would also run into problems as the guarantee of
// consistency of the "coins" function is also in question across the suite of
// pools in the curve ecosystem. There may be a solution to mitigate this
// problem but may be more trouble than it's worth.

/// @title ZapCurveTokenToPrincipalToken
/// @notice Allows the user to buy and sell principal tokens using a wider
/// array of tokens
/// @dev This contract introduces the concept of "root tokens" which are the
/// set of constituent tokens for a given curve pool. Each principal token
/// is constructed by a yield-generating position which in this case will be
/// represented by a curve LP token. This is referred to as the "base token"
/// and in the case where the user wishes to purchase or sell a principal token,
/// it can only be done so by using this token.
///
/// What this contract intends to do is enable the user purchase or sell
/// a position using those "root tokens" which would garner significant UX
/// improvements. The flow in the case of purchasing is as follows, the root
/// tokens are added as liquidity into the correct curve pool, giving a curve
/// "LP token" or "base token". Subsequently this is then used to purchase the
/// principal token. Selling works similarly but in the reverse direction.
///
/// Ex- Alice bought (x) amount curve LP token (let's say crvLUSD token) using LUSD (root token)
/// purchased (x) amount can be used to purchase the principal token by putting that amount
/// in the wrapped position contract.
contract ZapSwapCurve is Authorizable, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using Address for address;

    // Store the accessibility state of the contract
    bool public isFrozen;

    // A constant to represent ether
    address internal constant _ETH_CONSTANT =
        address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

    // Reference to the main balancer vault
    IVault internal immutable _balancer;

    /////////////////////////
    /// Zap In Data Structure
    /////////////////////////

    struct ZapInInfo {
        // The balancerPoolId references the particular pool in the balancer
        // contract which is used to exchange for the principal token
        bytes32 balancerPoolId;
        // The recipient is a target address the sender can send the resulting
        // principal tokens to
        address recipient;
        // Address of the principalToken
        IAsset principalToken;
        // The minimum amount of principal tokens the user expects to receive
        uint256 minPtAmount;
        // The time into the future for which the trade can happen
        uint256 deadline;
        // Some curvePools have themselves a dependent lpToken "root" which
        // this contract accommodates zapping through. This flag indicates if
        // such an action is necessary
        bool needsChildZap;
    }

    struct ZapCurveLpIn {
        // Address of target curvePool for which liquidity will be added
        // giving this contract the lpTokens necessary to swap for the
        // principalTokens
        address curvePool;
        // The target lpToken which will be received
        IERC20 lpToken;
        // Array of amounts which are structured in reference to the
        // "add_liquidity" function in the related curvePool. These in all
        // cases come in either fixed-length arrays of length 2 or 3
        uint256[] amounts;
        // Similar to "amounts", these are the reference token contract
        // addresses also ordered as per the inconsistent interface of the
        // "add_liquidity" curvePool function
        address[] roots;
        // Only relevant when there is a childZap, it references what
        // index in the amounts array of the main "zap" the resultant
        // number of lpTokens should be added to
        uint256 parentIdx;
        // The minimum amount of LP tokens expected to receive when adding
        // liquidity
        uint256 minLpAmount;
    }

    ///////////////////////////
    /// Zap Out Data Structure
    //////////////////////////

    struct ZapCurveLpOut {
        // Address of the curvePool for which an amount of lpTokens
        // is swapped for an amount of single root tokens
        address curvePool;
        // The contract address of the curve pools lpToken
        IERC20 lpToken;
        // This is the index of the target root we are swapping for
        int128 rootTokenIdx;
        // Address of the rootToken we are swapping for
        address rootToken;
        // This is the selector for deciding between the two differing curve
        // interfaces for the add
        bool curveRemoveLiqFnIsUint256;
    }

    struct ZapOutInfo {
        // Pool id of balancer pool that is used to exchange a users
        // amount of principal tokens
        bytes32 balancerPoolId;
        // Address of the principal token
        IAsset principalToken;
        // Amount of principal tokens the user wishes to swap for
        uint256 principalTokenAmount;
        // The recipient is the address the tokens which are to be swapped for
        // will be sent to
        address payable recipient;
        // The minimum amount base tokens the user is expecting
        uint256 minBaseTokenAmount;
        // The minimum amount root tokens the user is expecting
        uint256 minRootTokenAmount;
        // Timestamp into the future for which a transaction is valid for
        uint256 deadline;
        // If the target root token is sourced via two curve pool swaps, then
        // this is to be flagged as true
        bool targetNeedsChildZap;
    }

    /// @notice Memory encoding of the permit data
    struct PermitData {
        IERC20Permit tokenContract;
        address spender;
        uint256 amount;
        uint256 expiration;
        bytes32 r;
        bytes32 s;
        uint8 v;
    }

    /// @notice Sets the msg.sender as authorized and also set it as the owner
    ///         in the authorizable contract.
    /// @param __balancer The balancer vault contract
    constructor(IVault __balancer) {
        _authorize(msg.sender);
        _balancer = __balancer;
        isFrozen = false;
    }

    /// @notice Requires that the contract is not frozen
    modifier notFrozen() {
        require(!isFrozen, "Contract frozen");
        _;
    }

    // Allow this contract to receive ether
    receive() external payable {}

    /// @notice Allows an authorized address to freeze or unfreeze this contract
    /// @param _newState True for frozen and false for unfrozen
    function setIsFrozen(bool _newState) external onlyAuthorized {
        isFrozen = _newState;
    }

    /// @notice Takes the input permit calls and executes them
    /// @param data The array which encodes the set of permit calls to make
    modifier preApproval(PermitData[] memory data) {
        // If permit calls are provided we make try to make them
        _permitCall(data);
        _;
    }

    /// @notice Makes permit calls indicated by a struct
    /// @param data the struct which has the permit calldata
    function _permitCall(PermitData[] memory data) internal {
        // Make the permit call to the token in the data field using
        // the fields provided.
        if (data.length != 0) {
            // We make permit calls for each indicated call
            for (uint256 i = 0; i < data.length; i++) {
                data[i].tokenContract.permit(
                    msg.sender,
                    data[i].spender,
                    data[i].amount,
                    data[i].expiration,
                    data[i].v,
                    data[i].r,
                    data[i].s
                );
            }
        }
    }

    /// @notice This function sets approvals on all ERC20 tokens.
    /// @param tokens An array of token addresses which are to be approved
    /// @param spenders An array of contract addresses, most likely curve and
    /// balancer pool addresses
    /// @param amounts An array of amounts for which at each index, the spender
    /// from the same index in the spenders array is approved to use the token
    /// at the equivalent index of the token array on behalf of this contract
    function setApprovalsFor(
        address[] memory tokens,
        address[] memory spenders,
        uint256[] memory amounts
    ) external onlyAuthorized {
        require(tokens.length == spenders.length, "Incorrect length");
        require(tokens.length == amounts.length, "Incorrect length");
        for (uint256 i = 0; i < tokens.length; i++) {
            // Below call is to make sure that previous allowance shouldn't revert the transaction
            // It is just a safety pattern to use.
            IERC20(tokens[i]).safeApprove(spenders[i], uint256(0));
            IERC20(tokens[i]).safeApprove(spenders[i], amounts[i]);
        }
    }

    /// @notice zapIn Exchanges a number of tokens which are used in a specific
    /// curve pool(s) for a principal token.
    /// @param _info See ZapInInfo struct
    /// @param _zap See ZapCurveLpIn struct - This is the "main" or parent zap
    /// which produces the lp token necessary to swap for the principal token
    /// @param _childZap See ZapCurveLpIn - This is used only in cases where
    /// the "main" or "parent" zap itself is composed of another curve lp token
    /// which can be accessed more readily via another swap via curve
    function zapIn(
        ZapInInfo memory _info,
        ZapCurveLpIn memory _zap,
        ZapCurveLpIn memory _childZap,
        PermitData[] memory _permitData
    )
        external
        payable
        nonReentrant
        notFrozen
        preApproval(_permitData)
        returns (uint256 ptAmount)
    {
        // Instantiation of the context amount container which is used to track
        // amounts to be swapped in the final curve zap.
        uint256[3] memory ctx;

        // Only execute the childZap if it is necessary
        if (_info.needsChildZap) {
            uint256 _amount = _zapCurveLpIn(
                _childZap,
                // The context array is unnecessary for the childZap and so we
                // can just put a dud array in place of it
                [uint256(0), uint256(0), uint256(0)]
            );
            // When a childZap happens, we add the amount of lpTokens gathered
            // from it to the relevant root index of the "main" zap
            ctx[_childZap.parentIdx] += _amount;
        }

        // Swap an amount of "root" tokens on curve for the lp token that is
        // used to then purchase the principal token
        uint256 baseTokenAmount = _zapCurveLpIn(_zap, ctx);

        // Purchase of "ptAmount" of principal tokens
        ptAmount = _balancer.swap(
            IVault.SingleSwap({
                poolId: _info.balancerPoolId,
                kind: IVault.SwapKind.GIVEN_IN,
                assetIn: IAsset(address(_zap.lpToken)),
                assetOut: _info.principalToken,
                amount: baseTokenAmount,
                userData: "0x00"
            }),
            IVault.FundManagement({
                sender: address(this),
                fromInternalBalance: false,
                recipient: payable(_info.recipient),
                toInternalBalance: false
            }),
            _info.minPtAmount,
            _info.deadline
        );
    }

    /// @notice This function will add liquidity to a target curve pool,
    /// returning some amount of LP tokens as a result. This is effectively
    /// swapping amounts of the dependent curve pool tokens for the LP token
    /// which will be used elsewhere
    /// @param _zap ZapCurveLpIn struct
    /// @param _ctx fixed length array used as an amounts container between the
    /// zap and childZap and also makes the transition from a dynamic-length
    /// array to a fixed-length which is required for the actual call to add
    /// liquidity to the curvePool
    function _zapCurveLpIn(ZapCurveLpIn memory _zap, uint256[3] memory _ctx)
        internal
        returns (uint256)
    {
        // All curvePools have either 2 or 3 "root" tokens
        require(
            _zap.amounts.length == 2 || _zap.amounts.length == 3,
            "!(2 >= amounts.length <= 3)"
        );

        // Flag to detect if a zap to curve should be made
        bool shouldMakeZap = false;
        for (uint8 i = 0; i < _zap.amounts.length; i++) {
            bool zapIndexHasAmount = _zap.amounts[i] > 0;
            // If either the _ctx or zap amounts array has an index with an
            // amount > 0 we must zap curve
            shouldMakeZap = (zapIndexHasAmount || _ctx[i] > 0)
                ? true
                : shouldMakeZap;

            // if there is no amount at this index we can escape the loop earlier
            if (!zapIndexHasAmount) continue;

            if (_zap.roots[i] == _ETH_CONSTANT) {
                // Must check we do not unintentionally send ETH
                require(msg.value == _zap.amounts[i], "incorrect value");

                // We build the context container with our amounts
                _ctx[i] += _zap.amounts[i];
            } else {
                uint256 beforeAmount = _getBalanceOf(IERC20(_zap.roots[i]));

                // In the case of swapping an ERC20 "root" we must transfer them
                // to this contract in order to make the exchange
                IERC20(_zap.roots[i]).safeTransferFrom(
                    msg.sender,
                    address(this),
                    _zap.amounts[i]
                );

                // Due to rounding issues of some tokens, we use the
                // differential token balance of this contract
                _ctx[i] += _getBalanceOf(IERC20(_zap.roots[i])) - beforeAmount;
            }
        }

        // When there is nothing to swap for on curve we short-circuit
        if (!shouldMakeZap) {
            return 0;
        }
        uint256 beforeLpTokenBalance = _getBalanceOf(_zap.lpToken);

        if (_zap.amounts.length == 2) {
            ICurvePool(_zap.curvePool).add_liquidity{ value: msg.value }(
                [_ctx[0], _ctx[1]],
                _zap.minLpAmount
            );
        } else {
            ICurvePool(_zap.curvePool).add_liquidity{ value: msg.value }(
                [_ctx[0], _ctx[1], _ctx[2]],
                _zap.minLpAmount
            );
        }

        return _getBalanceOf(_zap.lpToken) - beforeLpTokenBalance;
    }

    /// @notice zapOut Allows users sell their principalTokens and subsequently
    /// swap the resultant curve LP token for one of its dependent "root tokens"
    /// @param _info See ZapOutInfo
    /// @param _zap See ZapCurveLpOut
    /// @param _childZap See ZapCurveLpOut
    function zapOut(
        ZapOutInfo memory _info,
        ZapCurveLpOut memory _zap,
        ZapCurveLpOut memory _childZap,
        PermitData[] memory _permitData
    )
        external
        payable
        nonReentrant
        notFrozen
        preApproval(_permitData)
        returns (uint256 amount)
    {
        // First, principalTokenAmount of principal tokens transferred
        // from sender to this contract
        IERC20(address(_info.principalToken)).safeTransferFrom(
            msg.sender,
            address(this),
            _info.principalTokenAmount
        );

        // Swaps an amount of users principal tokens for baseTokens, which
        // are the lpToken specified in the zap argument
        uint256 baseTokenAmount = _balancer.swap(
            IVault.SingleSwap({
                poolId: _info.balancerPoolId,
                kind: IVault.SwapKind.GIVEN_IN,
                assetIn: _info.principalToken,
                assetOut: IAsset(address(_zap.lpToken)),
                amount: _info.principalTokenAmount,
                userData: "0x00"
            }),
            IVault.FundManagement({
                sender: address(this),
                fromInternalBalance: false,
                recipient: payable(address(this)),
                toInternalBalance: false
            }),
            _info.minBaseTokenAmount,
            _info.deadline
        );

        // Swap the baseTokens for a target root. In the case of where the
        // specified token the user wants is part of the childZap, the zap that
        // occurs is to swap the baseTokens to the lpToken specified in the
        // childZap struct. If there is no childZap, then the contract sends
        // the tokens to the recipient
        amount = _zapCurveLpOut(
            _zap,
            baseTokenAmount,
            _info.targetNeedsChildZap ? 0 : _info.minRootTokenAmount,
            _info.targetNeedsChildZap ? payable(address(this)) : _info.recipient
        );

        // Execute the childZap is specified to do so
        if (_info.targetNeedsChildZap) {
            amount = _zapCurveLpOut(
                _childZap,
                amount,
                _info.minRootTokenAmount,
                _info.recipient
            );
        }
    }

    /// @notice Swaps an amount of curve LP tokens for a single root token
    /// @param _zap See ZapCurveLpOut
    /// @param _lpTokenAmount This is the amount of lpTokens we are swapping
    /// with
    /// @param _minRootTokenAmount This is the minimum amount of "root" tokens
    /// the user expects to swap for. Used only in the final zap when executed
    /// under zapOut
    /// @param _recipient The address which the outputs tokens are to be sent
    /// to. When there is a second zap to occur, in the first zap the recipient
    /// should be this address
    function _zapCurveLpOut(
        ZapCurveLpOut memory _zap,
        uint256 _lpTokenAmount,
        uint256 _minRootTokenAmount,
        address payable _recipient
    ) internal returns (uint256 rootAmount) {
        // Flag to detect if we are sending to recipient
        bool transferToRecipient = address(this) != _recipient;
        uint256 beforeAmount = _zap.rootToken == _ETH_CONSTANT
            ? address(this).balance
            : _getBalanceOf(IERC20(_zap.rootToken));

        if (_zap.curveRemoveLiqFnIsUint256) {
            ICurvePool(_zap.curvePool).remove_liquidity_one_coin(
                _lpTokenAmount,
                uint256(int256(_zap.rootTokenIdx)),
                _minRootTokenAmount
            );
        } else {
            ICurvePool(_zap.curvePool).remove_liquidity_one_coin(
                _lpTokenAmount,
                _zap.rootTokenIdx,
                _minRootTokenAmount
            );
        }

        // ETH case
        if (_zap.rootToken == _ETH_CONSTANT) {
            // Get ETH balance of current contract
            rootAmount = address(this).balance - beforeAmount;
            // if address does not equal this contract we send funds to recipient
            if (transferToRecipient) {
                // Send rootAmount of ETH to the user-specified recipient
                _recipient.transfer(rootAmount);
            }
        } else {
            // Get balance of root token that was swapped
            rootAmount = _getBalanceOf(IERC20(_zap.rootToken)) - beforeAmount;
            // Send tokens to recipient
            if (transferToRecipient) {
                IERC20(_zap.rootToken).safeTransferFrom(
                    address(this),
                    _recipient,
                    rootAmount
                );
            }
        }
    }

    function _getBalanceOf(IERC20 _token) internal view returns (uint256) {
        return _token.balanceOf(address(this));
    }
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.7.0;

contract Authorizable {
    // This contract allows a flexible authorization scheme

    // The owner who can change authorization status
    address public owner;
    // A mapping from an address to its authorization status
    mapping(address => bool) public authorized;

    /// @dev We set the deployer to the owner
    constructor() {
        owner = msg.sender;
    }

    /// @dev This modifier checks if the msg.sender is the owner
    modifier onlyOwner() {
        require(msg.sender == owner, "Sender not owner");
        _;
    }

    /// @dev This modifier checks if an address is authorized
    modifier onlyAuthorized() {
        require(isAuthorized(msg.sender), "Sender not Authorized");
        _;
    }

    /// @dev Returns true if an address is authorized
    /// @param who the address to check
    /// @return true if authorized false if not
    function isAuthorized(address who) public view returns (bool) {
        return authorized[who];
    }

    /// @dev Privileged function authorize an address
    /// @param who the address to authorize
    function authorize(address who) external onlyOwner {
        _authorize(who);
    }

    /// @dev Privileged function to de authorize an address
    /// @param who The address to remove authorization from
    function deauthorize(address who) external onlyOwner {
        authorized[who] = false;
    }

    /// @dev Function to change owner
    /// @param who The new owner address
    function setOwner(address who) public onlyOwner {
        owner = who;
    }

    /// @dev Inheritable function which authorizes someone
    /// @param who the address to authorize
    function _authorize(address who) internal {
        authorized[who] = true;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 6 of 10 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

pragma solidity ^0.8.0;

import "./IAsset.sol";

// This interface is used instead of importing one from balancer contracts to
// resolve version conflicts
interface IVault {
    enum SwapKind {
        GIVEN_IN,
        GIVEN_OUT
    }

    enum PoolSpecialization {
        GENERAL,
        MINIMAL_SWAP_INFO,
        TWO_TOKEN
    }

    struct SingleSwap {
        bytes32 poolId;
        SwapKind kind;
        IAsset assetIn;
        IAsset assetOut;
        uint256 amount;
        bytes userData;
    }

    struct FundManagement {
        address sender;
        bool fromInternalBalance;
        address payable recipient;
        bool toInternalBalance;
    }

    function swap(
        SingleSwap memory singleSwap,
        FundManagement memory funds,
        uint256 limit,
        uint256 deadline
    ) external payable returns (uint256);

    function getPool(bytes32 poolId)
        external
        view
        returns (address, PoolSpecialization);
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

interface ICurvePool {
    function add_liquidity(uint256[2] memory amountCtx, uint256 minAmount)
        external
        payable;

    function add_liquidity(uint256[3] memory amountCtx, uint256 minAmount)
        external
        payable;

    function remove_liquidity_one_coin(
        uint256 amountLp,
        uint256 idx,
        uint256 minAmount
    ) external payable;

    function remove_liquidity_one_coin(
        uint256 amount,
        int128 idx,
        uint256 minAmount
    ) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 10 of 10 : IAsset.sol
pragma solidity ^0.8.0;

// This interface is used instead of importing one from balancer contracts to
// resolve version conflicts
interface IAsset {

}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 7500
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IVault","name":"__balancer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"deauthorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"spenders","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setApprovalsFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_newState","type":"bool"}],"name":"setIsFrozen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"balancerPoolId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"contract IAsset","name":"principalToken","type":"address"},{"internalType":"uint256","name":"minPtAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"needsChildZap","type":"bool"}],"internalType":"struct ZapSwapCurve.ZapInInfo","name":"_info","type":"tuple"},{"components":[{"internalType":"address","name":"curvePool","type":"address"},{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"roots","type":"address[]"},{"internalType":"uint256","name":"parentIdx","type":"uint256"},{"internalType":"uint256","name":"minLpAmount","type":"uint256"}],"internalType":"struct ZapSwapCurve.ZapCurveLpIn","name":"_zap","type":"tuple"},{"components":[{"internalType":"address","name":"curvePool","type":"address"},{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"roots","type":"address[]"},{"internalType":"uint256","name":"parentIdx","type":"uint256"},{"internalType":"uint256","name":"minLpAmount","type":"uint256"}],"internalType":"struct ZapSwapCurve.ZapCurveLpIn","name":"_childZap","type":"tuple"},{"components":[{"internalType":"contract IERC20Permit","name":"tokenContract","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct ZapSwapCurve.PermitData[]","name":"_permitData","type":"tuple[]"}],"name":"zapIn","outputs":[{"internalType":"uint256","name":"ptAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"balancerPoolId","type":"bytes32"},{"internalType":"contract IAsset","name":"principalToken","type":"address"},{"internalType":"uint256","name":"principalTokenAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"minBaseTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minRootTokenAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"targetNeedsChildZap","type":"bool"}],"internalType":"struct ZapSwapCurve.ZapOutInfo","name":"_info","type":"tuple"},{"components":[{"internalType":"address","name":"curvePool","type":"address"},{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"int128","name":"rootTokenIdx","type":"int128"},{"internalType":"address","name":"rootToken","type":"address"},{"internalType":"bool","name":"curveRemoveLiqFnIsUint256","type":"bool"}],"internalType":"struct ZapSwapCurve.ZapCurveLpOut","name":"_zap","type":"tuple"},{"components":[{"internalType":"address","name":"curvePool","type":"address"},{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"int128","name":"rootTokenIdx","type":"int128"},{"internalType":"address","name":"rootToken","type":"address"},{"internalType":"bool","name":"curveRemoveLiqFnIsUint256","type":"bool"}],"internalType":"struct ZapSwapCurve.ZapCurveLpOut","name":"_childZap","type":"tuple"},{"components":[{"internalType":"contract IERC20Permit","name":"tokenContract","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct ZapSwapCurve.PermitData[]","name":"_permitData","type":"tuple[]"}],"name":"zapOut","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a06040523480156200001157600080fd5b5060405162002543380380620025438339810160408190526200003491620000a0565b600080546001600160a01b031916339081179091556001600255620000599062000079565b60601b6001600160601b0319166080526003805460ff19169055620000d0565b6001600160a01b03166000908152600160208190526040909120805460ff19169091179055565b600060208284031215620000b2578081fd5b81516001600160a01b0381168114620000c9578182fd5b9392505050565b60805160601c61244d620000f6600039600081816103fc015261086d015261244d6000f3fe6080604052600436106100c05760003560e01c80638da5cb5b11610074578063c24bca011161004e578063c24bca01146101db578063e5355a22146101fb578063fe9fbb801461020e576100c7565b80638da5cb5b14610179578063b6a5d7de1461019b578063b9181611146101bb576100c7565b806333eeb147116100a557806333eeb1471461010e57806364eda74b146101395780636a978af614610159576100c7565b806313af4035146100cc57806327c97fa5146100ee576100c7565b366100c757005b600080fd5b3480156100d857600080fd5b506100ec6100e7366004611a4b565b61022e565b005b3480156100fa57600080fd5b506100ec610109366004611a4b565b61029b565b34801561011a57600080fd5b50610123610304565b6040516101309190611efd565b60405180910390f35b34801561014557600080fd5b506100ec610154366004611aeb565b61030d565b61016c610167366004611c2d565b610363565b604051610130919061228e565b34801561018557600080fd5b5061018e6105b3565b6040516101309190611de1565b3480156101a757600080fd5b506100ec6101b6366004611a4b565b6105c2565b3480156101c757600080fd5b506101236101d6366004611a4b565b6105f8565b3480156101e757600080fd5b506100ec6101f6366004611a67565b61060d565b61016c610209366004611b23565b610778565b34801561021a57600080fd5b50610123610229366004611a4b565b6109cd565b6000546001600160a01b031633146102615760405162461bcd60e51b815260040161025890611f1b565b60405180910390fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b031633146102c55760405162461bcd60e51b815260040161025890611f1b565b6001600160a01b0316600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60035460ff1681565b610316336109cd565b6103325760405162461bcd60e51b815260040161025890611f52565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60006002805414156103875760405162461bcd60e51b81526004016102589061211f565b6002805560035460ff16156103ae5760405162461bcd60e51b8152600401610258906120e8565b816103b8816109ef565b6103e03330886040015189602001516001600160a01b0316610bb0909392919063ffffffff16565b6040805160c08101909152865181526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906352bbbe2990602081018481526020018a602001516001600160a01b0316815260200189602001516001600160a01b031681526020018a6040015181526020016040518060400160405280600481526020017f30783030000000000000000000000000000000000000000000000000000000008152508152506040518060800160405280306001600160a01b03168152602001600015158152602001306001600160a01b03168152602001600015158152508a608001518b60c001516040518563ffffffff1660e01b81526004016104f894939291906121ea565b602060405180830381600087803b15801561051257600080fd5b505af1158015610526573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054a9190611d1f565b905061058186828960e00151610564578960a00151610567565b60005b8a60e0015161057a578a6060015161057c565b305b610c53565b92508660e00151156105a4576105a185848960a001518a60600151610c53565b92505b50506001600255949350505050565b6000546001600160a01b031681565b6000546001600160a01b031633146105ec5760405162461bcd60e51b815260040161025890611f1b565b6105f581610e71565b50565b60016020526000908152604090205460ff1681565b610616336109cd565b6106325760405162461bcd60e51b815260040161025890611f52565b81518351146106535760405162461bcd60e51b81526004016102589061201d565b80518351146106745760405162461bcd60e51b81526004016102589061201d565b60005b8351811015610772576106ed8382815181106106a357634e487b7160e01b600052603260045260246000fd5b602002602001015160008684815181106106cd57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316610eb69092919063ffffffff16565b61076083828151811061071057634e487b7160e01b600052603260045260246000fd5b602002602001015183838151811061073857634e487b7160e01b600052603260045260246000fd5b60200260200101518684815181106106cd57634e487b7160e01b600052603260045260246000fd5b8061076a8161236f565b915050610677565b50505050565b600060028054141561079c5760405162461bcd60e51b81526004016102589061211f565b6002805560035460ff16156107c35760405162461bcd60e51b8152600401610258906120e8565b816107cd816109ef565b6107d5611701565b8660a001511561084557600061080886604051806060016040528060008152602001600081526020016000815250610f97565b9050808287608001516003811061082f57634e487b7160e01b600052603260045260246000fd5b602002018181516108409190612314565b905250505b60006108518783610f97565b6040805160c08101909152895181529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906352bbbe299060208101600081526020018a602001516001600160a01b031681526020018b604001516001600160a01b031681526020018481526020016040518060400160405280600481526020017f30783030000000000000000000000000000000000000000000000000000000008152508152506040518060800160405280306001600160a01b031681526020016000151581526020018c602001516001600160a01b03168152602001600015158152508b606001518c608001516040518563ffffffff1660e01b815260040161096a94939291906121ea565b602060405180830381600087803b15801561098457600080fd5b505af1158015610998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109bc9190611d1f565b600160025598975050505050505050565b6001600160a01b03811660009081526001602052604090205460ff165b919050565b8051156105f55760005b8151811015610bac57818181518110610a2257634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160a01b031663d505accf33848481518110610a5d57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151858581518110610a8957634e487b7160e01b600052603260045260246000fd5b602002602001015160400151868681518110610ab557634e487b7160e01b600052603260045260246000fd5b602002602001015160600151878781518110610ae157634e487b7160e01b600052603260045260246000fd5b602002602001015160c00151888881518110610b0d57634e487b7160e01b600052603260045260246000fd5b602002602001015160800151898981518110610b3957634e487b7160e01b600052603260045260246000fd5b602002602001015160a001516040518863ffffffff1660e01b8152600401610b679796959493929190611e33565b600060405180830381600087803b158015610b8157600080fd5b505af1158015610b95573d6000803e3d6000fd5b505050508080610ba49061236f565b9150506109f9565b5050565b610772846323b872dd60e01b858585604051602401610bd193929190611e0f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526114c2565b60608401516000906001600160a01b0383811630141591839173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee911614610c9a57610c958760600151611551565b610c9c565b475b9050866080015115610d3257865160408089015190517ff1dc3cc90000000000000000000000000000000000000000000000000000000081526001600160a01b039092169163f1dc3cc991610cfb918a91600f0b908a906004016122b0565b600060405180830381600087803b158015610d1557600080fd5b505af1158015610d29573d6000803e3d6000fd5b50505050610db5565b865160408089015190517f1a4d01d20000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691631a4d01d291610d82918a91908a90600401612297565b600060405180830381600087803b158015610d9c57600080fd5b505af1158015610db0573d6000803e3d6000fd5b505050505b60608701516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610e2d57610de8814761232c565b92508115610e28576040516001600160a01b0385169084156108fc029085906000818181858888f19350505050158015610e26573d6000803e3d6000fd5b505b610e67565b80610e3b8860600151611551565b610e45919061232c565b92508115610e67576060870151610e67906001600160a01b0316308686610bb0565b5050949350505050565b6001600160a01b0316600090815260016020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055565b801580610f5757506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063dd62ed3e90610f059030908690600401611df5565b60206040518083038186803b158015610f1d57600080fd5b505afa158015610f31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f559190611d1f565b155b610f735760405162461bcd60e51b815260040161025890612156565b610f928363095ea7b360e01b8484604051602401610bd1929190611e74565b505050565b600082604001515160021480610fb257508260400151516003145b610fce5760405162461bcd60e51b8152600401610258906121b3565b6000805b8460400151518160ff1610156112b15760008086604001518360ff168151811061100c57634e487b7160e01b600052603260045260246000fd5b6020026020010151119050808061104a57506000858360ff166003811061104357634e487b7160e01b600052603260045260246000fd5b6020020151115b6110545782611057565b60015b925080611064575061129f565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b031686606001518360ff16815181106110a957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156111785785604001518260ff16815181106110e757634e487b7160e01b600052603260045260246000fd5b6020026020010151341461110d5760405162461bcd60e51b8152600401610258906120b1565b85604001518260ff168151811061113457634e487b7160e01b600052603260045260246000fd5b6020026020010151858360ff166003811061115f57634e487b7160e01b600052603260045260246000fd5b602002018181516111709190612314565b90525061129d565b60006111b187606001518460ff16815181106111a457634e487b7160e01b600052603260045260246000fd5b6020026020010151611551565b905061122f333089604001518660ff16815181106111df57634e487b7160e01b600052603260045260246000fd5b60200260200101518a606001518760ff168151811061120e57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316610bb0909392919063ffffffff16565b8061125a88606001518560ff16815181106111a457634e487b7160e01b600052603260045260246000fd5b611264919061232c565b868460ff166003811061128757634e487b7160e01b600052603260045260246000fd5b602002018181516112989190612314565b905250505b505b806112a9816123a8565b915050610fd2565b50806112c15760009150506114bc565b60006112d08560200151611551565b9050846040015151600214156113ac5784600001516001600160a01b0316630b4c7e4d3460405180604001604052808860006003811061132057634e487b7160e01b600052603260045260246000fd5b602002015181526020018860016003811061134b57634e487b7160e01b600052603260045260246000fd5b60200201518152508860a001516040518463ffffffff1660e01b8152600401611375929190611e8d565b6000604051808303818588803b15801561138e57600080fd5b505af11580156113a2573d6000803e3d6000fd5b505050505061149f565b84600001516001600160a01b0316634515cef3346040518060600160405280886000600381106113ec57634e487b7160e01b600052603260045260246000fd5b602002015181526020018860016003811061141757634e487b7160e01b600052603260045260246000fd5b602002015181526020018860026003811061144257634e487b7160e01b600052603260045260246000fd5b60200201518152508860a001516040518463ffffffff1660e01b815260040161146c929190611ec5565b6000604051808303818588803b15801561148557600080fd5b505af1158015611499573d6000803e3d6000fd5b50505050505b806114ad8660200151611551565b6114b7919061232c565b925050505b92915050565b6000611517826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115e99092919063ffffffff16565b805190915015610f9257808060200190518101906115359190611b07565b610f925760405162461bcd60e51b815260040161025890612054565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526000906001600160a01b038316906370a0823190611599903090600401611de1565b60206040518083038186803b1580156115b157600080fd5b505afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bc9190611d1f565b60606115f88484600085611602565b90505b9392505050565b6060824710156116245760405162461bcd60e51b815260040161025890611f89565b61162d856116c2565b6116495760405162461bcd60e51b815260040161025890611fe6565b600080866001600160a01b031685876040516116659190611dc5565b60006040518083038185875af1925050503d80600081146116a2576040519150601f19603f3d011682016040523d82523d6000602084013e6116a7565b606091505b50915091506116b78282866116c8565b979650505050505050565b3b151590565b606083156116d75750816115fb565b8251156116e75782518084602001fd5b8160405162461bcd60e51b81526004016102589190611f08565b60405180606001604052806003906020820280368337509192915050565b80356109ea816123f4565b600082601f83011261173a578081fd5b8135602061174f61174a836122f0565b6122c6565b828152818101908583018385028701840188101561176b578586fd5b855b85811015611792578135611780816123f4565b8452928401929084019060010161176d565b5090979650505050505050565b600082601f8301126117af578081fd5b813560206117bf61174a836122f0565b8281528181019085830160e0808602880185018910156117dd578687fd5b865b868110156118845781838b0312156117f5578788fd5b6040805183810181811067ffffffffffffffff82111715611818576118186123de565b82526118238561171f565b815261183088860161171f565b818901528482013591810191909152606080850135908201526080808501359082015260a0808501359082015260c09061186b828601611a3a565b91810191909152855293850193918101916001016117df565b509198975050505050505050565b600082601f8301126118a2578081fd5b813560206118b261174a836122f0565b82815281810190858301838502870184018810156118ce578586fd5b855b85811015611792578135845292840192908401906001016118d0565b80356109ea81612409565b600060c08284031215611908578081fd5b61191260c06122c6565b905061191d8261171f565b815261192b6020830161171f565b6020820152604082013567ffffffffffffffff8082111561194b57600080fd5b61195785838601611892565b6040840152606084013591508082111561197057600080fd5b5061197d8482850161172a565b6060830152506080820135608082015260a082013560a082015292915050565b600060a082840312156119ae578081fd5b60405160a0810181811067ffffffffffffffff821117156119d1576119d16123de565b60405290508082356119e2816123f4565b815260208301356119f2816123f4565b60208201526040830135600f81900b8114611a0c57600080fd5b6040820152611a1d6060840161171f565b6060820152611a2e608084016118ec565b60808201525092915050565b803560ff811681146109ea57600080fd5b600060208284031215611a5c578081fd5b81356115fb816123f4565b600080600060608486031215611a7b578182fd5b833567ffffffffffffffff80821115611a92578384fd5b611a9e8783880161172a565b94506020860135915080821115611ab3578384fd5b611abf8783880161172a565b93506040860135915080821115611ad4578283fd5b50611ae186828701611892565b9150509250925092565b600060208284031215611afc578081fd5b81356115fb81612409565b600060208284031215611b18578081fd5b81516115fb81612409565b600080600080848603610120811215611b3a578283fd5b60c0811215611b47578283fd5b5060405160c0810167ffffffffffffffff8282108183111715611b6c57611b6c6123de565b8160405287358352611b806020890161171f565b6020840152611b916040890161171f565b60408401526060880135606084015260808801356080840152611bb660a089016118ec565b60a084015291955060c08701359180831115611bd0578485fd5b611bdc89848a016118f7565b955060e0880135925080831115611bf1578485fd5b611bfd89848a016118f7565b9450610100880135925080831115611c13578384fd5b5050611c218782880161179f565b91505092959194509250565b600080600080848603610260811215611c44578283fd5b61010080821215611c53578384fd5b604051915080820167ffffffffffffffff8382108183111715611c7857611c786123de565b8160405288358452611c8c60208a0161171f565b602085015260408901356040850152611ca760608a0161171f565b60608501526080890135608085015260a089013560a085015260c089013560c0850152611cd660e08a016118ec565b60e0850152839750611cea8a848b0161199d565b9650611cfa8a6101a08b0161199d565b9550610240890135935080841115611d10578485fd5b505050611c218782880161179f565b600060208284031215611d30578081fd5b5051919050565b60008151808452611d4f816020860160208601612343565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03169052565b6001600160a01b03808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b60008251611dd7818460208701612343565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b60608101818460005b6002811015611eb5578151835260209283019290910190600101611e96565b5050508260408301529392505050565b60808101818460005b6003811015611eed578151835260209283019290910190600101611ece565b5050508260608301529392505050565b901515815260200190565b6000602082526115fb6020830184611d37565b60208082526010908201527f53656e646572206e6f74206f776e657200000000000000000000000000000000604082015260600190565b60208082526015908201527f53656e646572206e6f7420417574686f72697a65640000000000000000000000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526010908201527f496e636f7272656374206c656e67746800000000000000000000000000000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252600f908201527f696e636f72726563742076616c75650000000000000000000000000000000000604082015260600190565b6020808252600f908201527f436f6e74726163742066726f7a656e0000000000000000000000000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6020808252601b908201527f212832203e3d20616d6f756e74732e6c656e677468203c3d2033290000000000604082015260600190565b600060e08252855160e083015260208601516002811061221857634e487b7160e01b82526021600452602482fd5b6101008301526040860151612231610120840182611d81565b506060860151612245610140840182611d81565b50608086015161016083015260a086015160c061018084015261226c6101a0840182611d37565b91505061227c6020830186611d8e565b60a082019390935260c0015292915050565b90815260200190565b928352600f9190910b6020830152604082015260600190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff811182821017156122e8576122e86123de565b604052919050565b600067ffffffffffffffff82111561230a5761230a6123de565b5060209081020190565b60008219821115612327576123276123c8565b500190565b60008282101561233e5761233e6123c8565b500390565b60005b8381101561235e578181015183820152602001612346565b838111156107725750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156123a1576123a16123c8565b5060010190565b600060ff821660ff8114156123bf576123bf6123c8565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146105f557600080fd5b80151581146105f557600080fdfea2646970667358221220ee329718b5ed518d6347b60ef802912c68b409558419ae0eb51b1157692e0a4c64736f6c63430008000033000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8

Deployed Bytecode

0x6080604052600436106100c05760003560e01c80638da5cb5b11610074578063c24bca011161004e578063c24bca01146101db578063e5355a22146101fb578063fe9fbb801461020e576100c7565b80638da5cb5b14610179578063b6a5d7de1461019b578063b9181611146101bb576100c7565b806333eeb147116100a557806333eeb1471461010e57806364eda74b146101395780636a978af614610159576100c7565b806313af4035146100cc57806327c97fa5146100ee576100c7565b366100c757005b600080fd5b3480156100d857600080fd5b506100ec6100e7366004611a4b565b61022e565b005b3480156100fa57600080fd5b506100ec610109366004611a4b565b61029b565b34801561011a57600080fd5b50610123610304565b6040516101309190611efd565b60405180910390f35b34801561014557600080fd5b506100ec610154366004611aeb565b61030d565b61016c610167366004611c2d565b610363565b604051610130919061228e565b34801561018557600080fd5b5061018e6105b3565b6040516101309190611de1565b3480156101a757600080fd5b506100ec6101b6366004611a4b565b6105c2565b3480156101c757600080fd5b506101236101d6366004611a4b565b6105f8565b3480156101e757600080fd5b506100ec6101f6366004611a67565b61060d565b61016c610209366004611b23565b610778565b34801561021a57600080fd5b50610123610229366004611a4b565b6109cd565b6000546001600160a01b031633146102615760405162461bcd60e51b815260040161025890611f1b565b60405180910390fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b031633146102c55760405162461bcd60e51b815260040161025890611f1b565b6001600160a01b0316600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60035460ff1681565b610316336109cd565b6103325760405162461bcd60e51b815260040161025890611f52565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60006002805414156103875760405162461bcd60e51b81526004016102589061211f565b6002805560035460ff16156103ae5760405162461bcd60e51b8152600401610258906120e8565b816103b8816109ef565b6103e03330886040015189602001516001600160a01b0316610bb0909392919063ffffffff16565b6040805160c08101909152865181526000906001600160a01b037f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c816906352bbbe2990602081018481526020018a602001516001600160a01b0316815260200189602001516001600160a01b031681526020018a6040015181526020016040518060400160405280600481526020017f30783030000000000000000000000000000000000000000000000000000000008152508152506040518060800160405280306001600160a01b03168152602001600015158152602001306001600160a01b03168152602001600015158152508a608001518b60c001516040518563ffffffff1660e01b81526004016104f894939291906121ea565b602060405180830381600087803b15801561051257600080fd5b505af1158015610526573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054a9190611d1f565b905061058186828960e00151610564578960a00151610567565b60005b8a60e0015161057a578a6060015161057c565b305b610c53565b92508660e00151156105a4576105a185848960a001518a60600151610c53565b92505b50506001600255949350505050565b6000546001600160a01b031681565b6000546001600160a01b031633146105ec5760405162461bcd60e51b815260040161025890611f1b565b6105f581610e71565b50565b60016020526000908152604090205460ff1681565b610616336109cd565b6106325760405162461bcd60e51b815260040161025890611f52565b81518351146106535760405162461bcd60e51b81526004016102589061201d565b80518351146106745760405162461bcd60e51b81526004016102589061201d565b60005b8351811015610772576106ed8382815181106106a357634e487b7160e01b600052603260045260246000fd5b602002602001015160008684815181106106cd57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316610eb69092919063ffffffff16565b61076083828151811061071057634e487b7160e01b600052603260045260246000fd5b602002602001015183838151811061073857634e487b7160e01b600052603260045260246000fd5b60200260200101518684815181106106cd57634e487b7160e01b600052603260045260246000fd5b8061076a8161236f565b915050610677565b50505050565b600060028054141561079c5760405162461bcd60e51b81526004016102589061211f565b6002805560035460ff16156107c35760405162461bcd60e51b8152600401610258906120e8565b816107cd816109ef565b6107d5611701565b8660a001511561084557600061080886604051806060016040528060008152602001600081526020016000815250610f97565b9050808287608001516003811061082f57634e487b7160e01b600052603260045260246000fd5b602002018181516108409190612314565b905250505b60006108518783610f97565b6040805160c08101909152895181529091506001600160a01b037f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c816906352bbbe299060208101600081526020018a602001516001600160a01b031681526020018b604001516001600160a01b031681526020018481526020016040518060400160405280600481526020017f30783030000000000000000000000000000000000000000000000000000000008152508152506040518060800160405280306001600160a01b031681526020016000151581526020018c602001516001600160a01b03168152602001600015158152508b606001518c608001516040518563ffffffff1660e01b815260040161096a94939291906121ea565b602060405180830381600087803b15801561098457600080fd5b505af1158015610998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109bc9190611d1f565b600160025598975050505050505050565b6001600160a01b03811660009081526001602052604090205460ff165b919050565b8051156105f55760005b8151811015610bac57818181518110610a2257634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160a01b031663d505accf33848481518110610a5d57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151858581518110610a8957634e487b7160e01b600052603260045260246000fd5b602002602001015160400151868681518110610ab557634e487b7160e01b600052603260045260246000fd5b602002602001015160600151878781518110610ae157634e487b7160e01b600052603260045260246000fd5b602002602001015160c00151888881518110610b0d57634e487b7160e01b600052603260045260246000fd5b602002602001015160800151898981518110610b3957634e487b7160e01b600052603260045260246000fd5b602002602001015160a001516040518863ffffffff1660e01b8152600401610b679796959493929190611e33565b600060405180830381600087803b158015610b8157600080fd5b505af1158015610b95573d6000803e3d6000fd5b505050508080610ba49061236f565b9150506109f9565b5050565b610772846323b872dd60e01b858585604051602401610bd193929190611e0f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526114c2565b60608401516000906001600160a01b0383811630141591839173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee911614610c9a57610c958760600151611551565b610c9c565b475b9050866080015115610d3257865160408089015190517ff1dc3cc90000000000000000000000000000000000000000000000000000000081526001600160a01b039092169163f1dc3cc991610cfb918a91600f0b908a906004016122b0565b600060405180830381600087803b158015610d1557600080fd5b505af1158015610d29573d6000803e3d6000fd5b50505050610db5565b865160408089015190517f1a4d01d20000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691631a4d01d291610d82918a91908a90600401612297565b600060405180830381600087803b158015610d9c57600080fd5b505af1158015610db0573d6000803e3d6000fd5b505050505b60608701516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610e2d57610de8814761232c565b92508115610e28576040516001600160a01b0385169084156108fc029085906000818181858888f19350505050158015610e26573d6000803e3d6000fd5b505b610e67565b80610e3b8860600151611551565b610e45919061232c565b92508115610e67576060870151610e67906001600160a01b0316308686610bb0565b5050949350505050565b6001600160a01b0316600090815260016020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055565b801580610f5757506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063dd62ed3e90610f059030908690600401611df5565b60206040518083038186803b158015610f1d57600080fd5b505afa158015610f31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f559190611d1f565b155b610f735760405162461bcd60e51b815260040161025890612156565b610f928363095ea7b360e01b8484604051602401610bd1929190611e74565b505050565b600082604001515160021480610fb257508260400151516003145b610fce5760405162461bcd60e51b8152600401610258906121b3565b6000805b8460400151518160ff1610156112b15760008086604001518360ff168151811061100c57634e487b7160e01b600052603260045260246000fd5b6020026020010151119050808061104a57506000858360ff166003811061104357634e487b7160e01b600052603260045260246000fd5b6020020151115b6110545782611057565b60015b925080611064575061129f565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b031686606001518360ff16815181106110a957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156111785785604001518260ff16815181106110e757634e487b7160e01b600052603260045260246000fd5b6020026020010151341461110d5760405162461bcd60e51b8152600401610258906120b1565b85604001518260ff168151811061113457634e487b7160e01b600052603260045260246000fd5b6020026020010151858360ff166003811061115f57634e487b7160e01b600052603260045260246000fd5b602002018181516111709190612314565b90525061129d565b60006111b187606001518460ff16815181106111a457634e487b7160e01b600052603260045260246000fd5b6020026020010151611551565b905061122f333089604001518660ff16815181106111df57634e487b7160e01b600052603260045260246000fd5b60200260200101518a606001518760ff168151811061120e57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316610bb0909392919063ffffffff16565b8061125a88606001518560ff16815181106111a457634e487b7160e01b600052603260045260246000fd5b611264919061232c565b868460ff166003811061128757634e487b7160e01b600052603260045260246000fd5b602002018181516112989190612314565b905250505b505b806112a9816123a8565b915050610fd2565b50806112c15760009150506114bc565b60006112d08560200151611551565b9050846040015151600214156113ac5784600001516001600160a01b0316630b4c7e4d3460405180604001604052808860006003811061132057634e487b7160e01b600052603260045260246000fd5b602002015181526020018860016003811061134b57634e487b7160e01b600052603260045260246000fd5b60200201518152508860a001516040518463ffffffff1660e01b8152600401611375929190611e8d565b6000604051808303818588803b15801561138e57600080fd5b505af11580156113a2573d6000803e3d6000fd5b505050505061149f565b84600001516001600160a01b0316634515cef3346040518060600160405280886000600381106113ec57634e487b7160e01b600052603260045260246000fd5b602002015181526020018860016003811061141757634e487b7160e01b600052603260045260246000fd5b602002015181526020018860026003811061144257634e487b7160e01b600052603260045260246000fd5b60200201518152508860a001516040518463ffffffff1660e01b815260040161146c929190611ec5565b6000604051808303818588803b15801561148557600080fd5b505af1158015611499573d6000803e3d6000fd5b50505050505b806114ad8660200151611551565b6114b7919061232c565b925050505b92915050565b6000611517826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115e99092919063ffffffff16565b805190915015610f9257808060200190518101906115359190611b07565b610f925760405162461bcd60e51b815260040161025890612054565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526000906001600160a01b038316906370a0823190611599903090600401611de1565b60206040518083038186803b1580156115b157600080fd5b505afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bc9190611d1f565b60606115f88484600085611602565b90505b9392505050565b6060824710156116245760405162461bcd60e51b815260040161025890611f89565b61162d856116c2565b6116495760405162461bcd60e51b815260040161025890611fe6565b600080866001600160a01b031685876040516116659190611dc5565b60006040518083038185875af1925050503d80600081146116a2576040519150601f19603f3d011682016040523d82523d6000602084013e6116a7565b606091505b50915091506116b78282866116c8565b979650505050505050565b3b151590565b606083156116d75750816115fb565b8251156116e75782518084602001fd5b8160405162461bcd60e51b81526004016102589190611f08565b60405180606001604052806003906020820280368337509192915050565b80356109ea816123f4565b600082601f83011261173a578081fd5b8135602061174f61174a836122f0565b6122c6565b828152818101908583018385028701840188101561176b578586fd5b855b85811015611792578135611780816123f4565b8452928401929084019060010161176d565b5090979650505050505050565b600082601f8301126117af578081fd5b813560206117bf61174a836122f0565b8281528181019085830160e0808602880185018910156117dd578687fd5b865b868110156118845781838b0312156117f5578788fd5b6040805183810181811067ffffffffffffffff82111715611818576118186123de565b82526118238561171f565b815261183088860161171f565b818901528482013591810191909152606080850135908201526080808501359082015260a0808501359082015260c09061186b828601611a3a565b91810191909152855293850193918101916001016117df565b509198975050505050505050565b600082601f8301126118a2578081fd5b813560206118b261174a836122f0565b82815281810190858301838502870184018810156118ce578586fd5b855b85811015611792578135845292840192908401906001016118d0565b80356109ea81612409565b600060c08284031215611908578081fd5b61191260c06122c6565b905061191d8261171f565b815261192b6020830161171f565b6020820152604082013567ffffffffffffffff8082111561194b57600080fd5b61195785838601611892565b6040840152606084013591508082111561197057600080fd5b5061197d8482850161172a565b6060830152506080820135608082015260a082013560a082015292915050565b600060a082840312156119ae578081fd5b60405160a0810181811067ffffffffffffffff821117156119d1576119d16123de565b60405290508082356119e2816123f4565b815260208301356119f2816123f4565b60208201526040830135600f81900b8114611a0c57600080fd5b6040820152611a1d6060840161171f565b6060820152611a2e608084016118ec565b60808201525092915050565b803560ff811681146109ea57600080fd5b600060208284031215611a5c578081fd5b81356115fb816123f4565b600080600060608486031215611a7b578182fd5b833567ffffffffffffffff80821115611a92578384fd5b611a9e8783880161172a565b94506020860135915080821115611ab3578384fd5b611abf8783880161172a565b93506040860135915080821115611ad4578283fd5b50611ae186828701611892565b9150509250925092565b600060208284031215611afc578081fd5b81356115fb81612409565b600060208284031215611b18578081fd5b81516115fb81612409565b600080600080848603610120811215611b3a578283fd5b60c0811215611b47578283fd5b5060405160c0810167ffffffffffffffff8282108183111715611b6c57611b6c6123de565b8160405287358352611b806020890161171f565b6020840152611b916040890161171f565b60408401526060880135606084015260808801356080840152611bb660a089016118ec565b60a084015291955060c08701359180831115611bd0578485fd5b611bdc89848a016118f7565b955060e0880135925080831115611bf1578485fd5b611bfd89848a016118f7565b9450610100880135925080831115611c13578384fd5b5050611c218782880161179f565b91505092959194509250565b600080600080848603610260811215611c44578283fd5b61010080821215611c53578384fd5b604051915080820167ffffffffffffffff8382108183111715611c7857611c786123de565b8160405288358452611c8c60208a0161171f565b602085015260408901356040850152611ca760608a0161171f565b60608501526080890135608085015260a089013560a085015260c089013560c0850152611cd660e08a016118ec565b60e0850152839750611cea8a848b0161199d565b9650611cfa8a6101a08b0161199d565b9550610240890135935080841115611d10578485fd5b505050611c218782880161179f565b600060208284031215611d30578081fd5b5051919050565b60008151808452611d4f816020860160208601612343565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03169052565b6001600160a01b03808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b60008251611dd7818460208701612343565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b60608101818460005b6002811015611eb5578151835260209283019290910190600101611e96565b5050508260408301529392505050565b60808101818460005b6003811015611eed578151835260209283019290910190600101611ece565b5050508260608301529392505050565b901515815260200190565b6000602082526115fb6020830184611d37565b60208082526010908201527f53656e646572206e6f74206f776e657200000000000000000000000000000000604082015260600190565b60208082526015908201527f53656e646572206e6f7420417574686f72697a65640000000000000000000000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526010908201527f496e636f7272656374206c656e67746800000000000000000000000000000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252600f908201527f696e636f72726563742076616c75650000000000000000000000000000000000604082015260600190565b6020808252600f908201527f436f6e74726163742066726f7a656e0000000000000000000000000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6020808252601b908201527f212832203e3d20616d6f756e74732e6c656e677468203c3d2033290000000000604082015260600190565b600060e08252855160e083015260208601516002811061221857634e487b7160e01b82526021600452602482fd5b6101008301526040860151612231610120840182611d81565b506060860151612245610140840182611d81565b50608086015161016083015260a086015160c061018084015261226c6101a0840182611d37565b91505061227c6020830186611d8e565b60a082019390935260c0015292915050565b90815260200190565b928352600f9190910b6020830152604082015260600190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff811182821017156122e8576122e86123de565b604052919050565b600067ffffffffffffffff82111561230a5761230a6123de565b5060209081020190565b60008219821115612327576123276123c8565b500190565b60008282101561233e5761233e6123c8565b500390565b60005b8381101561235e578181015183820152602001612346565b838111156107725750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156123a1576123a16123c8565b5060010190565b600060ff821660ff8114156123bf576123bf6123c8565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146105f557600080fd5b80151581146105f557600080fdfea2646970667358221220ee329718b5ed518d6347b60ef802912c68b409558419ae0eb51b1157692e0a4c64736f6c63430008000033

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

000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8

-----Decoded View---------------
Arg [0] : __balancer (address): 0xBA12222222228d8Ba445958a75a0704d566BF2C8

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
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.