ETH Price: $1,579.89 (-0.75%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Deleverage Posit...207165482024-09-10 0:10:23220 days ago1725927023IN
0x95897943...401BbAE3E
0 ETH0.00321854.39839702
Deleverage Posit...207138812024-09-09 15:14:23220 days ago1725894863IN
0x95897943...401BbAE3E
0 ETH0.008255569.61714503
Deleverage Posit...207137702024-09-09 14:52:11220 days ago1725893531IN
0x95897943...401BbAE3E
0 ETH0.008918618.12802272
Deleverage Posit...207066882024-09-08 15:08:11221 days ago1725808091IN
0x95897943...401BbAE3E
0 ETH0.002715552.3049631
Deleverage Posit...206862372024-09-05 18:40:11224 days ago1725561611IN
0x95897943...401BbAE3E
0 ETH0.003687143.53070188
Deleverage Posit...206487392024-08-31 13:06:11229 days ago1725109571IN
0x95897943...401BbAE3E
0 ETH0.001585291.33200754
Deposit And Leve...206438132024-08-30 20:34:47230 days ago1725050087IN
0x95897943...401BbAE3E
0 ETH0.001423571.58380092
Leverage Positio...206389862024-08-30 4:24:47230 days ago1724991887IN
0x95897943...401BbAE3E
0 ETH0.000492380.75510659
Deleverage Posit...206372782024-08-29 22:39:47231 days ago1724971187IN
0x95897943...401BbAE3E
0 ETH0.001524141.4
Leverage Positio...206323802024-08-29 6:14:11231 days ago1724912051IN
0x95897943...401BbAE3E
0 ETH0.001479061.25615645
Deposit And Leve...206314602024-08-29 3:07:47231 days ago1724900867IN
0x95897943...401BbAE3E
0 ETH0.000466360.72664848
Deleverage Posit...206282652024-08-28 16:25:11232 days ago1724862311IN
0x95897943...401BbAE3E
0 ETH0.00247594.47851992
Deleverage Posit...206182002024-08-27 6:42:59233 days ago1724740979IN
0x95897943...401BbAE3E
0 ETH0.001400381.0972326
Deleverage Posit...206156392024-08-26 22:05:59234 days ago1724709959IN
0x95897943...401BbAE3E
0 ETH0.00157891.280337
Deleverage Posit...206053182024-08-25 11:30:23235 days ago1724585423IN
0x95897943...401BbAE3E
0 ETH0.00129951.2
Leverage Positio...206043832024-08-25 8:22:35235 days ago1724574155IN
0x95897943...401BbAE3E
0 ETH0.001075450.88446302
Deleverage Posit...205982962024-08-24 11:55:59236 days ago1724500559IN
0x95897943...401BbAE3E
0 ETH0.000781230.80219559
Deposit And Leve...205962682024-08-24 5:07:11236 days ago1724476031IN
0x95897943...401BbAE3E
0 ETH0.001070730.86178651
Leverage Positio...205936722024-08-23 20:24:59237 days ago1724444699IN
0x95897943...401BbAE3E
0 ETH0.002408052.84191481
Leverage Positio...205936552024-08-23 20:21:35237 days ago1724444495IN
0x95897943...401BbAE3E
0 ETH0.00316042.93599246
Leverage Positio...205924742024-08-23 16:24:23237 days ago1724430263IN
0x95897943...401BbAE3E
0 ETH0.0028782.69507479
Leverage Positio...205913272024-08-23 12:34:11237 days ago1724416451IN
0x95897943...401BbAE3E
0 ETH0.003455522.21547627
Leverage Positio...205898102024-08-23 7:28:23237 days ago1724398103IN
0x95897943...401BbAE3E
0 ETH0.001453411.21936948
Leverage Positio...205870222024-08-22 22:05:47238 days ago1724364347IN
0x95897943...401BbAE3E
0 ETH0.002378891.9160443
Leverage Positio...205784812024-08-21 17:26:59239 days ago1724261219IN
0x95897943...401BbAE3E
0 ETH0.004695136.04121267
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ALE

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion
File 1 of 9 : ALE.sol
//SPDX-License-Identifier: None
pragma solidity ^0.8.0;

import "src/interfaces/IMarket.sol";
import "src/interfaces/IERC20.sol";
import "src/interfaces/ITransformHelper.sol";
import "src/util/CurveDBRHelper.sol";
import {Ownable} from "lib/openzeppelin-contracts/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol";

interface IDBR {
    function markets(address) external view returns (bool);
}

// Accelerated leverage engine
contract ALE is Ownable, ReentrancyGuard, CurveDBRHelper {
    error CollateralNotSet();
    error MarketNotSet(address market);
    error SwapFailed();
    error DOLAInvalidBorrow(uint256 expected, uint256 actual);
    error DOLAInvalidRepay(uint256 expected, uint256 actual);
    error InvalidProxyAddress();
    error InvalidHelperAddress();
    error NothingToDeposit();
    error DepositFailed(uint256 expected, uint256 actual);
    error WithdrawFailed(uint256 expected, uint256 actual);
    error TotalSupplyChanged(uint256 expected, uint256 actual);
    error CollateralIsZero();
    error NoMarket(address market);
    error WrongCollateral(address market, address buySellToken, address collateral, address helper);

    // 0x ExchangeProxy address.
    // See https://docs.0x.org/developer-resources/contract-addresses
    address payable public exchangeProxy;

    IDBR public constant DBR = IDBR(0xAD038Eb671c44b853887A7E32528FaB35dC5D710);

    struct Market {
        IERC20 buySellToken;
        IERC20 collateral;
        ITransformHelper helper;
    }

    struct Permit {
        uint256 deadline;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    struct DBRHelper {
        uint256 amountIn; // DOLA or DBR
        uint256 minOut; // DOLA or DBR
        uint256 dola; // DOLA to extra borrow or extra repay
    }

    event LeverageUp(
        address indexed market,
        address indexed account,
        uint256 dolaFlashMinted, // DOLA flash minted for buying collateral only
        uint256 collateralDeposited, // amount of collateral deposited into the escrow    
        uint256 dolaBorrowed,  // amount of DOLA borrowed on behalf of the user
        uint256 dolaForDBR   // amount of DOLA used for buying DBR
    );

    event LeverageDown(
        address indexed market,
        address indexed account,
        uint256 dolaFlashMinted, // Flash minted DOLA for repaying leverage only
        uint256 collateralSold,  // amount of collateral/underlying sold
        uint256 dolaUserRepaid,  // amount of DOLA deposited by the user as part of the repay
        uint256 dbrSoldForDola   // amount of DBR sold for DOLA
    );

    event Deposit(address indexed market, address indexed account, uint256 depositAmount);

    event NewMarket(address indexed market, address indexed buySellToken, address collateral, address indexed helper);

    event NewHelper(address indexed market, address indexed helper);

    // Mapping of market to Market structs
    // NOTE: in normal cases sellToken/buyToken is the collateral token,
    // in other cases it could be different (eg. st-yCRV is collateral, yCRV is the token to be swapped from/to DOLA)
    mapping(address => Market) public markets;

    modifier dolaSupplyUnchanged() {
        uint256 totalSupply = dola.totalSupply();
        _;
        if (totalSupply != dola.totalSupply())
            revert TotalSupplyChanged(totalSupply, dola.totalSupply());
    }

    constructor(
        address _exchangeProxy,
        address _pool
    ) Ownable(msg.sender) CurveDBRHelper(_pool) {
        exchangeProxy = payable(address(_exchangeProxy));
    }

    function setExchangeProxy(address _exchangeProxy) external onlyOwner {
        if (_exchangeProxy == address(0)) revert InvalidProxyAddress();
        exchangeProxy = payable(_exchangeProxy);
    }

    /// @notice Set the market for a collateral token
    /// @param _buySellToken The token which will be bought/sold (usually the collateral token), probably underlying if there's a helper
    /// @param _market The market contract
    /// @param _collateral The collateral token
    /// @param _helper Optional helper contract to transform collateral to buySelltoken and viceversa
    function setMarket(
        address _market,
        address _buySellToken,
        address _collateral,
        address _helper
    ) external onlyOwner {
        if(!DBR.markets(_market)) revert NoMarket(_market);

        if(_helper == address(0)) {
            if(_buySellToken != IMarket(_market).collateral() || _collateral != IMarket(_market).collateral()) {
                revert WrongCollateral(_market, _buySellToken, _collateral, _helper);
            }
        } else if (_helper != address(0) && _collateral != IMarket(_market).collateral()) {
            revert WrongCollateral(_market, _buySellToken, _collateral, _helper);
        }

        markets[_market].buySellToken = IERC20(_buySellToken);
        markets[_market].collateral = IERC20(_collateral);
        IERC20(_buySellToken).approve(_market, type(uint256).max);

        if (_buySellToken != _collateral) {
            IERC20(_collateral).approve(_market, type(uint256).max);
        } 

        if (_helper != address(0)) {
            markets[_market].helper = ITransformHelper(_helper);
            IERC20(_buySellToken).approve(_helper, type(uint256).max);
            IERC20(_collateral).approve(_helper, type(uint256).max);
        }

        emit NewMarket(_market, _buySellToken, _collateral, _helper);
    }

    /// @notice Update the helper contract
    /// @param _market The market we want to update the helper contract for
    /// @param _helper The helper contract
    function updateMarketHelper(
        address _market,
        address _helper
    ) external onlyOwner {
        if (address(markets[_market].buySellToken) == address(0)) revert MarketNotSet(_market);

        address oldHelper = address(markets[_market].helper);
        if (oldHelper != address(0)) {
            markets[_market].buySellToken.approve(oldHelper, 0);
            markets[_market].collateral.approve(oldHelper, 0);
        }

        markets[_market].helper = ITransformHelper(_helper);
        
        if (_helper != address(0)) {
            markets[_market].buySellToken.approve(_helper, type(uint256).max);
            markets[_market].collateral.approve(_helper, type(uint256).max);
        }
     

        emit NewHelper(_market, _helper);
    }

    /// @notice Leverage user position by minting DOLA, buying collateral, deposting into the user escrow and borrow DOLA on behalf to repay the minted DOLA
    /// @dev Requires user to sign message to permit the contract to borrow DOLA on behalf
    /// @param _value Amount of DOLA to flash mint/burn
    /// @param _market The market contract
    /// @param _spender The `allowanceTarget` field from the API response.
    /// @param _swapCallData The `data` field from the API response.
    /// @param _permit Permit data
    /// @param _helperData Optional helper data in case the collateral needs to be transformed
    /// @param _dbrData Optional data in case the user wants to buy DBR and also withdraw some DOLA
    function leveragePosition(
        uint256 _value,
        address _market,
        address _spender,
        bytes calldata _swapCallData,
        Permit calldata _permit,
        bytes calldata _helperData,
        DBRHelper calldata _dbrData
    ) public payable nonReentrant dolaSupplyUnchanged {
        if (address(markets[_market].buySellToken) == address(0))
            revert MarketNotSet(_market);

        IMarket market = IMarket(_market);

        // Mint and approve
        _mintAndApproveDola(_spender, _value);

        // Call the encoded swap function call on the contract at `swapTarget`,
        // passing along any ETH attached to this function call to cover protocol fees.
        (bool success, ) = exchangeProxy.call{value: msg.value}(_swapCallData);
        if (!success) revert SwapFailed();

        // Actual collateral/buyToken bought
        uint256 collateralAmount = markets[_market].buySellToken.balanceOf(address(this));
        if(collateralAmount == 0) revert CollateralIsZero();

        // If there's a helper contract, the buyToken has to be transformed
        if (address(markets[_market].helper) != address(0)) {
            collateralAmount = _convertToCollateral(
                collateralAmount,
                _market,
                _helperData
            );
        }

        // Deposit and borrow on behalf
        market.deposit(msg.sender, collateralAmount);

        _borrowDola(_value, _permit, _dbrData, market);

        // Burn the dola minted previously
        dola.burn(_value);

        if (_dbrData.dola != 0) {
            dola.transfer(msg.sender, _dbrData.dola);
        }

        if (_dbrData.amountIn != 0) {
            _buyDbr(_dbrData.amountIn, _dbrData.minOut, msg.sender);
        }

        if (dola.balanceOf(address(this)) != 0) {
            dola.transfer(msg.sender, dola.balanceOf(address(this)));
        }

        // Refund any possible unspent 0x protocol fees to the sender.
        if (address(this).balance > 0)
            payable(msg.sender).transfer(address(this).balance);

        emit LeverageUp(_market, msg.sender, _value, collateralAmount, _dbrData.dola, _dbrData.amountIn);
    }

    /// @notice Deposit collateral and instantly leverage user position by minting DOLA, buying collateral, deposting into the user escrow and borrow DOLA on behalf to repay the minted DOLA
    /// @dev Requires user to sign message to permit the contract to borrow DOLA on behalf
    /// @param _initialDeposit Amount of collateral or underlying (in case of helper) to deposit
    /// @param _value Amount of DOLA to borrow
    /// @param _market The market address
    /// @param _spender The `allowanceTarget` field from the API response.
    /// @param _swapCallData The `data` field from the API response.
    /// @param _permit Permit data
    /// @param _helperData Optional helper data in case the collateral needs to be transformed
    function depositAndLeveragePosition(
        uint256 _initialDeposit,
        uint256 _value,
        address _market,
        address _spender,
        bytes calldata _swapCallData,
        Permit calldata _permit,
        bytes calldata _helperData,
        DBRHelper calldata _dbrData
    ) external payable {
        if (_initialDeposit == 0) revert NothingToDeposit();
        IERC20 buyToken = markets[_market].buySellToken;
        buyToken.transferFrom(msg.sender, address(this), _initialDeposit);

        emit Deposit(_market, msg.sender, _initialDeposit);

        leveragePosition(
            _value,
            _market,
            _spender,
            _swapCallData,
            _permit,
            _helperData,
            _dbrData
        );
    }

    /// @notice Repay a DOLA loan and withdraw collateral from the escrow
    /// @dev Requires user to sign message to permit the contract to withdraw collateral from the escrow
    /// @param _value Amount of DOLA to repay
    /// @param _market The market contract
    /// @param _collateralAmount Collateral amount to withdraw from the escrow
    /// @param _spender The `allowanceTarget` field from the API response.
    /// @param _swapCallData The `data` field from the API response.
    /// @param _permit Permit data
    /// @param _helperData Optional helper data in case collateral needs to be transformed
    /// @param _dbrData Optional data in case the user wants to sell DBR
    function deleveragePosition(
        uint256 _value,
        address _market,
        uint256 _collateralAmount,
        address _spender,
        bytes calldata _swapCallData,
        Permit calldata _permit,
        bytes calldata _helperData,
        DBRHelper calldata _dbrData
    ) external payable nonReentrant dolaSupplyUnchanged {
        if (address(markets[_market].buySellToken) == address(0))
            revert MarketNotSet(_market);

        IERC20 sellToken = markets[_market].buySellToken;

        _repayAndWithdraw(_value, _collateralAmount, _permit, _dbrData, IMarket(_market));

        // If there's a helper contract, the collateral has to be transformed
        if (address(markets[_market].helper) != address(0)) {
            _collateralAmount = _convertToAsset(
                _collateralAmount,
                _market,
                sellToken,
                _helperData
            );
        }

        // Approve sellToken for spender
        sellToken.approve(_spender, 0);
        sellToken.approve(_spender, _collateralAmount);

        // Call the encoded swap function call on the contract at `swapTarget`,
        // passing along any ETH attached to this function call to cover protocol fees.
        // NOTE: This will swap the collateral or helperCollateral for DOLA
        (bool success, ) = exchangeProxy.call{value: msg.value}(_swapCallData);
        if (!success) revert SwapFailed();

        if (address(markets[_market].helper) == address(0)) {
            uint256 collateralAvailable = markets[_market].collateral.balanceOf(
                address(this)
            );

            if (collateralAvailable != 0) {
                markets[_market].collateral.transfer(
                    msg.sender,
                    collateralAvailable
                );
            }
        } else {
            uint256 sellTokenBal = sellToken.balanceOf(address(this));
            // Send any leftover sellToken to the sender
            if (sellTokenBal != 0) {
                sellToken.transfer(msg.sender, sellTokenBal);
            }
        }

        if (dola.balanceOf(address(this)) < _value)
            revert DOLAInvalidRepay(_value, dola.balanceOf(address(this)));

        dola.burn(_value);

        // Send any DOLA leftover to the sender after burning (in case the collateral withdrawn and swapped exceeds the value to burn)
        dola.transfer(msg.sender, dola.balanceOf(address(this)));

        if (_dbrData.amountIn != 0) {
            dbr.transferFrom(msg.sender, address(this), _dbrData.amountIn);
            _sellDbr(_dbrData.amountIn, _dbrData.minOut, msg.sender);
        }

        // Refund any unspent protocol fees to the sender.
        if (address(this).balance > 0)
            payable(msg.sender).transfer(address(this).balance);

       emit LeverageDown(_market, msg.sender, _value, _collateralAmount, _dbrData.dola, _dbrData.amountIn);
    }

    /// @notice Mint DOLA to this contract and approve the spender
    /// @param spender The spender address
    /// @param _value Amount of DOLA to mint and approve
    function _mintAndApproveDola(address spender, uint256 _value) internal {
        dola.mint(address(this), _value);
        dola.approve(spender, _value);
    }

    /// @notice Borrow DOLA on behalf of the user
    /// @param _value Amount of DOLA to borrow
    /// @param _permit Permit data
    /// @param _dbrData DBR data
    /// @param market The market contract
    function _borrowDola(
        uint256 _value,
        Permit calldata _permit,
        DBRHelper calldata _dbrData,
        IMarket market
    ) internal {
        uint256 dolaToBorrow = _value;

        if (_dbrData.dola != 0) {
            dolaToBorrow += _dbrData.dola;
        }

        if (_dbrData.amountIn != 0) {
            dolaToBorrow += _dbrData.amountIn;
        }
        // We borrow the amount of DOLA we minted before plus the amount for buying DBR if any
        market.borrowOnBehalf(
            msg.sender,
            dolaToBorrow,
            _permit.deadline,
            _permit.v,
            _permit.r,
            _permit.s
        );

        if (dola.balanceOf(address(this)) < dolaToBorrow)
            revert DOLAInvalidBorrow(dolaToBorrow,dola.balanceOf(address(this)));
    }

    /// @notice Repay DOLA loan and withdraw collateral from the escrow
    /// @param _value Amount of DOLA to repay
    /// @param _collateralAmount Collateral amount to withdraw from the escrow
    /// @param _permit Permit data
    /// @param _dbrData DBR data
    /// @param market The market contract
    function _repayAndWithdraw(
        uint256 _value,
        uint256 _collateralAmount,
        Permit calldata _permit,
        DBRHelper calldata _dbrData,
        IMarket market
    ) internal {
        if (_dbrData.dola != 0) {
            dola.transferFrom(msg.sender, address(this), _dbrData.dola);

            dola.mint(address(this), _value);
            dola.approve(address(market), _value + _dbrData.dola);

            market.repay(msg.sender, _value + _dbrData.dola);
        } else {
            _mintAndApproveDola(address(market), _value);
            market.repay(msg.sender, _value);
        }

        // withdraw amount from ZERO EX quote
        market.withdrawOnBehalf(
            msg.sender,
            _collateralAmount,
            _permit.deadline,
            _permit.v,
            _permit.r,
            _permit.s
        );
    }

    /// @notice convert a collateral amount into the underlying asset
    /// @param _collateralAmount Collateral amount to convert
    /// @param _market The market contract
    /// @param sellToken The sell token (the underlying asset)
    /// @param _helperData Optional helper data
    /// @return assetAmount The amount of sellToken/underlying after the conversion
    function _convertToAsset(
        uint256 _collateralAmount,
        address _market,
        IERC20 sellToken,
        bytes calldata _helperData
    ) internal returns (uint256) {
        // Collateral amount is now transformed into sellToken
        uint256 assetAmount = markets[_market].helper.transformFromCollateral(
            _collateralAmount,
            _helperData
        );

        if (sellToken.balanceOf(address(this)) < assetAmount)
            revert WithdrawFailed(assetAmount,sellToken.balanceOf(address(this)));

        return assetAmount;
    }

    /// @notice convert the underlying asset amount into the collateral
    /// @param _assetAmount The amount of sellToken/underlying to convert
    /// @param _market The market contract
    /// @param _helperData Optional helper data
    /// @return collateralAmount The amount of collateral after the conversion
    function _convertToCollateral(
        uint256 _assetAmount,
        address _market,
        bytes calldata _helperData
    ) internal returns (uint256) {
        // Collateral amount is now transformed
        uint256 collateralAmount = markets[_market]
            .helper
            .transformToCollateral(_assetAmount, _helperData);

        if (
            markets[_market].collateral.balanceOf(address(this)) <
            collateralAmount
        )
            revert DepositFailed(
                collateralAmount,
                markets[_market].collateral.balanceOf(address(this))
            );

        return collateralAmount;
    }

    // solhint-disable-next-line no-empty-blocks
    receive() external payable {}
}

File 2 of 9 : IMarket.sol
pragma solidity ^0.8.13;

interface IMarket {
    function borrowOnBehalf(address msgSender, uint dolaAmount, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    function withdrawOnBehalf(address msgSender, uint amount, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    function deposit(address msgSender, uint collateralAmount) external;
    function repay(address msgSender, uint amount) external;
    function collateral() external returns(address);
    function debts(address user) external returns(uint);
    function recall(uint amount) external;
    function totalDebt() external view returns (uint);
    function borrowPaused() external view returns (bool);
    function oracle() external view returns (address);
}

File 3 of 9 : IERC20.sol
pragma solidity ^0.8.13;

interface IERC20 {
    function approve(address,uint) external;
    function transfer(address,uint) external returns (bool);
    function transferFrom(address,address,uint) external returns (bool);
    function balanceOf(address) external view returns (uint);
    function allowance(address from, address to) external view returns (uint);
}

interface IDelegateableERC20 is IERC20 {
    function delegate(address delegatee) external;
    function delegates(address delegator) external view returns (address delegatee);
}

File 4 of 9 : ITransformHelper.sol
//SPDX-License-Identifier: None
pragma solidity ^0.8.0;

interface ITransformHelper {
    
    struct Permit {
        uint256 deadline;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    function transformToCollateral(
        uint amount,
        bytes calldata data
    ) external returns (uint);

    function transformToCollateralAndDeposit(
        uint amount,
        bytes calldata data
    ) external returns (uint256 collateralAmount);

    function transformFromCollateral(
        uint amount,
        bytes calldata data
    ) external returns (uint);

    function withdrawAndTransformFromCollateral(
        uint amount,
        Permit calldata permit,
        bytes calldata data
    ) external returns (uint256 underlyingAmount);

    function assetToCollateralRatio(
        uint assetAmount
    ) external view returns (uint collateralAmount);

    function assetToCollateral(
        uint assetAmount
    ) external view returns (uint collateralAmount);
    
    function collateralToAsset(
        uint collateralAmount
    ) external view returns (uint assetAmount);
}

File 5 of 9 : CurveDBRHelper.sol
pragma solidity ^0.8.13;
//import "src/util/OffchainAbstractHelper.sol";
import "src/interfaces/IERC20.sol";
import "src/interfaces/IDola.sol";

interface ICurvePool {
    function coins(uint index) external view returns (address);

    function get_dy(uint i, uint j, uint dx) external view returns (uint);

    function exchange(
        uint i,
        uint j,
        uint dx,
        uint min_dy,
        bool use_eth
    ) external payable returns (uint);

    function exchange(
        uint i,
        uint j,
        uint dx,
        uint min_dy,
        bool use_eth,
        address receiver
    ) external payable returns (uint);
}

contract CurveDBRHelper {
    ICurvePool public immutable curvePool;
    IDola constant dola = IDola(0x865377367054516e17014CcdED1e7d814EDC9ce4);
    IERC20 constant dbr = IERC20(0xAD038Eb671c44b853887A7E32528FaB35dC5D710);

    uint dbrIndex;
    uint dolaIndex;

    constructor(address _pool) {
        curvePool = ICurvePool(_pool);
        dola.approve(_pool, type(uint).max);
        dbr.approve(_pool, type(uint).max);
        if (ICurvePool(_pool).coins(0) == address(dola)) {
            dolaIndex = 0;
            dbrIndex = 1;
        } else {
            dolaIndex = 1;
            dbrIndex = 0;
        }
    }

    /**
    @notice Sells an exact amount of DBR for DOLA in a curve pool
    @param amount Amount of DBR to sell
    @param minOut minimum amount of DOLA to receive
    */
    function _sellDbr(uint amount, uint minOut, address receiver) internal {
        if (amount > 0) {
            curvePool.exchange(
                dbrIndex,
                dolaIndex,
                amount,
                minOut,
                false,
                receiver
            );
        }
    }

    /**
    @notice Buys an exact amount of DBR for DOLA in a curve pool
    @param amount Amount of DOLA to sell
    @param minOut minimum amount of DBR out
    */
    function _buyDbr(uint amount, uint minOut, address receiver) internal {
        if (amount > 0) {
            curvePool.exchange(
                dolaIndex,
                dbrIndex,
                amount,
                minOut,
                false,
                receiver
            );
        }
    }

    /**
    @notice Approximates the total amount of dola and dbr needed to borrow a dolaBorrowAmount while also borrowing enough to buy the DBR needed to cover for the borrowing period
    @dev Uses a binary search to approximate the amounts needed. Should only be called as part of generating transaction parameters.
    @param dolaBorrowAmount Amount of dola the user wishes to end up with
    @param period Amount of time in seconds the loan will last
    @param iterations Number of approximation iterations. The higher the more precise the result
    */
    function approximateDolaAndDbrNeeded(
        uint dolaBorrowAmount,
        uint period,
        uint iterations
    ) public view returns (uint dolaForDbr, uint dbrNeeded) {
        uint amountIn = dolaBorrowAmount;
        uint stepSize = amountIn / 2;
        uint dbrReceived = curvePool.get_dy(dolaIndex, dbrIndex, amountIn);
        uint dbrToBuy = ((amountIn + dolaBorrowAmount) * period) / 365 days;
        uint dist = dbrReceived > dbrToBuy
            ? dbrReceived - dbrToBuy
            : dbrToBuy - dbrReceived;
        for (uint i; i < iterations; ++i) {
            uint newAmountIn = amountIn;
            if (dbrReceived > dbrToBuy) {
                newAmountIn -= stepSize;
            } else {
                newAmountIn += stepSize;
            }
            uint newDbrReceived = curvePool.get_dy(
                dolaIndex,
                dbrIndex,
                newAmountIn
            );
            uint newDbrToBuy = ((newAmountIn + dolaBorrowAmount) * period) /
                365 days;
            uint newDist = newDbrReceived > newDbrToBuy
                ? newDbrReceived - newDbrToBuy
                : newDbrToBuy - newDbrReceived;
            if (newDist < dist) {
                dbrReceived = newDbrReceived;
                dbrToBuy = newDbrToBuy;
                dist = newDist;
                amountIn = newAmountIn;
            }
            stepSize /= 2;
        }
        return (amountIn, ((dolaBorrowAmount + amountIn) * period) / 365 days);
    }
}

File 6 of 9 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 7 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @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;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    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 making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 8 of 9 : IDola.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "src/interfaces/IERC20.sol";

interface IDola  is IERC20{
    function mint(address recipient, uint256 amount) external;
    function burn(uint256 amount) external;
    function addMinter(address minter) external;
    function totalSupply() external view returns (uint256);
}

File 9 of 9 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_exchangeProxy","type":"address"},{"internalType":"address","name":"_pool","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CollateralIsZero","type":"error"},{"inputs":[],"name":"CollateralNotSet","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"DOLAInvalidBorrow","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"DOLAInvalidRepay","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"DepositFailed","type":"error"},{"inputs":[],"name":"InvalidHelperAddress","type":"error"},{"inputs":[],"name":"InvalidProxyAddress","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"MarketNotSet","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"NoMarket","type":"error"},{"inputs":[],"name":"NothingToDeposit","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"SwapFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"TotalSupplyChanged","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"WithdrawFailed","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"buySellToken","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"address","name":"helper","type":"address"}],"name":"WrongCollateral","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"dolaFlashMinted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dolaUserRepaid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dbrSoldForDola","type":"uint256"}],"name":"LeverageDown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"dolaFlashMinted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralDeposited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dolaBorrowed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dolaForDBR","type":"uint256"}],"name":"LeverageUp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"helper","type":"address"}],"name":"NewHelper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"buySellToken","type":"address"},{"indexed":false,"internalType":"address","name":"collateral","type":"address"},{"indexed":true,"internalType":"address","name":"helper","type":"address"}],"name":"NewMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"DBR","outputs":[{"internalType":"contract IDBR","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dolaBorrowAmount","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"},{"internalType":"uint256","name":"iterations","type":"uint256"}],"name":"approximateDolaAndDbrNeeded","outputs":[{"internalType":"uint256","name":"dolaForDbr","type":"uint256"},{"internalType":"uint256","name":"dbrNeeded","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curvePool","outputs":[{"internalType":"contract ICurvePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"address","name":"_market","type":"address"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"bytes","name":"_swapCallData","type":"bytes"},{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ALE.Permit","name":"_permit","type":"tuple"},{"internalType":"bytes","name":"_helperData","type":"bytes"},{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"uint256","name":"dola","type":"uint256"}],"internalType":"struct ALE.DBRHelper","name":"_dbrData","type":"tuple"}],"name":"deleveragePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_initialDeposit","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"address","name":"_market","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"bytes","name":"_swapCallData","type":"bytes"},{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ALE.Permit","name":"_permit","type":"tuple"},{"internalType":"bytes","name":"_helperData","type":"bytes"},{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"uint256","name":"dola","type":"uint256"}],"internalType":"struct ALE.DBRHelper","name":"_dbrData","type":"tuple"}],"name":"depositAndLeveragePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"exchangeProxy","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"address","name":"_market","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"bytes","name":"_swapCallData","type":"bytes"},{"components":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ALE.Permit","name":"_permit","type":"tuple"},{"internalType":"bytes","name":"_helperData","type":"bytes"},{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"uint256","name":"dola","type":"uint256"}],"internalType":"struct ALE.DBRHelper","name":"_dbrData","type":"tuple"}],"name":"leveragePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"markets","outputs":[{"internalType":"contract IERC20","name":"buySellToken","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"contract ITransformHelper","name":"helper","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exchangeProxy","type":"address"}],"name":"setExchangeProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_market","type":"address"},{"internalType":"address","name":"_buySellToken","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_helper","type":"address"}],"name":"setMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_market","type":"address"},{"internalType":"address","name":"_helper","type":"address"}],"name":"updateMarketHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a060405234801562000010575f80fd5b506040516200301e3803806200301e83398101604081905262000033916200028e565b8033806200005a57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b620000658162000223565b50600180556001600160a01b038116608081905260405163095ea7b360e01b815260048101919091525f19602482015273865377367054516e17014ccded1e7d814edc9ce49063095ea7b3906044015f604051808303815f87803b158015620000cc575f80fd5b505af1158015620000df573d5f803e3d5ffd5b505060405163095ea7b360e01b81526001600160a01b03841660048201525f19602482015273ad038eb671c44b853887a7e32528fab35dc5d710925063095ea7b391506044015f604051808303815f87803b1580156200013d575f80fd5b505af115801562000150573d5f803e3d5ffd5b505060405163c661065760e01b81525f600482015273865377367054516e17014ccded1e7d814edc9ce492506001600160a01b038416915063c661065790602401602060405180830381865afa158015620001ad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001d39190620002c4565b6001600160a01b031603620001f1575f6003556001600255620001fb565b60016003555f6002555b5050600480546001600160a01b0319166001600160a01b0392909216919091179055620002e7565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811462000289575f80fd5b919050565b5f8060408385031215620002a0575f80fd5b620002ab8362000272565b9150620002bb6020840162000272565b90509250929050565b5f60208284031215620002d5575f80fd5b620002e08262000272565b9392505050565b608051612d026200031c5f395f81816101190152818161114e01528181611267015281816122ea01526127fc0152612d025ff3fe6080604052600436106100dc575f3560e01c8063a92d64e01161007c578063ca0b728811610057578063ca0b7288146102a5578063e653bf3a146102b8578063e6c4efab146102d7578063f2fde38b146102ea575f80fd5b8063a92d64e014610233578063b8b71de114610252578063c7c30be114610286575f80fd5b8063715018a6116100b7578063715018a61461017f5780637c65d3fc146101935780638da5cb5b146101a65780638e8f294b146101c2575f80fd5b806308efe934146100e7578063218751b2146101085780636d12471514610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5061010661010136600461283f565b610309565b005b348015610113575f80fd5b5061013b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610163575f80fd5b5061013b73ad038eb671c44b853887a7e32528fab35dc5d71081565b34801561018a575f80fd5b5061010661080f565b6101066101a1366004612903565b610822565b3480156101b1575f80fd5b505f546001600160a01b031661013b565b3480156101cd575f80fd5b506102096101dc3660046129c2565b60056020525f90815260409020805460018201546002909201546001600160a01b03918216928216911683565b604080516001600160a01b039485168152928416602084015292169181019190915260600161014f565b34801561023e575f80fd5b5061010661024d3660046129e4565b610e72565b34801561025d575f80fd5b5061027161026c366004612a1b565b611111565b6040805192835260208301919091520161014f565b348015610291575f80fd5b5060045461013b906001600160a01b031681565b6101066102b3366004612a44565b611394565b3480156102c3575f80fd5b506101066102d23660046129c2565b61149b565b6101066102e5366004612b0d565b6114ec565b3480156102f5575f80fd5b506101066103043660046129c2565b611d69565b610311611da6565b604051638e8f294b60e01b81526001600160a01b038516600482015273ad038eb671c44b853887a7e32528fab35dc5d71090638e8f294b90602401602060405180830381865afa158015610367573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038b9190612b50565b6103b8576040516305beb36d60e31b81526001600160a01b03851660048201526024015b60405180910390fd5b6001600160a01b0381166104ff57836001600160a01b031663d8dfeb456040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610403573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104279190612b6f565b6001600160a01b0316836001600160a01b03161415806104b95750836001600160a01b031663d8dfeb456040518163ffffffff1660e01b81526004016020604051808303815f875af115801561047f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a39190612b6f565b6001600160a01b0316826001600160a01b031614155b156104fa57604051630ad08e6760e41b81526001600160a01b03808616600483015280851660248301528084166044830152821660648201526084016103af565b6105ca565b6001600160a01b038116158015906105895750836001600160a01b031663d8dfeb456040518163ffffffff1660e01b81526004016020604051808303815f875af115801561054f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105739190612b6f565b6001600160a01b0316826001600160a01b031614155b156105ca57604051630ad08e6760e41b81526001600160a01b03808616600483015280851660248301528084166044830152821660648201526084016103af565b6001600160a01b038085165f908152600560205260409081902080548387166001600160a01b0319918216811783556001909201805494871694909116939093179092555163095ea7b360e01b815263095ea7b3906106309087905f1990600401612b8a565b5f604051808303815f87803b158015610647575f80fd5b505af1158015610659573d5f803e3d5ffd5b50505050816001600160a01b0316836001600160a01b0316146106d35760405163095ea7b360e01b81526001600160a01b0383169063095ea7b3906106a59087905f1990600401612b8a565b5f604051808303815f87803b1580156106bc575f80fd5b505af11580156106ce573d5f803e3d5ffd5b505050505b6001600160a01b038116156107c1576001600160a01b038481165f908152600560205260409081902060020180546001600160a01b0319168484161790555163095ea7b360e01b81529084169063095ea7b3906107379084905f1990600401612b8a565b5f604051808303815f87803b15801561074e575f80fd5b505af1158015610760573d5f803e3d5ffd5b505060405163095ea7b360e01b81526001600160a01b038516925063095ea7b391506107939084905f1990600401612b8a565b5f604051808303815f87803b1580156107aa575f80fd5b505af11580156107bc573d5f803e3d5ffd5b505050505b6040516001600160a01b03838116825280831691858216918716907f8ab0b8c470b101bb508ea695012478540f30a9857917e6c327eda5761d6f8be79060200160405180910390a450505050565b610817611da6565b6108205f611dd2565b565b61082a611e21565b5f5f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610874573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108989190612ba3565b6001600160a01b038a81165f90815260056020526040902054919250166108dd576040516331589d0960e01b81526001600160a01b038a1660048201526024016103af565b886108e8898c611e4b565b6004546040515f916001600160a01b0316903490610909908c908c90612bba565b5f6040518083038185875af1925050503d805f8114610943576040519150601f19603f3d011682016040523d82523d5f602084013e610948565b606091505b505090508061096a5760405163081ceff360e41b815260040160405180910390fd5b6001600160a01b038b81165f908152600560205260408082205490516370a0823160e01b8152306004820152919216906370a0823190602401602060405180830381865afa1580156109be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e29190612ba3565b9050805f03610a0457604051635a78c58160e11b815260040160405180910390fd5b6001600160a01b038c81165f908152600560205260409020600201541615610a3557610a32818d8989611f0d565b90505b6040516311f9fbc960e21b81526001600160a01b038416906347e7ef2490610a639033908590600401612b8a565b5f604051808303815f87803b158015610a7a575f80fd5b505af1158015610a8c573d5f803e3d5ffd5b50505050610a9c8d8987866120c4565b604051630852cd8d60e31b8152600481018e90525f80516020612cad833981519152906342966c68906024015f604051808303815f87803b158015610adf575f80fd5b505af1158015610af1573d5f803e3d5ffd5b50505050604085013515610b77576040805163a9059cbb60e01b81525f80516020612cad8339815191529163a9059cbb91610b35913391908a013590600401612b8a565b6020604051808303815f875af1158015610b51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b759190612b50565b505b843515610b8e57610b8e853560208701353361229e565b6040516370a0823160e01b81523060048201525f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015610bd4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf89190612ba3565b15610cd0576040516370a0823160e01b81523060048201525f80516020612cad8339815191529063a9059cbb90339083906370a0823190602401602060405180830381865afa158015610c4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c719190612ba3565b6040518363ffffffff1660e01b8152600401610c8e929190612b8a565b6020604051808303815f875af1158015610caa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cce9190612b50565b505b4715610d015760405133904780156108fc02915f818181858888f19350505050158015610cff573d5f803e3d5ffd5b505b604080518e815260208101839052868201358183015286356060820152905133916001600160a01b038f16917f27adca66c335786d061cb91c67c649d181361d7245b6d38c4995b1f9b94017729181900360800190a35050505f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc79190612ba3565b8114610e5d57805f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e17573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3b9190612ba3565b6040516360b7032b60e11b8152600481019290925260248201526044016103af565b50610e6760018055565b505050505050505050565b610e7a611da6565b6001600160a01b038281165f9081526005602052604090205416610ebc576040516331589d0960e01b81526001600160a01b03831660048201526024016103af565b6001600160a01b038083165f90815260056020526040902060020154168015610fb8576001600160a01b038084165f9081526005602052604080822054905163095ea7b360e01b815292169163095ea7b391610f1d91859190600401612b8a565b5f604051808303815f87803b158015610f34575f80fd5b505af1158015610f46573d5f803e3d5ffd5b5050506001600160a01b038085165f9081526005602052604080822060010154905163095ea7b360e01b81529216925063095ea7b391610f8a918591600401612b8a565b5f604051808303815f87803b158015610fa1575f80fd5b505af1158015610fb3573d5f803e3d5ffd5b505050505b6001600160a01b038381165f90815260056020526040902060020180546001600160a01b0319169184169182179055156110cc576001600160a01b038084165f908152600560205260409081902054905163095ea7b360e01b815291169063095ea7b39061102d9085905f1990600401612b8a565b5f604051808303815f87803b158015611044575f80fd5b505af1158015611056573d5f803e3d5ffd5b5050506001600160a01b038085165f908152600560205260409081902060010154905163095ea7b360e01b81529116915063095ea7b39061109e9085905f1990600401612b8a565b5f604051808303815f87803b1580156110b5575f80fd5b505af11580156110c7573d5f803e3d5ffd5b505050505b816001600160a01b0316836001600160a01b03167f06bc331032840de3e44179cee67a8860508a9c70737f1e433476e3a9a255b25f60405160405180910390a3505050565b5f808481611120600283612bdd565b60035460025460405163556d6e9f60e01b815260048101929092526024820152604481018490529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063556d6e9f90606401602060405180830381865afa15801561119b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111bf9190612ba3565b90505f6301e13380886111d28b87612bfc565b6111dc9190612c15565b6111e69190612bdd565b90505f8183116111ff576111fa8383612c2c565b611209565b6112098284612c2c565b90505f5b8881101561135d57858385111561122f576112288682612c2c565b905061123c565b6112398682612bfc565b90505b60035460025460405163556d6e9f60e01b815260048101929092526024820152604481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063556d6e9f90606401602060405180830381865afa1580156112b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d89190612ba3565b90505f6301e133808d8f856112ed9190612bfc565b6112f79190612c15565b6113019190612bdd565b90505f81831161131a576113158383612c2c565b611324565b6113248284612c2c565b90508581101561133b578297508196508095508399505b61134660028a612bdd565b9850505050508061135690612c3f565b905061120d565b50846301e133808a61136f838e612bfc565b6113799190612c15565b6113839190612bdd565b965096505050505050935093915050565b895f036113b457604051639a4f66bf60e01b815260040160405180910390fd5b6001600160a01b038089165f90815260056020526040908190205490516323b872dd60e01b8152336004820152306024820152604481018d905291169081906323b872dd906064016020604051808303815f875af1158015611418573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061143c9190612b50565b506040518b815233906001600160a01b038b16907f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a361148e8a8a8a8a8a8a8a8a8a610822565b5050505050505050505050565b6114a3611da6565b6001600160a01b0381166114ca5760405163fc9dfba760e01b815260040160405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6114f4611e21565b5f5f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115629190612ba3565b6001600160a01b038b81165f90815260056020526040902054919250166115a7576040516331589d0960e01b81526001600160a01b038b1660048201526024016103af565b6001600160a01b03808b165f90815260056020526040902054166115ce8c8b88868f61235c565b6001600160a01b038b81165f908152600560205260409020600201541615611600576115fd8a8c838888612623565b99505b60405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061162e908c905f90600401612b8a565b5f604051808303815f87803b158015611645575f80fd5b505af1158015611657573d5f803e3d5ffd5b505060405163095ea7b360e01b81526001600160a01b038416925063095ea7b39150611689908c908e90600401612b8a565b5f604051808303815f87803b1580156116a0575f80fd5b505af11580156116b2573d5f803e3d5ffd5b50506004546040515f93506001600160a01b03909116915034906116d9908c908c90612bba565b5f6040518083038185875af1925050503d805f8114611713576040519150601f19603f3d011682016040523d82523d5f602084013e611718565b606091505b505090508061173a5760405163081ceff360e41b815260040160405180910390fd5b6001600160a01b038c81165f9081526005602052604090206002015416611869576001600160a01b038c81165f908152600560205260408082206001015490516370a0823160e01b8152306004820152919216906370a0823190602401602060405180830381865afa1580156117b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117d69190612ba3565b90508015611863576001600160a01b03808e165f908152600560205260409081902060010154905163a9059cbb60e01b815291169063a9059cbb906118219033908590600401612b8a565b6020604051808303815f875af115801561183d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118619190612b50565b505b5061194b565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa1580156118ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118d19190612ba3565b905080156119495760405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906119079033908590600401612b8a565b6020604051808303815f875af1158015611923573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119479190612b50565b505b505b6040516370a0823160e01b81523060048201528d905f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015611993573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b79190612ba3565b1015611a4b576040516370a0823160e01b81523060048201528d905f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015611a05573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a299190612ba3565b60405163d694ba9560e01b8152600481019290925260248201526044016103af565b604051630852cd8d60e31b8152600481018e90525f80516020612cad833981519152906342966c68906024015f604051808303815f87803b158015611a8e575f80fd5b505af1158015611aa0573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f80516020612cad833981519152925063a9059cbb9150339083906370a0823190602401602060405180830381865afa158015611af4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b189190612ba3565b6040518363ffffffff1660e01b8152600401611b35929190612b8a565b6020604051808303815f875af1158015611b51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b759190612b50565b50833515611c0d576040516323b872dd60e01b81523360048201523060248201528435604482015273ad038eb671c44b853887a7e32528fab35dc5d710906323b872dd906064016020604051808303815f875af1158015611bd8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bfc9190612b50565b50611c0d84356020860135336127b0565b4715611c3e5760405133904780156108fc02915f818181858888f19350505050158015611c3c573d5f803e3d5ffd5b505b604080518e8152602081018d9052858201358183015285356060820152905133916001600160a01b038f16917fc9557b65f45f298d465e24590087886d84c9edd6e108069afb1a834ba704b7669181900360800190a350505f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cdf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d039190612ba3565b8114611d5357805f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e17573d5f803e3d5ffd5b50611d5d60018055565b50505050505050505050565b611d71611da6565b6001600160a01b038116611d9a57604051631e4fbdf760e01b81525f60048201526024016103af565b611da381611dd2565b50565b5f546001600160a01b031633146108205760405163118cdaa760e01b81523360048201526024016103af565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600260015403611e4457604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b6040516340c10f1960e01b81525f80516020612cad833981519152906340c10f1990611e7d9030908590600401612b8a565b5f604051808303815f87803b158015611e94575f80fd5b505af1158015611ea6573d5f803e3d5ffd5b505060405163095ea7b360e01b81525f80516020612cad833981519152925063095ea7b39150611edc9085908590600401612b8a565b5f604051808303815f87803b158015611ef3575f80fd5b505af1158015611f05573d5f803e3d5ffd5b505050505050565b6001600160a01b038084165f90815260056020526040808220600201549051632cfa26df60e01b815291928392911690632cfa26df90611f5590899088908890600401612c57565b6020604051808303815f875af1158015611f71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f959190612ba3565b6001600160a01b038681165f90815260056020526040908190206001015490516370a0823160e01b815230600482015292935083929116906370a0823190602401602060405180830381865afa158015611ff1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120159190612ba3565b10156120bb576001600160a01b038581165f90815260056020526040908190206001015490516370a0823160e01b8152306004820152839291909116906370a0823190602401602060405180830381865afa158015612076573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061209a9190612ba3565b604051629e327560e61b8152600481019290925260248201526044016103af565b95945050505050565b836040830135156120e0576120dd604084013582612bfc565b90505b8235156120f5576120f2833582612bfc565b90505b6001600160a01b038216631ef08b753383873561211860408a0160208b01612c8c565b604080516001600160e01b031960e088901b1681526001600160a01b0390951660048601526024850193909352604484019190915260ff1660648301528701356084820152606087013560a482015260c4015f604051808303815f87803b158015612181575f80fd5b505af1158015612193573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201528392505f80516020612cad83398151915291506370a0823190602401602060405180830381865afa1580156121df573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122039190612ba3565b1015612297576040516370a0823160e01b815230600482015281905f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015612251573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122759190612ba3565b60405163c1c3f18560e01b8152600481019290925260248201526044016103af565b5050505050565b82156123575760035460025460405163ce7d650360e01b81526004810192909252602482015260448101849052606481018390525f60848201526001600160a01b0382811660a48301527f0000000000000000000000000000000000000000000000000000000000000000169063ce7d65039060c4015b6020604051808303815f875af1158015612331573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123559190612ba3565b505b505050565b60408201351561251f57604080516323b872dd60e01b81523360048201523060248201529083013560448201525f80516020612cad833981519152906323b872dd906064016020604051808303815f875af11580156123bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123e19190612b50565b506040516340c10f1960e01b81525f80516020612cad833981519152906340c10f19906124149030908990600401612b8a565b5f604051808303815f87803b15801561242b575f80fd5b505af115801561243d573d5f803e3d5ffd5b505f80516020612cad833981519152925063095ea7b39150839050612466604086013589612bfc565b6040518363ffffffff1660e01b8152600401612483929190612b8a565b5f604051808303815f87803b15801561249a575f80fd5b505af11580156124ac573d5f803e3d5ffd5b50505050806001600160a01b03166322867d78338460400135886124d09190612bfc565b6040518363ffffffff1660e01b81526004016124ed929190612b8a565b5f604051808303815f87803b158015612504575f80fd5b505af1158015612516573d5f803e3d5ffd5b50505050612585565b6125298186611e4b565b604051630450cfaf60e31b81526001600160a01b038216906322867d78906125579033908990600401612b8a565b5f604051808303815f87803b15801561256e575f80fd5b505af1158015612580573d5f803e3d5ffd5b505050505b6001600160a01b038116633525f591338686356125a86040890160208a01612c8c565b604080516001600160e01b031960e088901b1681526001600160a01b0390951660048601526024850193909352604484019190915260ff1660648301528601356084820152606086013560a482015260c4015f604051808303815f87803b158015612611575f80fd5b505af1158015610e67573d5f803e3d5ffd5b6001600160a01b038085165f90815260056020526040808220600201549051634ee5492160e01b815291928392911690634ee549219061266b908a9088908890600401612c57565b6020604051808303815f875af1158015612687573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ab9190612ba3565b6040516370a0823160e01b815230600482015290915081906001600160a01b038716906370a0823190602401602060405180830381865afa1580156126f2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127169190612ba3565b10156127a6576040516370a0823160e01b815230600482015281906001600160a01b038716906370a0823190602401602060405180830381865afa158015612760573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127849190612ba3565b60405163e50972c560e01b8152600481019290925260248201526044016103af565b9695505050505050565b82156123575760025460035460405163ce7d650360e01b81526004810192909252602482015260448101849052606481018390525f60848201526001600160a01b0382811660a48301527f0000000000000000000000000000000000000000000000000000000000000000169063ce7d65039060c401612315565b6001600160a01b0381168114611da3575f80fd5b5f805f8060808587031215612852575f80fd5b843561285d8161282b565b9350602085013561286d8161282b565b9250604085013561287d8161282b565b9150606085013561288d8161282b565b939692955090935050565b5f8083601f8401126128a8575f80fd5b50813567ffffffffffffffff8111156128bf575f80fd5b6020830191508360208285010111156128d6575f80fd5b9250929050565b5f608082840312156128ed575f80fd5b50919050565b5f606082840312156128ed575f80fd5b5f805f805f805f805f6101808a8c03121561291c575f80fd5b8935985060208a013561292e8161282b565b975060408a013561293e8161282b565b965060608a013567ffffffffffffffff8082111561295a575f80fd5b6129668d838e01612898565b909850965086915061297b8d60808e016128dd565b95506101008c0135915080821115612991575f80fd5b5061299e8c828d01612898565b90945092506129b390508b6101208c016128f3565b90509295985092959850929598565b5f602082840312156129d2575f80fd5b81356129dd8161282b565b9392505050565b5f80604083850312156129f5575f80fd5b8235612a008161282b565b91506020830135612a108161282b565b809150509250929050565b5f805f60608486031215612a2d575f80fd5b505081359360208301359350604090920135919050565b5f805f805f805f805f806101a08b8d031215612a5e575f80fd5b8a35995060208b0135985060408b0135612a778161282b565b975060608b0135612a878161282b565b965060808b013567ffffffffffffffff80821115612aa3575f80fd5b612aaf8e838f01612898565b9098509650869150612ac48e60a08f016128dd565b95506101208d0135915080821115612ada575f80fd5b50612ae78d828e01612898565b9094509250612afc90508c6101408d016128f3565b90509295989b9194979a5092959850565b5f805f805f805f805f806101a08b8d031215612b27575f80fd5b8a35995060208b0135612b398161282b565b985060408b0135975060608b0135612a878161282b565b5f60208284031215612b60575f80fd5b815180151581146129dd575f80fd5b5f60208284031215612b7f575f80fd5b81516129dd8161282b565b6001600160a01b03929092168252602082015260400190565b5f60208284031215612bb3575f80fd5b5051919050565b818382375f9101908152919050565b634e487b7160e01b5f52601160045260245ffd5b5f82612bf757634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115612c0f57612c0f612bc9565b92915050565b8082028115828204841417612c0f57612c0f612bc9565b81810381811115612c0f57612c0f612bc9565b5f60018201612c5057612c50612bc9565b5060010190565b83815260406020820152816040820152818360608301375f818301606090810191909152601f909201601f1916010192915050565b5f60208284031215612c9c575f80fd5b813560ff811681146129dd575f80fdfe000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4a2646970667358221220bd8c49530a69260ebce60101df0b4e0eb8fc8bee38682093d15433735c2379f964736f6c63430008140033000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a

Deployed Bytecode

0x6080604052600436106100dc575f3560e01c8063a92d64e01161007c578063ca0b728811610057578063ca0b7288146102a5578063e653bf3a146102b8578063e6c4efab146102d7578063f2fde38b146102ea575f80fd5b8063a92d64e014610233578063b8b71de114610252578063c7c30be114610286575f80fd5b8063715018a6116100b7578063715018a61461017f5780637c65d3fc146101935780638da5cb5b146101a65780638e8f294b146101c2575f80fd5b806308efe934146100e7578063218751b2146101085780636d12471514610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5061010661010136600461283f565b610309565b005b348015610113575f80fd5b5061013b7f000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a81565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610163575f80fd5b5061013b73ad038eb671c44b853887a7e32528fab35dc5d71081565b34801561018a575f80fd5b5061010661080f565b6101066101a1366004612903565b610822565b3480156101b1575f80fd5b505f546001600160a01b031661013b565b3480156101cd575f80fd5b506102096101dc3660046129c2565b60056020525f90815260409020805460018201546002909201546001600160a01b03918216928216911683565b604080516001600160a01b039485168152928416602084015292169181019190915260600161014f565b34801561023e575f80fd5b5061010661024d3660046129e4565b610e72565b34801561025d575f80fd5b5061027161026c366004612a1b565b611111565b6040805192835260208301919091520161014f565b348015610291575f80fd5b5060045461013b906001600160a01b031681565b6101066102b3366004612a44565b611394565b3480156102c3575f80fd5b506101066102d23660046129c2565b61149b565b6101066102e5366004612b0d565b6114ec565b3480156102f5575f80fd5b506101066103043660046129c2565b611d69565b610311611da6565b604051638e8f294b60e01b81526001600160a01b038516600482015273ad038eb671c44b853887a7e32528fab35dc5d71090638e8f294b90602401602060405180830381865afa158015610367573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038b9190612b50565b6103b8576040516305beb36d60e31b81526001600160a01b03851660048201526024015b60405180910390fd5b6001600160a01b0381166104ff57836001600160a01b031663d8dfeb456040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610403573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104279190612b6f565b6001600160a01b0316836001600160a01b03161415806104b95750836001600160a01b031663d8dfeb456040518163ffffffff1660e01b81526004016020604051808303815f875af115801561047f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a39190612b6f565b6001600160a01b0316826001600160a01b031614155b156104fa57604051630ad08e6760e41b81526001600160a01b03808616600483015280851660248301528084166044830152821660648201526084016103af565b6105ca565b6001600160a01b038116158015906105895750836001600160a01b031663d8dfeb456040518163ffffffff1660e01b81526004016020604051808303815f875af115801561054f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105739190612b6f565b6001600160a01b0316826001600160a01b031614155b156105ca57604051630ad08e6760e41b81526001600160a01b03808616600483015280851660248301528084166044830152821660648201526084016103af565b6001600160a01b038085165f908152600560205260409081902080548387166001600160a01b0319918216811783556001909201805494871694909116939093179092555163095ea7b360e01b815263095ea7b3906106309087905f1990600401612b8a565b5f604051808303815f87803b158015610647575f80fd5b505af1158015610659573d5f803e3d5ffd5b50505050816001600160a01b0316836001600160a01b0316146106d35760405163095ea7b360e01b81526001600160a01b0383169063095ea7b3906106a59087905f1990600401612b8a565b5f604051808303815f87803b1580156106bc575f80fd5b505af11580156106ce573d5f803e3d5ffd5b505050505b6001600160a01b038116156107c1576001600160a01b038481165f908152600560205260409081902060020180546001600160a01b0319168484161790555163095ea7b360e01b81529084169063095ea7b3906107379084905f1990600401612b8a565b5f604051808303815f87803b15801561074e575f80fd5b505af1158015610760573d5f803e3d5ffd5b505060405163095ea7b360e01b81526001600160a01b038516925063095ea7b391506107939084905f1990600401612b8a565b5f604051808303815f87803b1580156107aa575f80fd5b505af11580156107bc573d5f803e3d5ffd5b505050505b6040516001600160a01b03838116825280831691858216918716907f8ab0b8c470b101bb508ea695012478540f30a9857917e6c327eda5761d6f8be79060200160405180910390a450505050565b610817611da6565b6108205f611dd2565b565b61082a611e21565b5f5f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610874573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108989190612ba3565b6001600160a01b038a81165f90815260056020526040902054919250166108dd576040516331589d0960e01b81526001600160a01b038a1660048201526024016103af565b886108e8898c611e4b565b6004546040515f916001600160a01b0316903490610909908c908c90612bba565b5f6040518083038185875af1925050503d805f8114610943576040519150601f19603f3d011682016040523d82523d5f602084013e610948565b606091505b505090508061096a5760405163081ceff360e41b815260040160405180910390fd5b6001600160a01b038b81165f908152600560205260408082205490516370a0823160e01b8152306004820152919216906370a0823190602401602060405180830381865afa1580156109be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e29190612ba3565b9050805f03610a0457604051635a78c58160e11b815260040160405180910390fd5b6001600160a01b038c81165f908152600560205260409020600201541615610a3557610a32818d8989611f0d565b90505b6040516311f9fbc960e21b81526001600160a01b038416906347e7ef2490610a639033908590600401612b8a565b5f604051808303815f87803b158015610a7a575f80fd5b505af1158015610a8c573d5f803e3d5ffd5b50505050610a9c8d8987866120c4565b604051630852cd8d60e31b8152600481018e90525f80516020612cad833981519152906342966c68906024015f604051808303815f87803b158015610adf575f80fd5b505af1158015610af1573d5f803e3d5ffd5b50505050604085013515610b77576040805163a9059cbb60e01b81525f80516020612cad8339815191529163a9059cbb91610b35913391908a013590600401612b8a565b6020604051808303815f875af1158015610b51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b759190612b50565b505b843515610b8e57610b8e853560208701353361229e565b6040516370a0823160e01b81523060048201525f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015610bd4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf89190612ba3565b15610cd0576040516370a0823160e01b81523060048201525f80516020612cad8339815191529063a9059cbb90339083906370a0823190602401602060405180830381865afa158015610c4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c719190612ba3565b6040518363ffffffff1660e01b8152600401610c8e929190612b8a565b6020604051808303815f875af1158015610caa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cce9190612b50565b505b4715610d015760405133904780156108fc02915f818181858888f19350505050158015610cff573d5f803e3d5ffd5b505b604080518e815260208101839052868201358183015286356060820152905133916001600160a01b038f16917f27adca66c335786d061cb91c67c649d181361d7245b6d38c4995b1f9b94017729181900360800190a35050505f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc79190612ba3565b8114610e5d57805f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e17573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3b9190612ba3565b6040516360b7032b60e11b8152600481019290925260248201526044016103af565b50610e6760018055565b505050505050505050565b610e7a611da6565b6001600160a01b038281165f9081526005602052604090205416610ebc576040516331589d0960e01b81526001600160a01b03831660048201526024016103af565b6001600160a01b038083165f90815260056020526040902060020154168015610fb8576001600160a01b038084165f9081526005602052604080822054905163095ea7b360e01b815292169163095ea7b391610f1d91859190600401612b8a565b5f604051808303815f87803b158015610f34575f80fd5b505af1158015610f46573d5f803e3d5ffd5b5050506001600160a01b038085165f9081526005602052604080822060010154905163095ea7b360e01b81529216925063095ea7b391610f8a918591600401612b8a565b5f604051808303815f87803b158015610fa1575f80fd5b505af1158015610fb3573d5f803e3d5ffd5b505050505b6001600160a01b038381165f90815260056020526040902060020180546001600160a01b0319169184169182179055156110cc576001600160a01b038084165f908152600560205260409081902054905163095ea7b360e01b815291169063095ea7b39061102d9085905f1990600401612b8a565b5f604051808303815f87803b158015611044575f80fd5b505af1158015611056573d5f803e3d5ffd5b5050506001600160a01b038085165f908152600560205260409081902060010154905163095ea7b360e01b81529116915063095ea7b39061109e9085905f1990600401612b8a565b5f604051808303815f87803b1580156110b5575f80fd5b505af11580156110c7573d5f803e3d5ffd5b505050505b816001600160a01b0316836001600160a01b03167f06bc331032840de3e44179cee67a8860508a9c70737f1e433476e3a9a255b25f60405160405180910390a3505050565b5f808481611120600283612bdd565b60035460025460405163556d6e9f60e01b815260048101929092526024820152604481018490529091505f907f000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a6001600160a01b03169063556d6e9f90606401602060405180830381865afa15801561119b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111bf9190612ba3565b90505f6301e13380886111d28b87612bfc565b6111dc9190612c15565b6111e69190612bdd565b90505f8183116111ff576111fa8383612c2c565b611209565b6112098284612c2c565b90505f5b8881101561135d57858385111561122f576112288682612c2c565b905061123c565b6112398682612bfc565b90505b60035460025460405163556d6e9f60e01b815260048101929092526024820152604481018290525f907f000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a6001600160a01b03169063556d6e9f90606401602060405180830381865afa1580156112b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d89190612ba3565b90505f6301e133808d8f856112ed9190612bfc565b6112f79190612c15565b6113019190612bdd565b90505f81831161131a576113158383612c2c565b611324565b6113248284612c2c565b90508581101561133b578297508196508095508399505b61134660028a612bdd565b9850505050508061135690612c3f565b905061120d565b50846301e133808a61136f838e612bfc565b6113799190612c15565b6113839190612bdd565b965096505050505050935093915050565b895f036113b457604051639a4f66bf60e01b815260040160405180910390fd5b6001600160a01b038089165f90815260056020526040908190205490516323b872dd60e01b8152336004820152306024820152604481018d905291169081906323b872dd906064016020604051808303815f875af1158015611418573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061143c9190612b50565b506040518b815233906001600160a01b038b16907f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a361148e8a8a8a8a8a8a8a8a8a610822565b5050505050505050505050565b6114a3611da6565b6001600160a01b0381166114ca5760405163fc9dfba760e01b815260040160405180910390fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6114f4611e21565b5f5f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115629190612ba3565b6001600160a01b038b81165f90815260056020526040902054919250166115a7576040516331589d0960e01b81526001600160a01b038b1660048201526024016103af565b6001600160a01b03808b165f90815260056020526040902054166115ce8c8b88868f61235c565b6001600160a01b038b81165f908152600560205260409020600201541615611600576115fd8a8c838888612623565b99505b60405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061162e908c905f90600401612b8a565b5f604051808303815f87803b158015611645575f80fd5b505af1158015611657573d5f803e3d5ffd5b505060405163095ea7b360e01b81526001600160a01b038416925063095ea7b39150611689908c908e90600401612b8a565b5f604051808303815f87803b1580156116a0575f80fd5b505af11580156116b2573d5f803e3d5ffd5b50506004546040515f93506001600160a01b03909116915034906116d9908c908c90612bba565b5f6040518083038185875af1925050503d805f8114611713576040519150601f19603f3d011682016040523d82523d5f602084013e611718565b606091505b505090508061173a5760405163081ceff360e41b815260040160405180910390fd5b6001600160a01b038c81165f9081526005602052604090206002015416611869576001600160a01b038c81165f908152600560205260408082206001015490516370a0823160e01b8152306004820152919216906370a0823190602401602060405180830381865afa1580156117b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117d69190612ba3565b90508015611863576001600160a01b03808e165f908152600560205260409081902060010154905163a9059cbb60e01b815291169063a9059cbb906118219033908590600401612b8a565b6020604051808303815f875af115801561183d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118619190612b50565b505b5061194b565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa1580156118ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118d19190612ba3565b905080156119495760405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906119079033908590600401612b8a565b6020604051808303815f875af1158015611923573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119479190612b50565b505b505b6040516370a0823160e01b81523060048201528d905f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015611993573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b79190612ba3565b1015611a4b576040516370a0823160e01b81523060048201528d905f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015611a05573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a299190612ba3565b60405163d694ba9560e01b8152600481019290925260248201526044016103af565b604051630852cd8d60e31b8152600481018e90525f80516020612cad833981519152906342966c68906024015f604051808303815f87803b158015611a8e575f80fd5b505af1158015611aa0573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f80516020612cad833981519152925063a9059cbb9150339083906370a0823190602401602060405180830381865afa158015611af4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b189190612ba3565b6040518363ffffffff1660e01b8152600401611b35929190612b8a565b6020604051808303815f875af1158015611b51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b759190612b50565b50833515611c0d576040516323b872dd60e01b81523360048201523060248201528435604482015273ad038eb671c44b853887a7e32528fab35dc5d710906323b872dd906064016020604051808303815f875af1158015611bd8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bfc9190612b50565b50611c0d84356020860135336127b0565b4715611c3e5760405133904780156108fc02915f818181858888f19350505050158015611c3c573d5f803e3d5ffd5b505b604080518e8152602081018d9052858201358183015285356060820152905133916001600160a01b038f16917fc9557b65f45f298d465e24590087886d84c9edd6e108069afb1a834ba704b7669181900360800190a350505f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cdf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d039190612ba3565b8114611d5357805f80516020612cad8339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e17573d5f803e3d5ffd5b50611d5d60018055565b50505050505050505050565b611d71611da6565b6001600160a01b038116611d9a57604051631e4fbdf760e01b81525f60048201526024016103af565b611da381611dd2565b50565b5f546001600160a01b031633146108205760405163118cdaa760e01b81523360048201526024016103af565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600260015403611e4457604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b6040516340c10f1960e01b81525f80516020612cad833981519152906340c10f1990611e7d9030908590600401612b8a565b5f604051808303815f87803b158015611e94575f80fd5b505af1158015611ea6573d5f803e3d5ffd5b505060405163095ea7b360e01b81525f80516020612cad833981519152925063095ea7b39150611edc9085908590600401612b8a565b5f604051808303815f87803b158015611ef3575f80fd5b505af1158015611f05573d5f803e3d5ffd5b505050505050565b6001600160a01b038084165f90815260056020526040808220600201549051632cfa26df60e01b815291928392911690632cfa26df90611f5590899088908890600401612c57565b6020604051808303815f875af1158015611f71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f959190612ba3565b6001600160a01b038681165f90815260056020526040908190206001015490516370a0823160e01b815230600482015292935083929116906370a0823190602401602060405180830381865afa158015611ff1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120159190612ba3565b10156120bb576001600160a01b038581165f90815260056020526040908190206001015490516370a0823160e01b8152306004820152839291909116906370a0823190602401602060405180830381865afa158015612076573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061209a9190612ba3565b604051629e327560e61b8152600481019290925260248201526044016103af565b95945050505050565b836040830135156120e0576120dd604084013582612bfc565b90505b8235156120f5576120f2833582612bfc565b90505b6001600160a01b038216631ef08b753383873561211860408a0160208b01612c8c565b604080516001600160e01b031960e088901b1681526001600160a01b0390951660048601526024850193909352604484019190915260ff1660648301528701356084820152606087013560a482015260c4015f604051808303815f87803b158015612181575f80fd5b505af1158015612193573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201528392505f80516020612cad83398151915291506370a0823190602401602060405180830381865afa1580156121df573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122039190612ba3565b1015612297576040516370a0823160e01b815230600482015281905f80516020612cad833981519152906370a0823190602401602060405180830381865afa158015612251573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122759190612ba3565b60405163c1c3f18560e01b8152600481019290925260248201526044016103af565b5050505050565b82156123575760035460025460405163ce7d650360e01b81526004810192909252602482015260448101849052606481018390525f60848201526001600160a01b0382811660a48301527f000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a169063ce7d65039060c4015b6020604051808303815f875af1158015612331573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123559190612ba3565b505b505050565b60408201351561251f57604080516323b872dd60e01b81523360048201523060248201529083013560448201525f80516020612cad833981519152906323b872dd906064016020604051808303815f875af11580156123bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123e19190612b50565b506040516340c10f1960e01b81525f80516020612cad833981519152906340c10f19906124149030908990600401612b8a565b5f604051808303815f87803b15801561242b575f80fd5b505af115801561243d573d5f803e3d5ffd5b505f80516020612cad833981519152925063095ea7b39150839050612466604086013589612bfc565b6040518363ffffffff1660e01b8152600401612483929190612b8a565b5f604051808303815f87803b15801561249a575f80fd5b505af11580156124ac573d5f803e3d5ffd5b50505050806001600160a01b03166322867d78338460400135886124d09190612bfc565b6040518363ffffffff1660e01b81526004016124ed929190612b8a565b5f604051808303815f87803b158015612504575f80fd5b505af1158015612516573d5f803e3d5ffd5b50505050612585565b6125298186611e4b565b604051630450cfaf60e31b81526001600160a01b038216906322867d78906125579033908990600401612b8a565b5f604051808303815f87803b15801561256e575f80fd5b505af1158015612580573d5f803e3d5ffd5b505050505b6001600160a01b038116633525f591338686356125a86040890160208a01612c8c565b604080516001600160e01b031960e088901b1681526001600160a01b0390951660048601526024850193909352604484019190915260ff1660648301528601356084820152606086013560a482015260c4015f604051808303815f87803b158015612611575f80fd5b505af1158015610e67573d5f803e3d5ffd5b6001600160a01b038085165f90815260056020526040808220600201549051634ee5492160e01b815291928392911690634ee549219061266b908a9088908890600401612c57565b6020604051808303815f875af1158015612687573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ab9190612ba3565b6040516370a0823160e01b815230600482015290915081906001600160a01b038716906370a0823190602401602060405180830381865afa1580156126f2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127169190612ba3565b10156127a6576040516370a0823160e01b815230600482015281906001600160a01b038716906370a0823190602401602060405180830381865afa158015612760573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127849190612ba3565b60405163e50972c560e01b8152600481019290925260248201526044016103af565b9695505050505050565b82156123575760025460035460405163ce7d650360e01b81526004810192909252602482015260448101849052606481018390525f60848201526001600160a01b0382811660a48301527f000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a169063ce7d65039060c401612315565b6001600160a01b0381168114611da3575f80fd5b5f805f8060808587031215612852575f80fd5b843561285d8161282b565b9350602085013561286d8161282b565b9250604085013561287d8161282b565b9150606085013561288d8161282b565b939692955090935050565b5f8083601f8401126128a8575f80fd5b50813567ffffffffffffffff8111156128bf575f80fd5b6020830191508360208285010111156128d6575f80fd5b9250929050565b5f608082840312156128ed575f80fd5b50919050565b5f606082840312156128ed575f80fd5b5f805f805f805f805f6101808a8c03121561291c575f80fd5b8935985060208a013561292e8161282b565b975060408a013561293e8161282b565b965060608a013567ffffffffffffffff8082111561295a575f80fd5b6129668d838e01612898565b909850965086915061297b8d60808e016128dd565b95506101008c0135915080821115612991575f80fd5b5061299e8c828d01612898565b90945092506129b390508b6101208c016128f3565b90509295985092959850929598565b5f602082840312156129d2575f80fd5b81356129dd8161282b565b9392505050565b5f80604083850312156129f5575f80fd5b8235612a008161282b565b91506020830135612a108161282b565b809150509250929050565b5f805f60608486031215612a2d575f80fd5b505081359360208301359350604090920135919050565b5f805f805f805f805f806101a08b8d031215612a5e575f80fd5b8a35995060208b0135985060408b0135612a778161282b565b975060608b0135612a878161282b565b965060808b013567ffffffffffffffff80821115612aa3575f80fd5b612aaf8e838f01612898565b9098509650869150612ac48e60a08f016128dd565b95506101208d0135915080821115612ada575f80fd5b50612ae78d828e01612898565b9094509250612afc90508c6101408d016128f3565b90509295989b9194979a5092959850565b5f805f805f805f805f806101a08b8d031215612b27575f80fd5b8a35995060208b0135612b398161282b565b985060408b0135975060608b0135612a878161282b565b5f60208284031215612b60575f80fd5b815180151581146129dd575f80fd5b5f60208284031215612b7f575f80fd5b81516129dd8161282b565b6001600160a01b03929092168252602082015260400190565b5f60208284031215612bb3575f80fd5b5051919050565b818382375f9101908152919050565b634e487b7160e01b5f52601160045260245ffd5b5f82612bf757634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115612c0f57612c0f612bc9565b92915050565b8082028115828204841417612c0f57612c0f612bc9565b81810381811115612c0f57612c0f612bc9565b5f60018201612c5057612c50612bc9565b5060010190565b83815260406020820152816040820152818360608301375f818301606090810191909152601f909201601f1916010192915050565b5f60208284031215612c9c575f80fd5b813560ff811681146129dd575f80fdfe000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4a2646970667358221220bd8c49530a69260ebce60101df0b4e0eb8fc8bee38682093d15433735c2379f964736f6c63430008140033

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

000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a

-----Decoded View---------------
Arg [0] : _exchangeProxy (address): 0xDef1C0ded9bec7F1a1670819833240f027b25EfF
Arg [1] : _pool (address): 0xC7DE47b9Ca2Fc753D6a2F167D8b3e19c6D18b19a

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff
Arg [1] : 000000000000000000000000c7de47b9ca2fc753d6a2f167d8b3e19c6d18b19a


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.