ETH Price: $2,679.81 (+1.61%)

Contract

0x71d86BE6eaC93A608E6054788c1DA12Dec450c82
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Unbond160804362022-11-30 4:31:47803 days ago1669782707IN
0x71d86BE6...Dec450c82
0 ETH0.0021731111.65156559
Bond160786292022-11-29 22:28:47803 days ago1669760927IN
0x71d86BE6...Dec450c82
0 ETH0.0014484510.49045105
Deposit160786172022-11-29 22:26:23803 days ago1669760783IN
0x71d86BE6...Dec450c82
0 ETH0.0011235410.60451946
Bond160762602022-11-29 14:31:11804 days ago1669732271IN
0x71d86BE6...Dec450c82
0 ETH0.0024853318
Deposit160762562022-11-29 14:30:23804 days ago1669732223IN
0x71d86BE6...Dec450c82
0 ETH0.001907118
Bond160747482022-11-29 9:27:35804 days ago1669714055IN
0x71d86BE6...Dec450c82
0 ETH0.0017229712.47860451
Deposit160747452022-11-29 9:26:59804 days ago1669714019IN
0x71d86BE6...Dec450c82
0 ETH0.0012052911.37611991
Bond160742782022-11-29 7:52:59804 days ago1669708379IN
0x71d86BE6...Dec450c82
0 ETH0.0017554812.71522262
Bond160742762022-11-29 7:52:35804 days ago1669708355IN
0x71d86BE6...Dec450c82
0 ETH0.0017391212.17243574
Deposit160742752022-11-29 7:52:23804 days ago1669708343IN
0x71d86BE6...Dec450c82
0 ETH0.0011014212.39817368
Deposit160742702022-11-29 7:51:23804 days ago1669708283IN
0x71d86BE6...Dec450c82
0 ETH0.0013411712.65860802
Withdraw160742522022-11-29 7:47:47804 days ago1669708067IN
0x71d86BE6...Dec450c82
0 ETH0.0009785512.32612649
Deposit160742422022-11-29 7:45:47804 days ago1669707947IN
0x71d86BE6...Dec450c82
0 ETH0.0007987911.13296374
Bond160742202022-11-29 7:41:23804 days ago1669707683IN
0x71d86BE6...Dec450c82
0 ETH0.0016073911.2504363
Deposit160742022022-11-29 7:37:47804 days ago1669707467IN
0x71d86BE6...Dec450c82
0 ETH0.0010867712.23154436
Bond160741832022-11-29 7:33:59804 days ago1669707239IN
0x71d86BE6...Dec450c82
0 ETH0.0016872611.80947585
Bond160741782022-11-29 7:32:59804 days ago1669707179IN
0x71d86BE6...Dec450c82
0 ETH0.0015956711.16936
Deposit160741782022-11-29 7:32:59804 days ago1669707179IN
0x71d86BE6...Dec450c82
0 ETH0.0009923911.16936
Deposit160741742022-11-29 7:32:11804 days ago1669707131IN
0x71d86BE6...Dec450c82
0 ETH0.0010088911.35500858
Deposit160741722022-11-29 7:31:47804 days ago1669707107IN
0x71d86BE6...Dec450c82
0 ETH0.0012271211.58343299
Bond160739252022-11-29 6:41:59804 days ago1669704119IN
0x71d86BE6...Dec450c82
0 ETH0.0016735312.12060153
Deposit160739132022-11-29 6:39:35804 days ago1669703975IN
0x71d86BE6...Dec450c82
0 ETH0.0012211211.52547203
Bond160738062022-11-29 6:18:11804 days ago1669702691IN
0x71d86BE6...Dec450c82
0 ETH0.0017442312.63259079
Deposit160737912022-11-29 6:15:11804 days ago1669702511IN
0x71d86BE6...Dec450c82
0 ETH0.0011662711.00778493
Bond160736752022-11-29 5:51:47804 days ago1669701107IN
0x71d86BE6...Dec450c82
0 ETH0.0017467512.65088866
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:
Pool

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : Pool.sol
pragma solidity ^0.5.17;
pragma experimental ABIEncoderV2;

import "./Constants.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IMetaPool.sol";
import "./interfaces/IERC20.sol";
import "./interfaces/IDollar.sol";
import "./interfaces/IForge.sol";
import "./libs/UniswapV2Library.sol";

contract PoolAccount {
    enum Status {
        Frozen,
        Fluid,
        Locked
    }

    struct State {
        uint256 staged;
        uint256 claimableTotal;
        uint256 lastClaimTime;
        uint256 bonded;
        uint256 phantom;
        uint256 fluidUntil;
    }
}

contract PoolStorage {
    struct Provider {
        IForge dao;
        IDollar dollar;
        IERC20 lpToken;
    }

    struct Balance {
        uint256 staged;
        uint256 claimable;
        uint256 bonded;
        uint256 phantom;
    }

    struct State {
        Balance balance;
        Provider provider;
        bool paused;
        mapping(address => PoolAccount.State) accounts;
    }
}

contract PoolState {
    PoolStorage.State _state;
}

contract PoolGetters is PoolState {
    using SafeMath for uint256;

    /**
     * Global
     */

    function crv3() public view returns (address) {
        return Constants.getCrv3Address();
    }

    function dao() public view returns (IForge) {
        return _state.provider.dao;
    }

    function dollar() public view returns (IDollar) {
        return _state.provider.dollar;
    }

    function lpToken() public view returns (IERC20) {
        return _state.provider.lpToken;
    }

    function totalBonded() public view returns (uint256) {
        return _state.balance.bonded;
    }

    function totalStaged() public view returns (uint256) {
        return _state.balance.staged;
    }

    function totalClaimable() public view returns (uint256) {
        return _state.balance.claimable;
    }

    function totalPhantom() public view returns (uint256) {
        return _state.balance.phantom;
    }

    function totalRewarded() public view returns (uint256) {
        return dollar().balanceOf(address(this)).sub(totalClaimable());
    }

    function paused() public view returns (bool) {
        return _state.paused;
    }

    /**
     * Account
     */

    function balanceOfStaged(address account) public view returns (uint256) {
        return _state.accounts[account].staged;
    }

    function balanceOfClaimableTotal(address account) public view returns (uint256) {
        return _state.accounts[account].claimableTotal;
    }

    function balanceOfClaimable(address account) public view returns (uint256) {
        if (block.timestamp >= getClaimFinishTime(account)) return balanceOfClaimableTotal(account);
        return balanceOfClaimableTotal(account).mul(block.timestamp.sub(getLastClaimTime(account))).div(Constants.getPoolExitLockupSeconds());
    }

    function getLastClaimTime(address account) public view returns (uint256) {
        return _state.accounts[account].lastClaimTime;
    }

    function getClaimFinishTime(address account) public view returns (uint256) {
        return getLastClaimTime(account).add(Constants.getPoolExitLockupSeconds());
    }

    function balanceOfBonded(address account) public view returns (uint256) {
        return _state.accounts[account].bonded;
    }

    function balanceOfPhantom(address account) public view returns (uint256) {
        return _state.accounts[account].phantom;
    }

    function balanceOfRewarded(address account) public view returns (uint256) {
        uint256 totalBonded = totalBonded();
        if (totalBonded == 0) {
            return 0;
        }

        uint256 totalRewardedWithPhantom = totalRewarded().add(totalPhantom());
        uint256 balanceOfRewardedWithPhantom = totalRewardedWithPhantom
            .mul(balanceOfBonded(account))
            .div(totalBonded);

        uint256 balanceOfPhantom = balanceOfPhantom(account);
        if (balanceOfRewardedWithPhantom > balanceOfPhantom) {
            return balanceOfRewardedWithPhantom.sub(balanceOfPhantom);
        }
        return 0;
    }

    function fluidUntil(address account) public view returns (uint256) {
        return _state.accounts[account].fluidUntil;
    }

    function statusOf(address account)
        public
        view
        returns (PoolAccount.Status)
    {
        return
            epoch() >= _state.accounts[account].fluidUntil
                ? PoolAccount.Status.Frozen
                : PoolAccount.Status.Fluid;
    }

    /**
     * Epoch
     */

    function epoch() internal view returns (uint256) {
        return dao().epoch();
    }
}

contract PoolSetters is PoolState, PoolGetters {
    using SafeMath for uint256;

    /**
     * Global
     */

    function pause() internal {
        _state.paused = true;
    }

    /**
     * Account
     */

    function incrementBalanceOfBonded(address account, uint256 amount)
        internal
    {
        _state.accounts[account].bonded = _state.accounts[account].bonded.add(
            amount
        );
        _state.balance.bonded = _state.balance.bonded.add(amount);
    }

    function decrementBalanceOfBonded(
        address account,
        uint256 amount,
        string memory reason
    ) internal {
        _state.accounts[account].bonded = _state.accounts[account].bonded.sub(
            amount,
            reason
        );
        _state.balance.bonded = _state.balance.bonded.sub(amount, reason);
    }

    function incrementBalanceOfStaged(address account, uint256 amount)
        internal
    {
        _state.accounts[account].staged = _state.accounts[account].staged.add(
            amount
        );
        _state.balance.staged = _state.balance.staged.add(amount);
    }

    function decrementBalanceOfStaged(
        address account,
        uint256 amount,
        string memory reason
    ) internal {
        _state.accounts[account].staged = _state.accounts[account].staged.sub(
            amount,
            reason
        );
        _state.balance.staged = _state.balance.staged.sub(amount, reason);
    }

    function incrementBalanceOfClaimable(address account, uint256 amount)
        internal
    {
        _state.accounts[account].claimableTotal = _state
            .accounts[account]
            .claimableTotal
            .add(amount);
        _state.balance.claimable = _state.balance.claimable.add(amount);
    }

    function decrementBalanceOfClaimable(
        address account,
        uint256 amount,
        string memory reason
    ) internal {
        _state.accounts[account].claimableTotal = _state
            .accounts[account]
            .claimableTotal
            .sub(amount, reason);
        _state.balance.claimable = _state.balance.claimable.sub(amount, reason);
    }

    function updateLastClaimTime(address account) internal {
        _state.accounts[account].lastClaimTime = block.timestamp;
    }

    function incrementBalanceOfPhantom(address account, uint256 amount)
        internal
    {
        _state.accounts[account].phantom = _state.accounts[account].phantom.add(
            amount
        );
        _state.balance.phantom = _state.balance.phantom.add(amount);
    }

    function decrementBalanceOfPhantom(
        address account,
        uint256 amount,
        string memory reason
    ) internal {
        _state.accounts[account].phantom = _state.accounts[account].phantom.sub(
            amount,
            reason
        );
        _state.balance.phantom = _state.balance.phantom.sub(amount, reason);
    }

    function unfreeze(address account) internal {
        _state.accounts[account].fluidUntil = epoch().add(
            Constants.getPoolExitLockupEpochs()
        );
    }
}

contract Liquidity is PoolGetters {
    function addLiquidity(uint256 dollarAmount, uint256 expectedReturn)
        internal
        returns (uint256, uint256)
    {
        IERC20 crv3Token = IERC20(crv3());
        address lpAddress = address(lpToken());
        uint256 balanceWas = lpToken().balanceOf(address(this));

        crv3Token.transferFrom(msg.sender, address(this), dollarAmount);

        if (crv3Token.allowance(address(this), lpAddress) < dollarAmount)
            dollar().approve(lpAddress, 2**256 - 1);

        uint256 crv3Allowed = crv3Token.allowance(address(this), lpAddress);

        if (crv3Allowed > 0 && crv3Allowed < dollarAmount)
            crv3Token.approve(lpAddress, 0);

        if (crv3Allowed == 0 || crv3Allowed < dollarAmount)
            crv3Token.approve(lpAddress, 2**256 - 1);

        IMetaPool(lpAddress).add_liquidity(
            [dollarAmount, dollarAmount],
            expectedReturn
        );

        return (
            dollarAmount,
            lpToken().balanceOf(address(this)).sub(balanceWas)
        );
    }
}

contract Pool is PoolSetters, Liquidity {
    using SafeMath for uint256;

    constructor(address dollar, address lpToken) public {
        _state.provider.dao = IForge(msg.sender);
        _state.provider.dollar = IDollar(dollar);
        _state.provider.lpToken = IERC20(lpToken);
    }

    bytes32 private constant FILE = "Pool";

    event Deposit(address indexed account, uint256 value);
    event Withdraw(address indexed account, uint256 value);
    event Claim(address indexed account, uint256 value);
    event Bond(address indexed account, uint256 start, uint256 value);
    event Unbond(
        address indexed account,
        uint256 start,
        uint256 value,
        uint256 newClaimable
    );
    event Provide(
        address indexed account,
        uint256 value,
        uint256 lessCrv3,
        uint256 lpAmount
    );

    function deposit(uint256 value) external onlyFrozen(msg.sender) notPaused {
        lpToken().transferFrom(msg.sender, address(this), value);
        incrementBalanceOfStaged(msg.sender, value);

        balanceCheck();

        emit Deposit(msg.sender, value);
    }

    function withdraw(uint256 value) external onlyFrozen(msg.sender) {
        lpToken().transfer(msg.sender, value);
        decrementBalanceOfStaged(
            msg.sender,
            value,
            "Pool: insufficient staged balance"
        );

        balanceCheck();

        emit Withdraw(msg.sender, value);
    }

    function claim(uint256 value) public {
        require(balanceOfClaimable(msg.sender) >= value, "Pool: insufficient pending claimable balance");

        dollar().transfer(msg.sender, value);
        decrementBalanceOfClaimable(
            msg.sender,
            value,
            "Pool: insufficient claimable balance"
        );

        updateLastClaimTime(msg.sender);
        balanceCheck();

        emit Claim(msg.sender, value);
    }

    function bond(uint256 value) external notPaused {
        unfreeze(msg.sender);

        uint256 totalRewardedWithPhantom = totalRewarded().add(totalPhantom());
        uint256 newPhantom = totalBonded() == 0
            ? totalRewarded() == 0
                ? Constants.getInitialStakeMultiple().mul(value)
                : 0
            : totalRewardedWithPhantom.mul(value).div(totalBonded());

        incrementBalanceOfBonded(msg.sender, value);
        incrementBalanceOfPhantom(msg.sender, newPhantom);
        decrementBalanceOfStaged(
            msg.sender,
            value,
            "Pool: insufficient staged balance"
        );

        balanceCheck();

        emit Bond(msg.sender, epoch().add(1), value);
    }

    function unbond(uint256 value) external {
        unfreeze(msg.sender);

        uint256 balanceOfBonded = balanceOfBonded(msg.sender);
        Require.that(balanceOfBonded > 0, FILE, "insufficient bonded balance");

        uint256 claimableBalance = balanceOfClaimable(msg.sender);
        if (claimableBalance > 0) {
            claim(claimableBalance);
        }

        uint256 newClaimable = balanceOfRewarded(msg.sender).mul(value).div(
            balanceOfBonded
        );
        uint256 lessPhantom = balanceOfPhantom(msg.sender).mul(value).div(
            balanceOfBonded
        );

        incrementBalanceOfStaged(msg.sender, value);
        incrementBalanceOfClaimable(msg.sender, newClaimable);
        decrementBalanceOfBonded(
            msg.sender,
            value,
            "Pool: insufficient bonded balance"
        );
        decrementBalanceOfPhantom(
            msg.sender,
            lessPhantom,
            "Pool: insufficient phantom balance"
        );

        updateLastClaimTime(msg.sender);
        balanceCheck();

        emit Unbond(msg.sender, epoch().add(1), value, newClaimable);
    }

    function provide(uint256 value, uint256 expectedReturn)
        external
        onlyFrozen(msg.sender)
        notPaused
    {
        Require.that(totalBonded() > 0, FILE, "insufficient total bonded");

        Require.that(totalRewarded() > 0, FILE, "insufficient total rewarded");

        Require.that(
            balanceOfRewarded(msg.sender) >= value,
            FILE,
            "insufficient rewarded balance"
        );

        (uint256 lessCrv3, uint256 lpAmount) = addLiquidity(
            value,
            expectedReturn
        );

        uint256 totalRewardedWithPhantom = totalRewarded()
            .add(totalPhantom())
            .add(value);
        uint256 newPhantomFromBonded = totalRewardedWithPhantom
            .mul(lpAmount)
            .div(totalBonded());

        incrementBalanceOfBonded(msg.sender, lpAmount);
        incrementBalanceOfPhantom(msg.sender, value.add(newPhantomFromBonded));

        balanceCheck();

        emit Provide(msg.sender, value, lessCrv3, lpAmount);
    }

    function setDao(IForge _dao) external onlyDao {
        _state.provider.dao = _dao;
    }

    function emergencyWithdraw(address token, uint256 value) external onlyDao {
        IERC20(token).transfer(address(dao()), value);
    }

    function emergencyPause() external onlyDao {
        pause();
    }

    function balanceCheck() private {
        Require.that(
            lpToken().balanceOf(address(this)) >=
                totalStaged().add(totalBonded()),
            FILE,
            "Inconsistent UNI-V2 balances"
        );
    }

    modifier onlyFrozen(address account) {
        Require.that(
            statusOf(account) == PoolAccount.Status.Frozen,
            FILE,
            "Not frozen"
        );

        _;
    }

    modifier onlyDao() {
        Require.that(msg.sender == address(dao()), FILE, "Not dao");

        _;
    }

    modifier notPaused() {
        Require.that(!paused(), FILE, "Paused");

        _;
    }
}

File 2 of 11 : Constants.sol
pragma solidity ^0.5.17;

import "./libs/Decimal.sol";
import "./libs/Require.sol";

library Constants {
    /* Chain */
    uint256 private constant CHAIN_ID = 1; // Mainnet

    /* Bootstrapping */
    uint256 private constant BOOTSTRAPPING_PERIOD = 504; // 21 days
    uint256 private constant BOOTSTRAPPING_PRICE = 1078280614764947472; // Should be 0.1 difference between peg

    /* Oracle */
    address private constant CRV3 =
        address(0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490); // Anywhere the term CRV3 is refernenced, consider that as "peg", really
    uint256 private constant ORACLE_RESERVE_MINIMUM = 1e22; // 10,000 T

    /* Bonding */
    uint256 private constant INITIAL_STAKE_MULTIPLE = 1e6; // 100 T -> 100M TS

    /* Epoch */
    struct EpochStrategy {
        uint256 offset;
        uint256 start;
        uint256 period;
    }

    uint256 private constant CURRENT_EPOCH_OFFSET = 0;
    uint256 private constant CURRENT_EPOCH_START = 1669687200;
    uint256 private constant CURRENT_EPOCH_PERIOD = 3600; // 1 hour

    /* Forge */
    uint256 private constant ADVANCE_INCENTIVE_IN_3CRV = 75 * 10**18; // 75 3CRV
    uint256 private constant ADVANCE_INCENTIVE_IN_T_MAX = 5000 * 10**18; // 5000 T

    uint256 private constant FORGE_EXIT_LOCKUP_EPOCHS = 144; // 6 days
    uint256 private constant FORGE_EXIT_LOCKUP_SECONDS = FORGE_EXIT_LOCKUP_EPOCHS * CURRENT_EPOCH_PERIOD;

    /* Pool */
    uint256 private constant POOL_EXIT_LOCKUP_EPOCHS = 72; // 3 days
    uint256 private constant POOL_EXIT_LOCKUP_SECONDS = POOL_EXIT_LOCKUP_EPOCHS * CURRENT_EPOCH_PERIOD;

    /* Market */
    uint256 private constant COUPON_EXPIRATION = 4320; // 180 days
    uint256 private constant DEBT_RATIO_CAP = 20e16; // 20%

    /* Regulator */
    uint256 private constant SUPPLY_CHANGE_LIMIT = 1e16; // 1%
    uint256 private constant COUPON_SUPPLY_CHANGE_LIMIT = 2e16; // 2%
    uint256 private constant ORACLE_POOL_RATIO = 50; // 50%
    uint256 private constant TREASURY_RATIO = 0; // 0%

    /* Deployed */
    address private constant TREASURY_ADDRESS =
        address(0x0000000000000000000000000000000000000000);

    /**
     * Getters
     */

    function getCrv3Address() internal pure returns (address) {
        return CRV3;
    }

    function getOracleReserveMinimum() internal pure returns (uint256) {
        return ORACLE_RESERVE_MINIMUM;
    }

    function getCurrentEpochStrategy()
        internal
        pure
        returns (EpochStrategy memory)
    {
        return
            EpochStrategy({
                offset: CURRENT_EPOCH_OFFSET,
                start: CURRENT_EPOCH_START,
                period: CURRENT_EPOCH_PERIOD
            });
    }

    function getInitialStakeMultiple() internal pure returns (uint256) {
        return INITIAL_STAKE_MULTIPLE;
    }

    function getBootstrappingPeriod() internal pure returns (uint256) {
        return BOOTSTRAPPING_PERIOD;
    }

    function getBootstrappingPrice()
        internal
        pure
        returns (Decimal.D256 memory)
    {
        return Decimal.D256({value: BOOTSTRAPPING_PRICE});
    }

    function getAdvanceIncentive() internal pure returns (uint256) {
        return ADVANCE_INCENTIVE_IN_3CRV;
    }

    function getMaxAdvanceTIncentive() internal pure returns (uint256) {
        return ADVANCE_INCENTIVE_IN_T_MAX;
    }

    function getForgeExitLockupEpochs() internal pure returns (uint256) {
        return FORGE_EXIT_LOCKUP_EPOCHS;
    }

    function getForgeExitLockupSeconds() internal pure returns (uint256) {
        return FORGE_EXIT_LOCKUP_SECONDS;
    }

    function getPoolExitLockupEpochs() internal pure returns (uint256) {
        return POOL_EXIT_LOCKUP_EPOCHS;
    }

    function getPoolExitLockupSeconds() internal pure returns (uint256) {
        return POOL_EXIT_LOCKUP_SECONDS;
    }

    function getCouponExpiration() internal pure returns (uint256) {
        return COUPON_EXPIRATION;
    }

    function getDebtRatioCap() internal pure returns (Decimal.D256 memory) {
        return Decimal.D256({value: DEBT_RATIO_CAP});
    }

    function getSupplyChangeLimit()
        internal
        pure
        returns (Decimal.D256 memory)
    {
        return Decimal.D256({value: SUPPLY_CHANGE_LIMIT});
    }

    function getCouponSupplyChangeLimit()
        internal
        pure
        returns (Decimal.D256 memory)
    {
        return Decimal.D256({value: COUPON_SUPPLY_CHANGE_LIMIT});
    }

    function getOraclePoolRatio() internal pure returns (uint256) {
        return ORACLE_POOL_RATIO;
    }

    function getTreasuryRatio() internal pure returns (uint256) {
        return TREASURY_RATIO;
    }

    function getChainId() internal pure returns (uint256) {
        return CHAIN_ID;
    }

    function getTreasuryAddress() internal pure returns (address) {
        return TREASURY_ADDRESS;
    }
}

File 3 of 11 : IDollar.sol
pragma solidity ^0.5.17;

import "./IERC20.sol";

contract IDollar is IERC20 {
    function burn(uint256 amount) public;

    function burnFrom(address account, uint256 amount) public;

    function mint(address account, uint256 amount) public returns (bool);
}

File 4 of 11 : IERC20.sol
pragma solidity ^0.5.17;

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

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

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

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

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

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

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

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

File 5 of 11 : IForge.sol
pragma solidity ^0.5.17;

contract IForge {
    function epoch() external view returns (uint256);
}

File 6 of 11 : IMetaPool.sol
pragma solidity ^0.5.17;

interface IMetaPool {
    event Transfer(
        address indexed sender,
        address indexed receiver,
        uint256 value
    );
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    event TokenExchange(
        address indexed buyer,
        int128 sold_id,
        uint256 tokens_sold,
        int128 bought_id,
        uint256 tokens_bought
    );
    event TokenExchangeUnderlying(
        address indexed buyer,
        int128 sold_id,
        uint256 tokens_sold,
        int128 bought_id,
        uint256 tokens_bought
    );
    event AddLiquidity(
        address indexed provider,
        uint256[2] token_amounts,
        uint256[2] fees,
        uint256 invariant,
        uint256 token_supply
    );
    event RemoveLiquidity(
        address indexed provider,
        uint256[2] token_amounts,
        uint256[2] fees,
        uint256 token_supply
    );
    event RemoveLiquidityOne(
        address indexed provider,
        uint256 token_amount,
        uint256 coin_amount,
        uint256 token_supply
    );
    event RemoveLiquidityImbalance(
        address indexed provider,
        uint256[2] token_amounts,
        uint256[2] fees,
        uint256 invariant,
        uint256 token_supply
    );
    event CommitNewAdmin(uint256 indexed deadline, address indexed admin);
    event NewAdmin(address indexed admin);
    event CommitNewFee(
        uint256 indexed deadline,
        uint256 fee,
        uint256 admin_fee
    );
    event NewFee(uint256 fee, uint256 admin_fee);
    event RampA(
        uint256 old_A,
        uint256 new_A,
        uint256 initial_time,
        uint256 future_time
    );
    event StopRampA(uint256 A, uint256 t);

    function initialize(
        string calldata _name,
        string calldata _symbol,
        address _coin,
        uint256 _decimals,
        uint256 _A,
        uint256 _fee,
        address _admin
    ) external;

    function decimals() external view returns (uint256);

    function transfer(address _to, uint256 _value) external returns (bool);

    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) external returns (bool);

    function approve(address _spender, uint256 _value) external returns (bool);

    function get_previous_balances() external view returns (uint256[2] memory);

    function get_balances() external view returns (uint256[2] memory);

    function get_twap_balances(
        uint256[2] calldata _first_balances,
        uint256[2] calldata _last_balances,
        uint256 _time_elapsed
    ) external view returns (uint256[2] memory);

    function get_price_cumulative_last()
        external
        view
        returns (uint256[2] memory);

    function admin_fee() external view returns (uint256);

    function A() external view returns (uint256);

    function A_precise() external view returns (uint256);

    function get_virtual_price() external view returns (uint256);

    function calc_token_amount(uint256[2] calldata _amounts, bool _is_deposit)
        external
        view
        returns (uint256);

    function calc_token_amount(
        uint256[2] calldata _amounts,
        bool _is_deposit,
        bool _previous
    ) external view returns (uint256);

    function add_liquidity(
        uint256[2] calldata _amounts,
        uint256 _min_mint_amount
    ) external returns (uint256);

    function add_liquidity(
        uint256[2] calldata _amounts,
        uint256 _min_mint_amount,
        address _receiver
    ) external returns (uint256);

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

    function get_dy(
        int128 i,
        int128 j,
        uint256 dx,
        uint256[2] calldata _balances
    ) external view returns (uint256);

    function get_dy_underlying(
        int128 i,
        int128 j,
        uint256 dx
    ) external view returns (uint256);

    function get_dy_underlying(
        int128 i,
        int128 j,
        uint256 dx,
        uint256[2] calldata _balances
    ) external view returns (uint256);

    function exchange(
        int128 i,
        int128 j,
        uint256 dx,
        uint256 min_dy
    ) external returns (uint256);

    function exchange(
        int128 i,
        int128 j,
        uint256 dx,
        uint256 min_dy,
        address _receiver
    ) external returns (uint256);

    function exchange_underlying(
        int128 i,
        int128 j,
        uint256 dx,
        uint256 min_dy
    ) external returns (uint256);

    function exchange_underlying(
        int128 i,
        int128 j,
        uint256 dx,
        uint256 min_dy,
        address _receiver
    ) external returns (uint256);

    function remove_liquidity(
        uint256 _burn_amount,
        uint256[2] calldata _min_amounts
    ) external returns (uint256[2] memory);

    function remove_liquidity(
        uint256 _burn_amount,
        uint256[2] calldata _min_amounts,
        address _receiver
    ) external returns (uint256[2] memory);

    function remove_liquidity_imbalance(
        uint256[2] calldata _amounts,
        uint256 _max_burn_amount
    ) external returns (uint256);

    function remove_liquidity_imbalance(
        uint256[2] calldata _amounts,
        uint256 _max_burn_amount,
        address _receiver
    ) external returns (uint256);

    function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)
        external
        view
        returns (uint256);

    function calc_withdraw_one_coin(
        uint256 _burn_amount,
        int128 i,
        bool _previous
    ) external view returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _burn_amount,
        int128 i,
        uint256 _min_received
    ) external returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _burn_amount,
        int128 i,
        uint256 _min_received,
        address _receiver
    ) external returns (uint256);

    function ramp_A(uint256 _future_A, uint256 _future_time) external;

    function stop_ramp_A() external;

    function admin_balances(uint256 i) external view returns (uint256);

    function withdraw_admin_fees() external;

    function admin() external view returns (address);

    function coins(uint256 arg0) external view returns (address);

    function balances(uint256 arg0) external view returns (uint256);

    function fee() external view returns (uint256);

    function block_timestamp_last() external view returns (uint256);

    function initial_A() external view returns (uint256);

    function future_A() external view returns (uint256);

    function initial_A_time() external view returns (uint256);

    function future_A_time() external view returns (uint256);

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function balanceOf(address arg0) external view returns (uint256);

    function allowance(address arg0, address arg1)
        external
        view
        returns (uint256);

    function totalSupply() external view returns (uint256);
}

File 7 of 11 : IUniswapV2Pair.sol
pragma solidity ^0.5.17;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

File 8 of 11 : Decimal.sol
pragma solidity ^0.5.17;

import "./SafeMath.sol";

/**
 * @title Decimal
 * @author dYdX
 *
 * Library that defines a fixed-point number with 18 decimal places.
 */
library Decimal {
    using SafeMath for uint256;

    // ============ Constants ============

    uint256 constant BASE = 10**18;

    // ============ Structs ============

    struct D256 {
        uint256 value;
    }

    // ============ Static Functions ============

    function zero() internal pure returns (D256 memory) {
        return D256({value: 0});
    }

    function one() internal pure returns (D256 memory) {
        return D256({value: BASE});
    }

    function from(uint256 a) internal pure returns (D256 memory) {
        return D256({value: a.mul(BASE)});
    }

    function ratio(uint256 a, uint256 b) internal pure returns (D256 memory) {
        return D256({value: getPartial(a, BASE, b)});
    }

    // ============ Self Functions ============

    function add(D256 memory self, uint256 b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: self.value.add(b.mul(BASE))});
    }

    function sub(D256 memory self, uint256 b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: self.value.sub(b.mul(BASE))});
    }

    function sub(
        D256 memory self,
        uint256 b,
        string memory reason
    ) internal pure returns (D256 memory) {
        return D256({value: self.value.sub(b.mul(BASE), reason)});
    }

    function mul(D256 memory self, uint256 b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: self.value.mul(b)});
    }

    function div(D256 memory self, uint256 b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: self.value.div(b)});
    }

    function pow(D256 memory self, uint256 b)
        internal
        pure
        returns (D256 memory)
    {
        if (b == 0) {
            return from(1);
        }

        D256 memory temp = D256({value: self.value});
        for (uint256 i = 1; i < b; i++) {
            temp = mul(temp, self);
        }

        return temp;
    }

    function add(D256 memory self, D256 memory b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: self.value.add(b.value)});
    }

    function sub(D256 memory self, D256 memory b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: self.value.sub(b.value)});
    }

    function sub(
        D256 memory self,
        D256 memory b,
        string memory reason
    ) internal pure returns (D256 memory) {
        return D256({value: self.value.sub(b.value, reason)});
    }

    function mul(D256 memory self, D256 memory b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: getPartial(self.value, b.value, BASE)});
    }

    function div(D256 memory self, D256 memory b)
        internal
        pure
        returns (D256 memory)
    {
        return D256({value: getPartial(self.value, BASE, b.value)});
    }

    function equals(D256 memory self, D256 memory b)
        internal
        pure
        returns (bool)
    {
        return self.value == b.value;
    }

    function greaterThan(D256 memory self, D256 memory b)
        internal
        pure
        returns (bool)
    {
        return compareTo(self, b) == 2;
    }

    function lessThan(D256 memory self, D256 memory b)
        internal
        pure
        returns (bool)
    {
        return compareTo(self, b) == 0;
    }

    function greaterThanOrEqualTo(D256 memory self, D256 memory b)
        internal
        pure
        returns (bool)
    {
        return compareTo(self, b) > 0;
    }

    function lessThanOrEqualTo(D256 memory self, D256 memory b)
        internal
        pure
        returns (bool)
    {
        return compareTo(self, b) < 2;
    }

    function isZero(D256 memory self) internal pure returns (bool) {
        return self.value == 0;
    }

    function asUint256(D256 memory self) internal pure returns (uint256) {
        return self.value.div(BASE);
    }

    // ============ Core Methods ============

    function getPartial(
        uint256 target,
        uint256 numerator,
        uint256 denominator
    ) private pure returns (uint256) {
        return target.mul(numerator).div(denominator);
    }

    function compareTo(D256 memory a, D256 memory b)
        private
        pure
        returns (uint256)
    {
        if (a.value == b.value) {
            return 1;
        }
        return a.value > b.value ? 2 : 0;
    }
}

File 9 of 11 : Require.sol
pragma solidity ^0.5.17;

/**
 * @title Require
 * @author dYdX
 *
 * Stringifies parameters to pretty-print revert messages. Costs more gas than regular require()
 */
library Require {

    // ============ Constants ============

    uint256 constant ASCII_ZERO = 48; // '0'
    uint256 constant ASCII_RELATIVE_ZERO = 87; // 'a' - 10
    uint256 constant ASCII_LOWER_EX = 120; // 'x'
    bytes2 constant COLON = 0x3a20; // ': '
    bytes2 constant COMMA = 0x2c20; // ', '
    bytes2 constant LPAREN = 0x203c; // ' <'
    byte constant RPAREN = 0x3e; // '>'
    uint256 constant FOUR_BIT_MASK = 0xf;

    // ============ Library Functions ============

    function that(
        bool must,
        bytes32 file,
        bytes32 reason
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason)
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        uint256 payloadA
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        RPAREN
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        uint256 payloadA,
        uint256 payloadB
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        COMMA,
                        stringify(payloadB),
                        RPAREN
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        address payloadA
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        RPAREN
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        address payloadA,
        uint256 payloadB
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        COMMA,
                        stringify(payloadB),
                        RPAREN
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        address payloadA,
        uint256 payloadB,
        uint256 payloadC
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        COMMA,
                        stringify(payloadB),
                        COMMA,
                        stringify(payloadC),
                        RPAREN
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        bytes32 payloadA
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        RPAREN
                    )
                )
            );
        }
    }

    function that(
        bool must,
        bytes32 file,
        bytes32 reason,
        bytes32 payloadA,
        uint256 payloadB,
        uint256 payloadC
    )
    internal
    pure
    {
        if (!must) {
            revert(
                string(
                    abi.encodePacked(
                        stringifyTruncated(file),
                        COLON,
                        stringifyTruncated(reason),
                        LPAREN,
                        stringify(payloadA),
                        COMMA,
                        stringify(payloadB),
                        COMMA,
                        stringify(payloadC),
                        RPAREN
                    )
                )
            );
        }
    }

    // ============ Private Functions ============

    function stringifyTruncated(
        bytes32 input
    )
    private
    pure
    returns (bytes memory)
    {
        // put the input bytes into the result
        bytes memory result = abi.encodePacked(input);

        // determine the length of the input by finding the location of the last non-zero byte
        for (uint256 i = 32; i > 0; ) {
            // reverse-for-loops with unsigned integer
            /* solium-disable-next-line security/no-modify-for-iter-var */
            i--;

            // find the last non-zero byte in order to determine the length
            if (result[i] != 0) {
                uint256 length = i + 1;

                /* solium-disable-next-line security/no-inline-assembly */
                assembly {
                    mstore(result, length) // r.length = length;
                }

                return result;
            }
        }

        // all bytes are zero
        return new bytes(0);
    }

    function stringify(
        uint256 input
    )
    private
    pure
    returns (bytes memory)
    {
        if (input == 0) {
            return "0";
        }

        // get the final string length
        uint256 j = input;
        uint256 length;
        while (j != 0) {
            length++;
            j /= 10;
        }

        // allocate the string
        bytes memory bstr = new bytes(length);

        // populate the string starting with the least-significant character
        j = input;
        for (uint256 i = length; i > 0; ) {
            // reverse-for-loops with unsigned integer
            /* solium-disable-next-line security/no-modify-for-iter-var */
            i--;

            // take last decimal digit
            bstr[i] = byte(uint8(ASCII_ZERO + (j % 10)));

            // remove the last decimal digit
            j /= 10;
        }

        return bstr;
    }

    function stringify(
        address input
    )
    private
    pure
    returns (bytes memory)
    {
        uint256 z = uint256(input);

        // addresses are "0x" followed by 20 bytes of data which take up 2 characters each
        bytes memory result = new bytes(42);

        // populate the result with "0x"
        result[0] = byte(uint8(ASCII_ZERO));
        result[1] = byte(uint8(ASCII_LOWER_EX));

        // for each byte (starting from the lowest byte), populate the result with two characters
        for (uint256 i = 0; i < 20; i++) {
            // each byte takes two characters
            uint256 shift = i * 2;

            // populate the least-significant character
            result[41 - shift] = char(z & FOUR_BIT_MASK);
            z = z >> 4;

            // populate the most-significant character
            result[40 - shift] = char(z & FOUR_BIT_MASK);
            z = z >> 4;
        }

        return result;
    }

    function stringify(
        bytes32 input
    )
    private
    pure
    returns (bytes memory)
    {
        uint256 z = uint256(input);

        // bytes32 are "0x" followed by 32 bytes of data which take up 2 characters each
        bytes memory result = new bytes(66);

        // populate the result with "0x"
        result[0] = byte(uint8(ASCII_ZERO));
        result[1] = byte(uint8(ASCII_LOWER_EX));

        // for each byte (starting from the lowest byte), populate the result with two characters
        for (uint256 i = 0; i < 32; i++) {
            // each byte takes two characters
            uint256 shift = i * 2;

            // populate the least-significant character
            result[65 - shift] = char(z & FOUR_BIT_MASK);
            z = z >> 4;

            // populate the most-significant character
            result[64 - shift] = char(z & FOUR_BIT_MASK);
            z = z >> 4;
        }

        return result;
    }

    function char(
        uint256 input
    )
    private
    pure
    returns (byte)
    {
        // return ASCII digit (0-9)
        if (input < 10) {
            return byte(uint8(input + ASCII_ZERO));
        }

        // return ASCII letter (a-f)
        return byte(uint8(input + ASCII_RELATIVE_ZERO));
    }
}

File 10 of 11 : SafeMath.sol
pragma solidity ^0.5.17;

library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 11 of 11 : UniswapV2Library.sol
pragma solidity ^0.5.17;

import "./SafeMath.sol";
import "../interfaces/IUniswapV2Pair.sol";

library UniswapV2Library {
    using SafeMath for uint;

    // returns sorted token addresses, used to handle return values from pairs sorted in this order
    function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
        require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');
        (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');
    }

    // calculates the CREATE2 address for a pair without making any external calls
    function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
        (address token0, address token1) = sortTokens(tokenA, tokenB);
        pair = address(uint(keccak256(abi.encodePacked(
                hex'ff',
                factory,
                keccak256(abi.encodePacked(token0, token1)),
                hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash
            ))));
    }

    // fetches and sorts the reserves for a pair
    function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
        (address token0,) = sortTokens(tokenA, tokenB);
        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    }

    // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
    function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
        require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
        require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        amountB = amountA.mul(reserveB) / reserveA;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"dollar","type":"address"},{"internalType":"address","name":"lpToken","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"start","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Bond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lessCrv3","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpAmount","type":"uint256"}],"name":"Provide","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"start","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newClaimable","type":"uint256"}],"name":"Unbond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdraw","type":"event"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfClaimableTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfPhantom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfRewarded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfStaged","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"bond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"claim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"crv3","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dao","outputs":[{"internalType":"contract IForge","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dollar","outputs":[{"internalType":"contract IDollar","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"emergencyPause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"fluidUntil","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getClaimFinishTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getLastClaimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lpToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"expectedReturn","type":"uint256"}],"name":"provide","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IForge","name":"_dao","type":"address"}],"name":"setDao","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"statusOf","outputs":[{"internalType":"enum PoolAccount.Status","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalPhantom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalRewarded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStaged","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"unbond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040516200221c3803806200221c833981016040819052620000349162000084565b600480546001600160a01b03199081163317909155600580546001600160a01b0394851690831617905560068054929093169116179055620000ef565b80516200007e81620000d5565b92915050565b600080604083850312156200009857600080fd5b6000620000a6858562000071565b9250506020620000b98582860162000071565b9150509250929050565b60006001600160a01b0382166200007e565b620000e081620000c3565b8114620000ec57600080fd5b50565b61211d80620000ff6000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80636637b882116101045780639940686e116100a2578063c0d7a94f11610071578063c0d7a94f14610398578063cf023779146103ab578063e0cf7285146103b3578063e8c3c54f146103bb576101cf565b80639940686e14610357578063a680e0bc1461036a578063aed29d071461037d578063b6b55f2514610385576101cf565b806386cf9f14116100de57806386cf9f14146102fe5780638901bf7b1461031157806395ccea671461032457806397a5d5b514610337576101cf565b80636637b882146102c35780636dca5abe146102d6578063825ad607146102eb576101cf565b806344d96e951161017157806351adeb571161014b57806351adeb571461028b57806351bf21d8146102935780635c975abb146102a65780635fcbd285146102bb576101cf565b806344d96e95146102735780634838ed191461027b57806351858e2714610283576101cf565b80632ad48299116101ad5780632ad48299146102255780632e1a7d4d14610238578063379607f51461024b5780634162169f1461025e576101cf565b80631667eb17146101d457806327de9e32146101fd57806329f32ed414610212575b600080fd5b6101e76101e2366004611ad7565b6103ce565b6040516101f49190611f2a565b60405180910390f35b61021061020b366004611b73565b61043f565b005b6101e7610220366004611ad7565b610596565b6101e7610233366004611ad7565b6105b4565b610210610246366004611b73565b6105d2565b610210610259366004611b73565b610701565b610266610832565b6040516101f49190611ecd565b6101e7610841565b6101e7610847565b61021061084d565b61026661088e565b6101e76102a1366004611ad7565b61089d565b6102ae6108bb565b6040516101f49190611ebf565b6102666108c4565b6102106102d1366004611b55565b6108d3565b6102de610900565b6040516101f49190611e0f565b6101e76102f9366004611ad7565b61090f565b6101e761030c366004611ad7565b61092d565b6101e761031f366004611ad7565b610948565b610210610332366004611afd565b61095e565b61034a610345366004611ad7565b6109f5565b6040516101f49190611edb565b610210610365366004611b73565b610a2e565b6101e7610378366004611ad7565b610b4c565b6101e7610b6a565b610210610393366004611b73565b610c06565b6101e76103a6366004611ad7565b610cf1565b6101e7610d79565b6101e7610d7f565b6102106103c9366004611baf565b610d85565b60006103d982610948565b42106103ef576103e8826105b4565b905061043a565b6104376103fa610efc565b61042b61041661040986610b4c565b429063ffffffff610f0316565b61041f866105b4565b9063ffffffff610f4e16565b9063ffffffff610f8816565b90505b919050565b61044833610fca565b60006104533361090f565b905061048a6000821163141bdbdb60e21b7f696e73756666696369656e7420626f6e6465642062616c616e63650000000000610ffc565b6000610495336103ce565b905080156104a6576104a681610701565b60006104b98361042b8661041f33610cf1565b905060006104ce8461042b8761041f33610596565b90506104da3386611051565b6104e433836110ae565b61050733866040518060600160405280602181526020016120ba60219139611113565b61052a338260405180606001604052806022815260200161207760229139611178565b610533336111dd565b61053b6111fd565b337f93530ac0ee8c50e696e13c5ac62355d0c0ba4bd943620d5bda1eb08b64ae7512610576600161056a6112c6565b9063ffffffff61134016565b878560405161058793929190611f46565b60405180910390a25050505050565b6001600160a01b031660009081526008602052604090206004015490565b6001600160a01b031660009081526008602052604090206001015490565b3361060960005b6105e2836109f5565b60028111156105ed57fe5b1463141bdbdb60e21b692737ba10333937bd32b760b11b610ffc565b6106116108c4565b6001600160a01b031663a9059cbb33846040518363ffffffff1660e01b815260040161063e929190611e45565b602060405180830381600087803b15801561065857600080fd5b505af115801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106909190810190611b37565b506106b4338360405180606001604052806021815260200161209960219139611365565b6106bc6111fd565b336001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364836040516106f59190611f2a565b60405180910390a25050565b8061070b336103ce565b10156107325760405162461bcd60e51b815260040161072990611efa565b60405180910390fd5b61073a61088e565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401610767929190611e45565b602060405180830381600087803b15801561078157600080fd5b505af1158015610795573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107b99190810190611b37565b506107dd3382604051806060016040528060248152602001612053602491396113c5565b6107e6336111dd565b6107ee6111fd565b336001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4826040516108279190611f2a565b60405180910390a250565b6004546001600160a01b031690565b60025490565b60015490565b610884610858610832565b6001600160a01b0316336001600160a01b03161463141bdbdb60e21b664e6f742064616f60c81b610ffc565b61088c61142d565b565b6005546001600160a01b031690565b6001600160a01b031660009081526008602052604090206005015490565b60075460ff1690565b6006546001600160a01b031690565b6108de610858610832565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600061090a61143c565b905090565b6001600160a01b031660009081526008602052604090206003015490565b6001600160a01b031660009081526008602052604090205490565b6000610437610955610efc565b61056a84610b4c565b610969610858610832565b816001600160a01b031663a9059cbb610980610832565b836040518363ffffffff1660e01b815260040161099e929190611e96565b602060405180830381600087803b1580156109b857600080fd5b505af11580156109cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109f09190810190611b37565b505050565b6001600160a01b038116600090815260086020526040812060050154610a196112c6565b1015610a26576001610437565b506000919050565b610a51610a396108bb565b1563141bdbdb60e21b6514185d5cd95960d21b610ffc565b610a5a33610fca565b6000610a6f610a67610d7f565b61056a610b6a565b90506000610a7b610841565b15610aa057610a9b610a8b610841565b61042b848663ffffffff610f4e16565b610ac0565b610aa8610b6a565b15610ab4576000610ac0565b610ac08361041f611454565b9050610acc338461145b565b610ad633826114bd565b610af9338460405180606001604052806021815260200161209960219139611365565b610b016111fd565b337f3ae9ad26d7d47616d306d7757b947fe7b0f9a7c61a5f0dc784b0ddb6c7c40b5a610b30600161056a6112c6565b85604051610b3f929190611f38565b60405180910390a2505050565b6001600160a01b031660009081526008602052604090206002015490565b600061090a610b77610847565b610b7f61088e565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610baa9190611e0f565b60206040518083038186803b158015610bc257600080fd5b505afa158015610bd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610bfa9190810190611b91565b9063ffffffff610f0316565b33610c1160006105d9565b610c1c610a396108bb565b610c246108c4565b6001600160a01b03166323b872dd3330856040518463ffffffff1660e01b8152600401610c5393929190611e1d565b602060405180830381600087803b158015610c6d57600080fd5b505af1158015610c81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ca59190810190611b37565b50610cb03383611051565b610cb86111fd565b336001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c836040516106f59190611f2a565b600080610cfc610841565b905080610d0d57600091505061043a565b6000610d1a610a67610d7f565b90506000610d3b8361042b610d2e8861090f565b859063ffffffff610f4e16565b90506000610d4886610596565b905080821115610d6d57610d62828263ffffffff610f0316565b94505050505061043a565b50600095945050505050565b60005490565b60035490565b33610d9060006105d9565b610d9b610a396108bb565b610dd76000610da8610841565b1163141bdbdb60e21b7f696e73756666696369656e7420746f74616c20626f6e64656400000000000000610ffc565b610e136000610de4610b6a565b1163141bdbdb60e21b7f696e73756666696369656e7420746f74616c2072657761726465640000000000610ffc565b610e5083610e2033610cf1565b101563141bdbdb60e21b7f696e73756666696369656e742072657761726465642062616c616e6365000000610ffc565b600080610e5d858561151f565b915091506000610e728661056a610a67610d7f565b90506000610e81610a8b610841565b9050610e8d338461145b565b610ea633610ea1898463ffffffff61134016565b6114bd565b610eae6111fd565b336001600160a01b03167fbe9d8078818a53534ce225882a00e0c6f709b5296c8a08c3a1f23f9ffd448380888686604051610eeb93929190611f46565b60405180910390a250505050505050565b6203f48090565b6000610f4583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506119b3565b90505b92915050565b600082610f5d57506000610f48565b82820282848281610f6a57fe5b0414610f455760405162461bcd60e51b815260040161072990611f1a565b6000610f4583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506119e4565b610fdd610fd5611a1b565b61056a6112c6565b6001600160a01b03909116600090815260086020526040902060050155565b826109f05761100a82611a20565b6101d160f51b61101983611a20565b60405160200161102b93929190611dde565b60408051601f198184030181529082905262461bcd60e51b825261072991600401611ee9565b6001600160a01b03821660009081526008602052604090205461107a908263ffffffff61134016565b6001600160a01b038316600090815260086020526040812091909155546110a7908263ffffffff61134016565b6000555050565b6001600160a01b0382166000908152600860205260409020600101546110da908263ffffffff61134016565b6001600160a01b03831660009081526008602052604090206001908101919091555461110c908263ffffffff61134016565b6001555050565b6001600160a01b03831660009081526008602052604090206003015461114090838363ffffffff6119b316565b6001600160a01b03841660009081526008602052604090206003015560025461117090838363ffffffff6119b316565b600255505050565b6001600160a01b0383166000908152600860205260409020600401546111a590838363ffffffff6119b316565b6001600160a01b0384166000908152600860205260409020600401556003546111d590838363ffffffff6119b316565b600355505050565b6001600160a01b0316600090815260086020526040902042600290910155565b61088c61121361120b610841565b61056a610d79565b61121b6108c4565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016112469190611e0f565b60206040518083038186803b15801561125e57600080fd5b505afa158015611272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112969190810190611b91565b101563141bdbdb60e21b7f496e636f6e73697374656e7420554e492d56322062616c616e63657300000000610ffc565b60006112d0610832565b6001600160a01b031663900cf0cf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561130857600080fd5b505afa15801561131c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061090a9190810190611b91565b600082820183811015610f455760405162461bcd60e51b815260040161072990611f0a565b6001600160a01b03831660009081526008602052604090205461138f90838363ffffffff6119b316565b6001600160a01b038416600090815260086020526040812091909155546113bd90838363ffffffff6119b316565b600055505050565b6001600160a01b0383166000908152600860205260409020600101546113f290838363ffffffff6119b316565b6001600160a01b03841660009081526008602052604090206001908101919091555461142590838363ffffffff6119b316565b600155505050565b6007805460ff19166001179055565b736c3f90f043a72fa612cbac8115ee7e52bde6e49090565b620f424090565b6001600160a01b038216600090815260086020526040902060030154611487908263ffffffff61134016565b6001600160a01b0383166000908152600860205260409020600301556002546114b6908263ffffffff61134016565b6002555050565b6001600160a01b0382166000908152600860205260409020600401546114e9908263ffffffff61134016565b6001600160a01b038316600090815260086020526040902060040155600354611518908263ffffffff61134016565b6003555050565b600080600061152c610900565b905060006115386108c4565b905060006115446108c4565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161156f9190611e0f565b60206040518083038186803b15801561158757600080fd5b505afa15801561159b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115bf9190810190611b91565b6040516323b872dd60e01b81529091506001600160a01b038416906323b872dd906115f290339030908c90600401611e1d565b602060405180830381600087803b15801561160c57600080fd5b505af1158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116449190810190611b37565b50604051636eb1769f60e11b815287906001600160a01b0385169063dd62ed3e906116759030908790600401611e60565b60206040518083038186803b15801561168d57600080fd5b505afa1580156116a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116c59190810190611b91565b1015611756576116d361088e565b6001600160a01b031663095ea7b3836000196040518363ffffffff1660e01b8152600401611702929190611e7b565b602060405180830381600087803b15801561171c57600080fd5b505af1158015611730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117549190810190611b37565b505b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e906117879030908790600401611e60565b60206040518083038186803b15801561179f57600080fd5b505afa1580156117b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117d79190810190611b91565b90506000811180156117e857508781105b156118705760405163095ea7b360e01b81526001600160a01b0385169063095ea7b39061181c908690600090600401611e7b565b602060405180830381600087803b15801561183657600080fd5b505af115801561184a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061186e9190810190611b37565b505b80158061187c57508781105b156119055760405163095ea7b360e01b81526001600160a01b0385169063095ea7b3906118b190869060001990600401611e7b565b602060405180830381600087803b1580156118cb57600080fd5b505af11580156118df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506119039190810190611b37565b505b604080518082018252898152602081018a90529051630b4c7e4d60e01b81526001600160a01b03851691630b4c7e4d9161194491908b90600401611ea4565b602060405180830381600087803b15801561195e57600080fd5b505af1158015611972573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506119969190810190611b91565b50876119a483610b7f6108c4565b95509550505050509250929050565b600081848411156119d75760405162461bcd60e51b81526004016107299190611ee9565b50508183035b9392505050565b60008183611a055760405162461bcd60e51b81526004016107299190611ee9565b506000838581611a1157fe5b0495945050505050565b604890565b60608082604051602001611a349190611dc9565b60408051601f19818403018152919052905060205b8015611a8957815160001990910190829082908110611a6457fe5b01602001516001600160f81b03191615611a84576001018152905061043a565b611a49565b505060408051600081526020810190915292915050565b8035610f4881612023565b8051610f4881612037565b8035610f4881612040565b8035610f4881612049565b8051610f4881612049565b600060208284031215611ae957600080fd5b6000611af58484611aa0565b949350505050565b60008060408385031215611b1057600080fd5b6000611b1c8585611aa0565b9250506020611b2d85828601611ac1565b9150509250929050565b600060208284031215611b4957600080fd5b6000611af58484611aab565b600060208284031215611b6757600080fd5b6000611af58484611ab6565b600060208284031215611b8557600080fd5b6000611af58484611ac1565b600060208284031215611ba357600080fd5b6000611af58484611acc565b60008060408385031215611bc257600080fd5b6000611b1c8585611ac1565b6000611bda8383611dc0565b505060200190565b611beb81611fbb565b82525050565b611beb81611f7d565b611c0381611f64565b611c0d818461043a565b9250611c1882611f61565b8060005b83811015611c46578151611c308782611bce565b9650611c3b83611f6e565b925050600101611c1c565b505050505050565b611beb81611f88565b611beb611c6382611f8d565b611f61565b611beb611c6382611f61565b6000611c7f82611f6a565b611c89818561043a565b9350611c99818560208601611fdc565b9290920192915050565b611beb81611f9a565b611beb81611fc6565b611beb81611fd1565b6000611cc982611f6a565b611cd38185611f74565b9350611ce3818560208601611fdc565b611cec8161200c565b9093019392505050565b6000611d03602c83611f74565b7f506f6f6c3a20696e73756666696369656e742070656e64696e6720636c61696d81526b61626c652062616c616e636560a01b602082015260400192915050565b6000611d51601b83611f74565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000611d8a602183611f74565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b611beb81611f61565b6000611dd58284611c68565b50602001919050565b6000611dea8286611c74565b9150611df68285611c57565b600282019150611e068284611c74565b95945050505050565b60208101610f488284611bf1565b60608101611e2b8286611be2565b611e386020830185611bf1565b611af56040830184611dc0565b60408101611e538285611be2565b6119dd6020830184611dc0565b60408101611e6e8285611bf1565b6119dd6020830184611bf1565b60408101611e898285611bf1565b6119dd6020830184611cb5565b60408101611e538285611bf1565b60608101611eb28285611bfa565b6119dd6040830184611dc0565b60208101610f488284611c4e565b60208101610f488284611ca3565b60208101610f488284611cac565b60208082528101610f458184611cbe565b6020808252810161043781611cf6565b6020808252810161043781611d44565b6020808252810161043781611d7d565b60208101610f488284611dc0565b60408101611e538285611dc0565b60608101611f548286611dc0565b611e386020830185611dc0565b90565b50600290565b5190565b60200190565b90815260200190565b600061043782611faf565b151590565b6001600160f01b03191690565b600061043782611f7d565b8061043a81612016565b6001600160a01b031690565b600061043782611f9a565b600061043782611fa5565b600061043782611f61565b60005b83811015611ff7578181015183820152602001611fdf565b83811115612006576000848401525b50505050565b601f01601f191690565b6003811061202057fe5b50565b61202c81611f7d565b811461202057600080fd5b61202c81611f88565b61202c81611f9a565b61202c81611f6156fe506f6f6c3a20696e73756666696369656e7420636c61696d61626c652062616c616e6365506f6f6c3a20696e73756666696369656e74207068616e746f6d2062616c616e6365506f6f6c3a20696e73756666696369656e74207374616765642062616c616e6365506f6f6c3a20696e73756666696369656e7420626f6e6465642062616c616e6365a365627a7a72315820a57091e0a9246dad90f53c19903dfdbe68f41564fede51ec067b672018ed35856c6578706572696d656e74616cf564736f6c63430005110040000000000000000000000000be4fe13a73675c49a17f3524602634913c668b4c00000000000000000000000084997fafc913f1613f51bb0e2b5854222900514b

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80636637b882116101045780639940686e116100a2578063c0d7a94f11610071578063c0d7a94f14610398578063cf023779146103ab578063e0cf7285146103b3578063e8c3c54f146103bb576101cf565b80639940686e14610357578063a680e0bc1461036a578063aed29d071461037d578063b6b55f2514610385576101cf565b806386cf9f14116100de57806386cf9f14146102fe5780638901bf7b1461031157806395ccea671461032457806397a5d5b514610337576101cf565b80636637b882146102c35780636dca5abe146102d6578063825ad607146102eb576101cf565b806344d96e951161017157806351adeb571161014b57806351adeb571461028b57806351bf21d8146102935780635c975abb146102a65780635fcbd285146102bb576101cf565b806344d96e95146102735780634838ed191461027b57806351858e2714610283576101cf565b80632ad48299116101ad5780632ad48299146102255780632e1a7d4d14610238578063379607f51461024b5780634162169f1461025e576101cf565b80631667eb17146101d457806327de9e32146101fd57806329f32ed414610212575b600080fd5b6101e76101e2366004611ad7565b6103ce565b6040516101f49190611f2a565b60405180910390f35b61021061020b366004611b73565b61043f565b005b6101e7610220366004611ad7565b610596565b6101e7610233366004611ad7565b6105b4565b610210610246366004611b73565b6105d2565b610210610259366004611b73565b610701565b610266610832565b6040516101f49190611ecd565b6101e7610841565b6101e7610847565b61021061084d565b61026661088e565b6101e76102a1366004611ad7565b61089d565b6102ae6108bb565b6040516101f49190611ebf565b6102666108c4565b6102106102d1366004611b55565b6108d3565b6102de610900565b6040516101f49190611e0f565b6101e76102f9366004611ad7565b61090f565b6101e761030c366004611ad7565b61092d565b6101e761031f366004611ad7565b610948565b610210610332366004611afd565b61095e565b61034a610345366004611ad7565b6109f5565b6040516101f49190611edb565b610210610365366004611b73565b610a2e565b6101e7610378366004611ad7565b610b4c565b6101e7610b6a565b610210610393366004611b73565b610c06565b6101e76103a6366004611ad7565b610cf1565b6101e7610d79565b6101e7610d7f565b6102106103c9366004611baf565b610d85565b60006103d982610948565b42106103ef576103e8826105b4565b905061043a565b6104376103fa610efc565b61042b61041661040986610b4c565b429063ffffffff610f0316565b61041f866105b4565b9063ffffffff610f4e16565b9063ffffffff610f8816565b90505b919050565b61044833610fca565b60006104533361090f565b905061048a6000821163141bdbdb60e21b7f696e73756666696369656e7420626f6e6465642062616c616e63650000000000610ffc565b6000610495336103ce565b905080156104a6576104a681610701565b60006104b98361042b8661041f33610cf1565b905060006104ce8461042b8761041f33610596565b90506104da3386611051565b6104e433836110ae565b61050733866040518060600160405280602181526020016120ba60219139611113565b61052a338260405180606001604052806022815260200161207760229139611178565b610533336111dd565b61053b6111fd565b337f93530ac0ee8c50e696e13c5ac62355d0c0ba4bd943620d5bda1eb08b64ae7512610576600161056a6112c6565b9063ffffffff61134016565b878560405161058793929190611f46565b60405180910390a25050505050565b6001600160a01b031660009081526008602052604090206004015490565b6001600160a01b031660009081526008602052604090206001015490565b3361060960005b6105e2836109f5565b60028111156105ed57fe5b1463141bdbdb60e21b692737ba10333937bd32b760b11b610ffc565b6106116108c4565b6001600160a01b031663a9059cbb33846040518363ffffffff1660e01b815260040161063e929190611e45565b602060405180830381600087803b15801561065857600080fd5b505af115801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106909190810190611b37565b506106b4338360405180606001604052806021815260200161209960219139611365565b6106bc6111fd565b336001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364836040516106f59190611f2a565b60405180910390a25050565b8061070b336103ce565b10156107325760405162461bcd60e51b815260040161072990611efa565b60405180910390fd5b61073a61088e565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401610767929190611e45565b602060405180830381600087803b15801561078157600080fd5b505af1158015610795573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107b99190810190611b37565b506107dd3382604051806060016040528060248152602001612053602491396113c5565b6107e6336111dd565b6107ee6111fd565b336001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4826040516108279190611f2a565b60405180910390a250565b6004546001600160a01b031690565b60025490565b60015490565b610884610858610832565b6001600160a01b0316336001600160a01b03161463141bdbdb60e21b664e6f742064616f60c81b610ffc565b61088c61142d565b565b6005546001600160a01b031690565b6001600160a01b031660009081526008602052604090206005015490565b60075460ff1690565b6006546001600160a01b031690565b6108de610858610832565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600061090a61143c565b905090565b6001600160a01b031660009081526008602052604090206003015490565b6001600160a01b031660009081526008602052604090205490565b6000610437610955610efc565b61056a84610b4c565b610969610858610832565b816001600160a01b031663a9059cbb610980610832565b836040518363ffffffff1660e01b815260040161099e929190611e96565b602060405180830381600087803b1580156109b857600080fd5b505af11580156109cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109f09190810190611b37565b505050565b6001600160a01b038116600090815260086020526040812060050154610a196112c6565b1015610a26576001610437565b506000919050565b610a51610a396108bb565b1563141bdbdb60e21b6514185d5cd95960d21b610ffc565b610a5a33610fca565b6000610a6f610a67610d7f565b61056a610b6a565b90506000610a7b610841565b15610aa057610a9b610a8b610841565b61042b848663ffffffff610f4e16565b610ac0565b610aa8610b6a565b15610ab4576000610ac0565b610ac08361041f611454565b9050610acc338461145b565b610ad633826114bd565b610af9338460405180606001604052806021815260200161209960219139611365565b610b016111fd565b337f3ae9ad26d7d47616d306d7757b947fe7b0f9a7c61a5f0dc784b0ddb6c7c40b5a610b30600161056a6112c6565b85604051610b3f929190611f38565b60405180910390a2505050565b6001600160a01b031660009081526008602052604090206002015490565b600061090a610b77610847565b610b7f61088e565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610baa9190611e0f565b60206040518083038186803b158015610bc257600080fd5b505afa158015610bd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610bfa9190810190611b91565b9063ffffffff610f0316565b33610c1160006105d9565b610c1c610a396108bb565b610c246108c4565b6001600160a01b03166323b872dd3330856040518463ffffffff1660e01b8152600401610c5393929190611e1d565b602060405180830381600087803b158015610c6d57600080fd5b505af1158015610c81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ca59190810190611b37565b50610cb03383611051565b610cb86111fd565b336001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c836040516106f59190611f2a565b600080610cfc610841565b905080610d0d57600091505061043a565b6000610d1a610a67610d7f565b90506000610d3b8361042b610d2e8861090f565b859063ffffffff610f4e16565b90506000610d4886610596565b905080821115610d6d57610d62828263ffffffff610f0316565b94505050505061043a565b50600095945050505050565b60005490565b60035490565b33610d9060006105d9565b610d9b610a396108bb565b610dd76000610da8610841565b1163141bdbdb60e21b7f696e73756666696369656e7420746f74616c20626f6e64656400000000000000610ffc565b610e136000610de4610b6a565b1163141bdbdb60e21b7f696e73756666696369656e7420746f74616c2072657761726465640000000000610ffc565b610e5083610e2033610cf1565b101563141bdbdb60e21b7f696e73756666696369656e742072657761726465642062616c616e6365000000610ffc565b600080610e5d858561151f565b915091506000610e728661056a610a67610d7f565b90506000610e81610a8b610841565b9050610e8d338461145b565b610ea633610ea1898463ffffffff61134016565b6114bd565b610eae6111fd565b336001600160a01b03167fbe9d8078818a53534ce225882a00e0c6f709b5296c8a08c3a1f23f9ffd448380888686604051610eeb93929190611f46565b60405180910390a250505050505050565b6203f48090565b6000610f4583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506119b3565b90505b92915050565b600082610f5d57506000610f48565b82820282848281610f6a57fe5b0414610f455760405162461bcd60e51b815260040161072990611f1a565b6000610f4583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506119e4565b610fdd610fd5611a1b565b61056a6112c6565b6001600160a01b03909116600090815260086020526040902060050155565b826109f05761100a82611a20565b6101d160f51b61101983611a20565b60405160200161102b93929190611dde565b60408051601f198184030181529082905262461bcd60e51b825261072991600401611ee9565b6001600160a01b03821660009081526008602052604090205461107a908263ffffffff61134016565b6001600160a01b038316600090815260086020526040812091909155546110a7908263ffffffff61134016565b6000555050565b6001600160a01b0382166000908152600860205260409020600101546110da908263ffffffff61134016565b6001600160a01b03831660009081526008602052604090206001908101919091555461110c908263ffffffff61134016565b6001555050565b6001600160a01b03831660009081526008602052604090206003015461114090838363ffffffff6119b316565b6001600160a01b03841660009081526008602052604090206003015560025461117090838363ffffffff6119b316565b600255505050565b6001600160a01b0383166000908152600860205260409020600401546111a590838363ffffffff6119b316565b6001600160a01b0384166000908152600860205260409020600401556003546111d590838363ffffffff6119b316565b600355505050565b6001600160a01b0316600090815260086020526040902042600290910155565b61088c61121361120b610841565b61056a610d79565b61121b6108c4565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016112469190611e0f565b60206040518083038186803b15801561125e57600080fd5b505afa158015611272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112969190810190611b91565b101563141bdbdb60e21b7f496e636f6e73697374656e7420554e492d56322062616c616e63657300000000610ffc565b60006112d0610832565b6001600160a01b031663900cf0cf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561130857600080fd5b505afa15801561131c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061090a9190810190611b91565b600082820183811015610f455760405162461bcd60e51b815260040161072990611f0a565b6001600160a01b03831660009081526008602052604090205461138f90838363ffffffff6119b316565b6001600160a01b038416600090815260086020526040812091909155546113bd90838363ffffffff6119b316565b600055505050565b6001600160a01b0383166000908152600860205260409020600101546113f290838363ffffffff6119b316565b6001600160a01b03841660009081526008602052604090206001908101919091555461142590838363ffffffff6119b316565b600155505050565b6007805460ff19166001179055565b736c3f90f043a72fa612cbac8115ee7e52bde6e49090565b620f424090565b6001600160a01b038216600090815260086020526040902060030154611487908263ffffffff61134016565b6001600160a01b0383166000908152600860205260409020600301556002546114b6908263ffffffff61134016565b6002555050565b6001600160a01b0382166000908152600860205260409020600401546114e9908263ffffffff61134016565b6001600160a01b038316600090815260086020526040902060040155600354611518908263ffffffff61134016565b6003555050565b600080600061152c610900565b905060006115386108c4565b905060006115446108c4565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161156f9190611e0f565b60206040518083038186803b15801561158757600080fd5b505afa15801561159b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115bf9190810190611b91565b6040516323b872dd60e01b81529091506001600160a01b038416906323b872dd906115f290339030908c90600401611e1d565b602060405180830381600087803b15801561160c57600080fd5b505af1158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116449190810190611b37565b50604051636eb1769f60e11b815287906001600160a01b0385169063dd62ed3e906116759030908790600401611e60565b60206040518083038186803b15801561168d57600080fd5b505afa1580156116a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116c59190810190611b91565b1015611756576116d361088e565b6001600160a01b031663095ea7b3836000196040518363ffffffff1660e01b8152600401611702929190611e7b565b602060405180830381600087803b15801561171c57600080fd5b505af1158015611730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117549190810190611b37565b505b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e906117879030908790600401611e60565b60206040518083038186803b15801561179f57600080fd5b505afa1580156117b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117d79190810190611b91565b90506000811180156117e857508781105b156118705760405163095ea7b360e01b81526001600160a01b0385169063095ea7b39061181c908690600090600401611e7b565b602060405180830381600087803b15801561183657600080fd5b505af115801561184a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061186e9190810190611b37565b505b80158061187c57508781105b156119055760405163095ea7b360e01b81526001600160a01b0385169063095ea7b3906118b190869060001990600401611e7b565b602060405180830381600087803b1580156118cb57600080fd5b505af11580156118df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506119039190810190611b37565b505b604080518082018252898152602081018a90529051630b4c7e4d60e01b81526001600160a01b03851691630b4c7e4d9161194491908b90600401611ea4565b602060405180830381600087803b15801561195e57600080fd5b505af1158015611972573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506119969190810190611b91565b50876119a483610b7f6108c4565b95509550505050509250929050565b600081848411156119d75760405162461bcd60e51b81526004016107299190611ee9565b50508183035b9392505050565b60008183611a055760405162461bcd60e51b81526004016107299190611ee9565b506000838581611a1157fe5b0495945050505050565b604890565b60608082604051602001611a349190611dc9565b60408051601f19818403018152919052905060205b8015611a8957815160001990910190829082908110611a6457fe5b01602001516001600160f81b03191615611a84576001018152905061043a565b611a49565b505060408051600081526020810190915292915050565b8035610f4881612023565b8051610f4881612037565b8035610f4881612040565b8035610f4881612049565b8051610f4881612049565b600060208284031215611ae957600080fd5b6000611af58484611aa0565b949350505050565b60008060408385031215611b1057600080fd5b6000611b1c8585611aa0565b9250506020611b2d85828601611ac1565b9150509250929050565b600060208284031215611b4957600080fd5b6000611af58484611aab565b600060208284031215611b6757600080fd5b6000611af58484611ab6565b600060208284031215611b8557600080fd5b6000611af58484611ac1565b600060208284031215611ba357600080fd5b6000611af58484611acc565b60008060408385031215611bc257600080fd5b6000611b1c8585611ac1565b6000611bda8383611dc0565b505060200190565b611beb81611fbb565b82525050565b611beb81611f7d565b611c0381611f64565b611c0d818461043a565b9250611c1882611f61565b8060005b83811015611c46578151611c308782611bce565b9650611c3b83611f6e565b925050600101611c1c565b505050505050565b611beb81611f88565b611beb611c6382611f8d565b611f61565b611beb611c6382611f61565b6000611c7f82611f6a565b611c89818561043a565b9350611c99818560208601611fdc565b9290920192915050565b611beb81611f9a565b611beb81611fc6565b611beb81611fd1565b6000611cc982611f6a565b611cd38185611f74565b9350611ce3818560208601611fdc565b611cec8161200c565b9093019392505050565b6000611d03602c83611f74565b7f506f6f6c3a20696e73756666696369656e742070656e64696e6720636c61696d81526b61626c652062616c616e636560a01b602082015260400192915050565b6000611d51601b83611f74565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000611d8a602183611f74565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b611beb81611f61565b6000611dd58284611c68565b50602001919050565b6000611dea8286611c74565b9150611df68285611c57565b600282019150611e068284611c74565b95945050505050565b60208101610f488284611bf1565b60608101611e2b8286611be2565b611e386020830185611bf1565b611af56040830184611dc0565b60408101611e538285611be2565b6119dd6020830184611dc0565b60408101611e6e8285611bf1565b6119dd6020830184611bf1565b60408101611e898285611bf1565b6119dd6020830184611cb5565b60408101611e538285611bf1565b60608101611eb28285611bfa565b6119dd6040830184611dc0565b60208101610f488284611c4e565b60208101610f488284611ca3565b60208101610f488284611cac565b60208082528101610f458184611cbe565b6020808252810161043781611cf6565b6020808252810161043781611d44565b6020808252810161043781611d7d565b60208101610f488284611dc0565b60408101611e538285611dc0565b60608101611f548286611dc0565b611e386020830185611dc0565b90565b50600290565b5190565b60200190565b90815260200190565b600061043782611faf565b151590565b6001600160f01b03191690565b600061043782611f7d565b8061043a81612016565b6001600160a01b031690565b600061043782611f9a565b600061043782611fa5565b600061043782611f61565b60005b83811015611ff7578181015183820152602001611fdf565b83811115612006576000848401525b50505050565b601f01601f191690565b6003811061202057fe5b50565b61202c81611f7d565b811461202057600080fd5b61202c81611f88565b61202c81611f9a565b61202c81611f6156fe506f6f6c3a20696e73756666696369656e7420636c61696d61626c652062616c616e6365506f6f6c3a20696e73756666696369656e74207068616e746f6d2062616c616e6365506f6f6c3a20696e73756666696369656e74207374616765642062616c616e6365506f6f6c3a20696e73756666696369656e7420626f6e6465642062616c616e6365a365627a7a72315820a57091e0a9246dad90f53c19903dfdbe68f41564fede51ec067b672018ed35856c6578706572696d656e74616cf564736f6c63430005110040

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

000000000000000000000000be4fe13a73675c49a17f3524602634913c668b4c00000000000000000000000084997fafc913f1613f51bb0e2b5854222900514b

-----Decoded View---------------
Arg [0] : dollar (address): 0xBE4fe13A73675c49A17f3524602634913C668B4C
Arg [1] : lpToken (address): 0x84997FAFC913f1613F51Bb0E2b5854222900514B

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000be4fe13a73675c49a17f3524602634913c668b4c
Arg [1] : 00000000000000000000000084997fafc913f1613f51bb0e2b5854222900514b


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.