ETH Price: $2,446.51 (+3.58%)

Contract

0x5717EEDCE2c23e061adD9F1D1C67C0d8F45eC75b
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Redeem173980882023-06-03 5:30:23468 days ago1685770223IN
0x5717EEDC...8F45eC75b
0 ETH0.0013529821.24262508
Redeem173866512023-06-01 14:47:59470 days ago1685630879IN
0x5717EEDC...8F45eC75b
0 ETH0.0017041834.07551407
Redeem173798812023-05-31 15:56:11471 days ago1685548571IN
0x5717EEDC...8F45eC75b
0 ETH0.0019626739.24400509
Redeem173725502023-05-30 15:12:35472 days ago1685459555IN
0x5717EEDC...8F45eC75b
0 ETH0.004056163.68315756
Redeem173681522023-05-30 0:18:23472 days ago1685405903IN
0x5717EEDC...8F45eC75b
0 ETH0.0011724123.44270111
Redeem173641992023-05-29 10:58:35473 days ago1685357915IN
0x5717EEDC...8F45eC75b
0 ETH0.0017928828.14928101
Redeem173637542023-05-29 9:27:59473 days ago1685352479IN
0x5717EEDC...8F45eC75b
0 ETH0.001444828.88917434
Redeem173635552023-05-29 8:47:47473 days ago1685350067IN
0x5717EEDC...8F45eC75b
0 ETH0.0013815727.62482363
Redeem173608692023-05-28 23:44:23473 days ago1685317463IN
0x5717EEDC...8F45eC75b
0 ETH0.0012996825.98754063
Redeem173608512023-05-28 23:40:47473 days ago1685317247IN
0x5717EEDC...8F45eC75b
0 ETH0.0013911927.81713467
Redeem173599162023-05-28 20:32:35474 days ago1685305955IN
0x5717EEDC...8F45eC75b
0 ETH0.0017610527.64961924
Redeem173597302023-05-28 19:54:59474 days ago1685303699IN
0x5717EEDC...8F45eC75b
0 ETH0.0016387732.77426109
Redeem173594462023-05-28 18:57:59474 days ago1685300279IN
0x5717EEDC...8F45eC75b
0 ETH0.0011669523.33343514
Redeem173582372023-05-28 14:54:23474 days ago1685285663IN
0x5717EEDC...8F45eC75b
0 ETH0.0017753435.49847219
Redeem173576512023-05-28 12:55:35474 days ago1685278535IN
0x5717EEDC...8F45eC75b
0 ETH0.0011804823.60394258
Redeem173570932023-05-28 11:02:47474 days ago1685271767IN
0x5717EEDC...8F45eC75b
0 ETH0.0019294730.29380466
Redeem173570912023-05-28 11:02:23474 days ago1685271743IN
0x5717EEDC...8F45eC75b
0 ETH0.001527130.54081749
Redeem173566432023-05-28 9:31:35474 days ago1685266295IN
0x5717EEDC...8F45eC75b
0 ETH0.001585824.89806042
Redeem173559702023-05-28 7:14:35474 days ago1685258075IN
0x5717EEDC...8F45eC75b
0 ETH0.0010941421.87772375
Redeem173549772023-05-28 3:54:35474 days ago1685246075IN
0x5717EEDC...8F45eC75b
0 ETH0.0021517333.78343042
Redeem173530422023-05-27 21:24:23475 days ago1685222663IN
0x5717EEDC...8F45eC75b
0 ETH0.0013416721.93287967
Redeem173513972023-05-27 15:51:11475 days ago1685202671IN
0x5717EEDC...8F45eC75b
0 ETH0.0015533825.39873026
Redeem173485692023-05-27 6:19:59475 days ago1685168399IN
0x5717EEDC...8F45eC75b
0 ETH0.0018218123.27543604
Redeem173483882023-05-27 5:43:23475 days ago1685166203IN
0x5717EEDC...8F45eC75b
0 ETH0.0014035922.94512201
Redeem173482072023-05-27 5:07:11475 days ago1685164031IN
0x5717EEDC...8F45eC75b
0 ETH0.0016136326.38374986
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:
BondERC20

Compiler Version
v0.7.5+commit.eb77ed08

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 8 : BondERC20.sol
import "./libraries/SafeMath.sol";
import "./libraries/FixedPoint.sol";
import "./libraries/Address.sol";
import "./libraries/SafeERC20.sol";
import "./interface/IHATETreasury.sol";

// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.7.5;

contract BondERC20 {
    using FixedPoint for *;
    using SafeERC20 for IERC20;
    using SafeMath for uint;

    modifier onlyOwner() {
        require(owner == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    /* ======== EVENTS ======== */

    event BondCreated(uint deposit, uint payout, uint expires);
    event BondRedeemed(address recipient, uint payout, uint remaining);
    event BondPriceChanged(uint internalPrice, uint debtRatio);
    event ControlVariableAdjustment(uint initialBCV, uint newBCV, uint adjustment, bool addition);

    /* ======== STATE VARIABLES ======== */

    address public owner;

    IERC20 private immutable HATE; // token paid for principal
    IERC20 private immutable principalToken; // inflow token
    IHATETreasury private immutable treasury; // pays for and receives principal

    address public feeTo;
    // in thousandths of a %. i.e. 500 = 0.5%
    uint public feePercent;

    uint public totalPrincipalBonded;
    uint public totalPayoutGiven;
    uint public totalDebt; // total value of outstanding bonds; used for pricing
    uint public lastDecay; // reference timestamp for debt decay

    Terms public terms; // stores terms for new bonds
    Adjust public adjustment; // stores adjustment to BCV data

    mapping(address => Bond) public bondInfo; // stores bond information for depositors

    /* ======== STRUCTS ======== */

    // Info for creating new bonds
    struct Terms {
        uint controlVariable; // scaling variable for price
        uint vestingTerm; // in seconds
        uint minimumPrice; // vs principal value
        uint maxPayout; // in thousandths of a %. i.e. 500 = 0.5%
        uint maxDebt; // payout token decimal debt ratio, max % total supply created as debt
    }

    // Info for bond holder
    struct Bond {
        uint payout; // payout token remaining to be paid
        uint vesting; // seconds left to vest
        uint lastBlockTimestamp; // Last interaction
        uint truePricePaid; // Price paid (principal tokens per payout token) in ten-millionths - 4000000 = 0.4
    }

    // Info for incremental adjustments to control variable
    struct Adjust {
        bool add; // addition or subtraction
        uint rate; // increment
        uint target; // BCV when adjustment finished
        uint buffer; // minimum length (in seconds) between adjustments
        uint lastBlockTimestamp; // timestamp when last adjustment made
    }

    /* ======== CONSTRUCTOR ======== */

    constructor(address _treasury, address _principalToken) {
        require(_treasury != address(0));
        treasury = IHATETreasury(_treasury);
        HATE = IERC20(IHATETreasury(_treasury).HATE());
        require(_principalToken != address(0));
        principalToken = IERC20(_principalToken);
        owner = msg.sender;
    }

    /* ======== INITIALIZATION ======== */

    /**
     *  @notice initializes bond parameters
     *  @param _controlVariable uint
     *  @param _vestingTerm uint
     *  @param _minimumPrice uint
     *  @param _maxPayout uint
     *  @param _maxDebt uint
     *  @param _initialDebt uint
     */
    function initializeBond(
        uint _controlVariable,
        uint _vestingTerm,
        uint _minimumPrice,
        uint _maxPayout,
        uint _maxDebt,
        uint _initialDebt
    ) external onlyOwner {
        require(currentDebt() == 0, "Debt must be 0 for initialization");
        terms = Terms({
            controlVariable: _controlVariable,
            vestingTerm: _vestingTerm,
            minimumPrice: _minimumPrice,
            maxPayout: _maxPayout,
            maxDebt: _maxDebt
        });
        totalDebt = _initialDebt;
        lastDecay = block.timestamp;
    }

    /* ======== POLICY FUNCTIONS ======== */

    function setFeeAndFeeTo(address feeTo_, uint256 feePercent_) external onlyOwner {
        feeTo = feeTo_;
        feePercent = feePercent_;
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        owner = newOwner;
    }

    enum PARAMETER {
        VESTING,
        PAYOUT,
        DEBT
    }

    /**
     *  @notice set parameters for new bonds
     *  @param _parameter PARAMETER
     *  @param _input uint
     */
    function setBondTerms(PARAMETER _parameter, uint _input) external onlyOwner {
        if (_parameter == PARAMETER.VESTING) {
            // 0
            require(_input >= 129600, "Vesting must be longer than 36 hours");
            terms.vestingTerm = _input;
        } else if (_parameter == PARAMETER.PAYOUT) {
            // 1
            terms.maxPayout = _input;
        } else if (_parameter == PARAMETER.DEBT) {
            // 2
            terms.maxDebt = _input;
        }
    }

    /**
     *  @notice set control variable adjustment
     *  @param _addition bool
     *  @param _increment uint
     *  @param _target uint
     *  @param _buffer uint
     */
    function setAdjustment(bool _addition, uint _increment, uint _target, uint _buffer) external onlyOwner {
        require(_increment <= terms.controlVariable.mul(30).div(1000), "Increment too large");

        adjustment = Adjust({
            add: _addition,
            rate: _increment,
            target: _target,
            buffer: _buffer,
            lastBlockTimestamp: block.timestamp
        });
    }

    /* ======== USER FUNCTIONS ======== */

    /**
     *  @notice deposit bond
     *  @param _amount uint
     *  @param _maxPrice uint
     *  @param _depositor address
     *  @return uint
     */
    function deposit(uint _amount, uint _maxPrice, address _depositor) external returns (uint) {
        require(_depositor != address(0), "Invalid address");

        decayDebt();

        uint nativePrice = bondPrice();

        require(_maxPrice >= nativePrice, "Slippage limit: more than max price"); // slippage protection

        uint value = treasury.valueOfToken(address(principalToken), _amount);

        uint payout = payoutFor(value);

        require(payout >= 10 ** HATE.decimals() / 100, "Bond too small"); // must be > 0.01 payout token ( underflow protection )
        require(payout <= maxPayout(), "Bond too large"); // size protection because there is no slippage

        // total debt is increased
        totalDebt = totalDebt.add(value);

        require(totalDebt <= terms.maxDebt, "Max capacity reached");

        // depositor info is stored
        bondInfo[_depositor] = Bond({
            payout: bondInfo[_depositor].payout.add(payout),
            vesting: terms.vestingTerm,
            lastBlockTimestamp: block.timestamp,
            truePricePaid: bondPrice()
        });

        totalPrincipalBonded = totalPrincipalBonded.add(_amount); // total bonded increased
        totalPayoutGiven = totalPayoutGiven.add(payout); // total payout increased

        treasury.mintHATE(address(this), payout);

        if (feeTo != address(0) && feePercent > 0) {
            uint256 _fee = payout.mul(feePercent).div(100000);
            treasury.mintHATE(feeTo, _fee);
        }

        principalToken.safeTransferFrom(msg.sender, address(treasury), _amount); // transfer principal bonded to custom treasury

        // indexed events are emitted
        emit BondCreated(_amount, payout, block.timestamp.add(terms.vestingTerm));
        emit BondPriceChanged(_bondPrice(), debtRatio());

        adjust(); // control variable is adjusted
        return payout;
    }

    /**
     *  @notice redeem bond for user
     *  @param _depositor address
     *  @return uint
     */
    function redeem(address _depositor) external returns (uint) {
        Bond memory info = bondInfo[_depositor];
        uint percentVested = percentVestedFor(_depositor); // (seconds since last interaction / vesting term remaining)

        if (percentVested >= 10000) {
            // if fully vested
            delete bondInfo[_depositor]; // delete user info
            emit BondRedeemed(_depositor, info.payout, 0); // emit bond data
            HATE.safeTransfer(_depositor, info.payout);
            return info.payout;
        } else {
            // if unfinished
            // calculate payout vested
            uint payout = info.payout.mul(percentVested).div(10000);

            // store updated deposit info
            bondInfo[_depositor] = Bond({
                payout: info.payout.sub(payout),
                vesting: info.vesting.sub(block.timestamp.sub(info.lastBlockTimestamp)),
                lastBlockTimestamp: block.timestamp,
                truePricePaid: info.truePricePaid
            });

            emit BondRedeemed(_depositor, payout, bondInfo[_depositor].payout);
            HATE.safeTransfer(_depositor, payout);
            return payout;
        }
    }

    /* ======== INTERNAL HELPER FUNCTIONS ======== */

    /**
     *  @notice makes incremental adjustment to control variable
     */
    function adjust() internal {
        uint timestampCanAdjust = adjustment.lastBlockTimestamp.add(adjustment.buffer);
        if (adjustment.rate != 0 && block.timestamp >= timestampCanAdjust) {
            uint initial = terms.controlVariable;
            if (adjustment.add) {
                terms.controlVariable = terms.controlVariable.add(adjustment.rate);
                if (terms.controlVariable >= adjustment.target) {
                    adjustment.rate = 0;
                }
            } else {
                terms.controlVariable = terms.controlVariable.sub(adjustment.rate);
                if (terms.controlVariable <= adjustment.target) {
                    adjustment.rate = 0;
                }
            }
            adjustment.lastBlockTimestamp = block.timestamp;
            emit ControlVariableAdjustment(initial, terms.controlVariable, adjustment.rate, adjustment.add);
        }
    }

    /**
     *  @notice reduce total debt
     */
    function decayDebt() internal {
        totalDebt = totalDebt.sub(debtDecay());
        lastDecay = block.timestamp;
    }

    /**
     *  @notice calculate current bond price and remove floor if above
     *  @return price_ uint
     */
    function _bondPrice() internal returns (uint price_) {
        price_ = terms.controlVariable.mul(debtRatio()).div(10 ** (uint256(HATE.decimals()).sub(5)));
        if (price_ < terms.minimumPrice) {
            price_ = terms.minimumPrice;
        } else if (terms.minimumPrice != 0) {
            terms.minimumPrice = 0;
        }
    }

    /* ======== VIEW FUNCTIONS ======== */

    /**
     *  @notice calculate current bond premium
     *  @return price_ uint
     */
    function bondPrice() public view returns (uint price_) {
        price_ = terms.controlVariable.mul(debtRatio()).div(10 ** (uint256(HATE.decimals()).sub(5)));
        if (price_ < terms.minimumPrice) {
            price_ = terms.minimumPrice;
        }
    }

    /**
     *  @notice determine maximum bond size
     *  @return uint
     */
    function maxPayout() public view returns (uint) {
        return HATE.totalSupply().mul(terms.maxPayout).div(100000);
    }

    /*
     *  @param _value uint
     *  @return _payout uint
     */
    function payoutFor(uint _value) public view returns (uint _payout) {
        _payout = FixedPoint.fraction(_value, bondPrice()).decode112with18().div(1e9);
    }

    /**
     *  @notice calculate current ratio of debt to payout token supply
     *  @return debtRatio_ uint
     */
    function debtRatio() public view returns (uint debtRatio_) {
        debtRatio_ = FixedPoint
            .fraction(currentDebt().mul(10 ** HATE.decimals()), HATE.totalSupply())
            .decode112with18()
            .div(1e18);
    }

    /**
     *  @notice calculate debt factoring in decay
     *  @return uint
     */
    function currentDebt() public view returns (uint) {
        return totalDebt.sub(debtDecay());
    }

    /**
     *  @notice amount to decay total debt by
     *  @return decay_ uint
     */
    function debtDecay() public view returns (uint decay_) {
        uint timestampSinceLast = block.timestamp.sub(lastDecay);
        decay_ = totalDebt.mul(timestampSinceLast).div(terms.vestingTerm);
        if (decay_ > totalDebt) {
            decay_ = totalDebt;
        }
    }

    /**
     *  @notice calculate how far into vesting a depositor is
     *  @param _depositor address
     *  @return percentVested_ uint
     */
    function percentVestedFor(address _depositor) public view returns (uint percentVested_) {
        Bond memory bond = bondInfo[_depositor];
        uint timestampSinceLast = block.timestamp.sub(bond.lastBlockTimestamp);
        uint vesting = bond.vesting;

        if (vesting > 0) {
            percentVested_ = timestampSinceLast.mul(10000).div(vesting);
        } else {
            percentVested_ = 0;
        }
    }

    /**
     *  @notice calculate amount of payout token available for claim by depositor
     *  @param _depositor address
     *  @return pendingPayout_ uint
     */
    function pendingPayoutFor(address _depositor) external view returns (uint pendingPayout_) {
        uint percentVested = percentVestedFor(_depositor);
        uint payout = bondInfo[_depositor].payout;

        if (percentVested >= 10000) {
            pendingPayout_ = payout;
        } else {
            pendingPayout_ = payout.mul(percentVested).div(10000);
        }
    }
}

File 2 of 8 : IERC20.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.7.5;

interface IERC20 {

  function decimals() external view returns (uint8);
  
  /**
   * @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 3 of 8 : IHATETreasury.sol
pragma solidity >=0.7.5;

interface IHATETreasury {
    function mintHATE(address to_, uint256 amount_) external;
    function valueOfToken(address _principalToken, uint _amount) external view returns (uint value_);
    function HATE() external view returns (address);
}

File 4 of 8 : Address.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.7.5;


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

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

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

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

    function addressToString(address _address) internal pure returns(string memory) {
        bytes32 _bytes = bytes32(uint256(_address));
        bytes memory HEX = "0123456789abcdef";
        bytes memory _addr = new bytes(42);

        _addr[0] = '0';
        _addr[1] = 'x';

        for(uint256 i = 0; i < 20; i++) {
            _addr[2+i*2] = HEX[uint8(_bytes[i + 12] >> 4)];
            _addr[3+i*2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
        }

        return string(_addr);

    }
}

File 5 of 8 : FixedPoint.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.7.5;

import "./FullMath.sol";


library Babylonian {

    function sqrt(uint256 x) internal pure returns (uint256) {
        if (x == 0) return 0;

        uint256 xx = x;
        uint256 r = 1;
        if (xx >= 0x100000000000000000000000000000000) {
            xx >>= 128;
            r <<= 64;
        }
        if (xx >= 0x10000000000000000) {
            xx >>= 64;
            r <<= 32;
        }
        if (xx >= 0x100000000) {
            xx >>= 32;
            r <<= 16;
        }
        if (xx >= 0x10000) {
            xx >>= 16;
            r <<= 8;
        }
        if (xx >= 0x100) {
            xx >>= 8;
            r <<= 4;
        }
        if (xx >= 0x10) {
            xx >>= 4;
            r <<= 2;
        }
        if (xx >= 0x8) {
            r <<= 1;
        }
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1; // Seven iterations should be enough
        uint256 r1 = x / r;
        return (r < r1 ? r : r1);
    }
}

library BitMath {

    function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
        require(x > 0, 'BitMath::mostSignificantBit: zero');

        if (x >= 0x100000000000000000000000000000000) {
            x >>= 128;
            r += 128;
        }
        if (x >= 0x10000000000000000) {
            x >>= 64;
            r += 64;
        }
        if (x >= 0x100000000) {
            x >>= 32;
            r += 32;
        }
        if (x >= 0x10000) {
            x >>= 16;
            r += 16;
        }
        if (x >= 0x100) {
            x >>= 8;
            r += 8;
        }
        if (x >= 0x10) {
            x >>= 4;
            r += 4;
        }
        if (x >= 0x4) {
            x >>= 2;
            r += 2;
        }
        if (x >= 0x2) r += 1;
    }
}


library FixedPoint {

    struct uq112x112 {
        uint224 _x;
    }

    struct uq144x112 {
        uint256 _x;
    }

    uint8 private constant RESOLUTION = 112;
    uint256 private constant Q112 = 0x10000000000000000000000000000;
    uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000;
    uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits)

    function decode(uq112x112 memory self) internal pure returns (uint112) {
        return uint112(self._x >> RESOLUTION);
    }

    function decode112with18(uq112x112 memory self) internal pure returns (uint) {

        return uint(self._x) / 5192296858534827;
    }

    function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) {
        require(denominator > 0, 'FixedPoint::fraction: division by zero');
        if (numerator == 0) return FixedPoint.uq112x112(0);

        if (numerator <= uint144(-1)) {
            uint256 result = (numerator << RESOLUTION) / denominator;
            require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
            return uq112x112(uint224(result));
        } else {
            uint256 result = FullMath.mulDiv(numerator, Q112, denominator);
            require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
            return uq112x112(uint224(result));
        }
    }
    
    // square root of a UQ112x112
    // lossy between 0/1 and 40 bits
    function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) {
        if (self._x <= uint144(-1)) {
            return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112)));
        }

        uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x);
        safeShiftBits -= safeShiftBits % 2;
        return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2)));
    }
}

File 6 of 8 : FullMath.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.7.5;

library FullMath {
    function fullMul(uint256 x, uint256 y) private pure returns (uint256 l, uint256 h) {
        uint256 mm = mulmod(x, y, uint256(-1));
        l = x * y;
        h = mm - l;
        if (mm < l) h -= 1;
    }

    function fullDiv(
        uint256 l,
        uint256 h,
        uint256 d
    ) private pure returns (uint256) {
        uint256 pow2 = d & -d;
        d /= pow2;
        l /= pow2;
        l += h * ((-pow2) / pow2 + 1);
        uint256 r = 1;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        return l * r;
    }

    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 d
    ) internal pure returns (uint256) {
        (uint256 l, uint256 h) = fullMul(x, y);

        uint256 mm = mulmod(x, y, d);
        if (mm > l) h -= 1;
        l -= mm;

        if (h == 0) return l / d;

        require(h < d, 'FullMath: FULLDIV_OVERFLOW');
        return fullDiv(l, h, d);
    }
}

File 7 of 8 : SafeERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.7.5;

import {IERC20} from "../interface/IERC20.sol";

/// @notice Safe IERC20 and ETH transfer library that safely handles missing return values.
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/libraries/TransferHelper.sol)
/// Taken from Solmate
library SafeERC20 {
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        (bool success, bytes memory data) = address(token).call(
            abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, amount)
        );

        require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        (bool success, bytes memory data) = address(token).call(
            abi.encodeWithSelector(IERC20.transfer.selector, to, amount)
        );

        require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FAILED");
    }

    function safeApprove(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        (bool success, bytes memory data) = address(token).call(
            abi.encodeWithSelector(IERC20.approve.selector, to, amount)
        );

        require(success && (data.length == 0 || abi.decode(data, (bool))), "APPROVE_FAILED");
    }

    function safeTransferETH(address to, uint256 amount) internal {
        (bool success, ) = to.call{value: amount}(new bytes(0));

        require(success, "ETH_TRANSFER_FAILED");
    }
}

File 8 of 8 : SafeMath.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.7.5;


// TODO(zx): Replace all instances of SafeMath with OZ implementation
library SafeMath {

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

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

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        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;
    }

    // Only used in the  BondingCalculator.sol
    function sqrrt(uint256 a) internal pure returns (uint c) {
        if (a > 3) {
            c = a;
            uint b = add( div( a, 2), 1 );
            while (b < c) {
                c = b;
                b = div( add( div( a, b ), b), 2 );
            }
        } else if (a != 0) {
            c = 1;
        }
    }

}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_principalToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"deposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"BondCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"internalPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtRatio","type":"uint256"}],"name":"BondPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remaining","type":"uint256"}],"name":"BondRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"initialBCV","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBCV","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adjustment","type":"uint256"},{"indexed":false,"internalType":"bool","name":"addition","type":"bool"}],"name":"ControlVariableAdjustment","type":"event"},{"inputs":[],"name":"adjustment","outputs":[{"internalType":"bool","name":"add","type":"bool"},{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"target","type":"uint256"},{"internalType":"uint256","name":"buffer","type":"uint256"},{"internalType":"uint256","name":"lastBlockTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bondInfo","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"},{"internalType":"uint256","name":"vesting","type":"uint256"},{"internalType":"uint256","name":"lastBlockTimestamp","type":"uint256"},{"internalType":"uint256","name":"truePricePaid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondPrice","outputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtDecay","outputs":[{"internalType":"uint256","name":"decay_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtRatio","outputs":[{"internalType":"uint256","name":"debtRatio_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxPrice","type":"uint256"},{"internalType":"address","name":"_depositor","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_controlVariable","type":"uint256"},{"internalType":"uint256","name":"_vestingTerm","type":"uint256"},{"internalType":"uint256","name":"_minimumPrice","type":"uint256"},{"internalType":"uint256","name":"_maxPayout","type":"uint256"},{"internalType":"uint256","name":"_maxDebt","type":"uint256"},{"internalType":"uint256","name":"_initialDebt","type":"uint256"}],"name":"initializeBond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"payoutFor","outputs":[{"internalType":"uint256","name":"_payout","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"pendingPayoutFor","outputs":[{"internalType":"uint256","name":"pendingPayout_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"percentVestedFor","outputs":[{"internalType":"uint256","name":"percentVested_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_addition","type":"bool"},{"internalType":"uint256","name":"_increment","type":"uint256"},{"internalType":"uint256","name":"_target","type":"uint256"},{"internalType":"uint256","name":"_buffer","type":"uint256"}],"name":"setAdjustment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum BondERC20.PARAMETER","name":"_parameter","type":"uint8"},{"internalType":"uint256","name":"_input","type":"uint256"}],"name":"setBondTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeTo_","type":"address"},{"internalType":"uint256","name":"feePercent_","type":"uint256"}],"name":"setFeeAndFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"terms","outputs":[{"internalType":"uint256","name":"controlVariable","type":"uint256"},{"internalType":"uint256","name":"vestingTerm","type":"uint256"},{"internalType":"uint256","name":"minimumPrice","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"maxDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPayoutGiven","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPrincipalBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e06040523480156200001157600080fd5b50604051620034b2380380620034b2833981810160405260408110156200003757600080fd5b810190808051906020019092919080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200008d57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b815250508173ffffffffffffffffffffffffffffffffffffffff16630d48c5d66040518163ffffffff1660e01b815260040160206040518083038186803b1580156200010b57600080fd5b505afa15801562000120573d6000803e3d6000fd5b505050506040513d60208110156200013757600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001b957600080fd5b8073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505060805160601c60a05160601c60c05160601c6132136200029f60003980610e21528061127652806113b35280611484525080610e5d52806114a6525080610f1c528061170e52806119065280611c415280611cfe5280611dea5280611ef952806128c252506132136000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80638dbdbe6d116100de578063d502562511610097578063e392a26211610071578063e392a26214610682578063f2fde38b146106a0578063f5c2ab5b146106e4578063fc7b9c181461070257610173565b8063d50256251461060c578063d7ccfb0b14610646578063e0176de81461066457610173565b80638dbdbe6d1461040f57806395a2251f1461047b5780639c006085146104d3578063a50603b214610521578063cd1234b314610581578063cea55f57146105ee57610173565b8063507930ec11610130578063507930ec146102e7578063759076e51461033f5780637927ebf81461035d5780637cbe044c1461039f5780637fd6f15c146103bd5780638da5cb5b146103db57610173565b8063017e7e581461017857806301b88ee8146101ac5780631a3d0068146102045780631e321a0f146102525780632bab6bde1461028d578063451ee4a1146102ab575b600080fd5b610180610720565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ee600480360360208110156101c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610746565b6040518082815260200191505060405180910390f35b6102506004803603608081101561021a57600080fd5b810190808035151590602001909291908035906020019092919080359060200190929190803590602001909291905050506107dd565b005b61028b6004803603604081101561026857600080fd5b81019080803560ff169060200190929190803590602001909291905050506109bc565b005b610295610b64565b6040518082815260200191505060405180910390f35b6102b3610b6a565b6040518086151581526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b610329600480360360208110156102fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b9b565b6040518082815260200191505060405180910390f35b610347610c81565b6040518082815260200191505060405180910390f35b6103896004803603602081101561037357600080fd5b8101908080359060200190929190505050610ca4565b6040518082815260200191505060405180910390f35b6103a7610cdc565b6040518082815260200191505060405180910390f35b6103c5610ce2565b6040518082815260200191505060405180910390f35b6103e3610ce8565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104656004803603606081101561042557600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d0c565b6040518082815260200191505060405180910390f35b6104bd6004803603602081101561049157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115ab565b6040518082815260200191505060405180910390f35b61051f600480360360408110156104e957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611956565b005b61057f600480360360c081101561053757600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050611a63565b005b6105c36004803603602081101561059757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bf8565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b6105f6611c28565b6040518082815260200191505060405180910390f35b610614611dba565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b61064e611dde565b6040518082815260200191505060405180910390f35b61066c611ee5565b6040518082815260200191505060405180910390f35b61068a611fb9565b6040518082815260200191505060405180910390f35b6106e2600480360360208110156106b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612015565b005b6106ec61219f565b6040518082815260200191505060405180910390f35b61070a6121a5565b6040518082815260200191505060405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008061075283610b9b565b90506000601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154905061271082106107ac578092506107d6565b6107d36127106107c584846121ab90919063ffffffff16565b61223190919063ffffffff16565b92505b5050919050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461089e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6108cb6103e86108bd601e6007600001546121ab90919063ffffffff16565b61223190919063ffffffff16565b831115610940576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e6372656d656e7420746f6f206c617267650000000000000000000000000081525060200191505060405180910390fd5b6040518060a00160405280851515815260200184815260200183815260200182815260200142815250600c60008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015590505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a7d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60006002811115610a8a57fe5b826002811115610a9657fe5b1415610b07576201fa40811015610af8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806131ba6024913960400191505060405180910390fd5b80600760010181905550610b60565b60016002811115610b1457fe5b826002811115610b2057fe5b1415610b355780600760030181905550610b5f565b600280811115610b4157fe5b826002811115610b4d57fe5b1415610b5e57806007600401819055505b5b5b5050565b60045481565b600c8060000160009054906101000a900460ff16908060010154908060020154908060030154908060040154905085565b6000610ba56130af565b601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090506000610c3282604001514261227b90919063ffffffff16565b90506000826020015190506000811115610c7457610c6d81610c5f612710856121ab90919063ffffffff16565b61223190919063ffffffff16565b9350610c79565b600093505b505050919050565b6000610c9f610c8e611fb9565b60055461227b90919063ffffffff16565b905090565b6000610cd5633b9aca00610cc7610cc285610cbd611dde565b6122c5565b6125a6565b61223190919063ffffffff16565b9050919050565b60035481565b60025481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f496e76616c69642061646472657373000000000000000000000000000000000081525060200191505060405180910390fd5b610db86125e2565b6000610dc2611dde565b905080841015610e1d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131976023913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d1b317e57f0000000000000000000000000000000000000000000000000000000000000000886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b158015610ece57600080fd5b505afa158015610ee2573d6000803e3d6000fd5b505050506040513d6020811015610ef857600080fd5b810190808051906020019092919050505090506000610f1682610ca4565b905060647f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610f8057600080fd5b505afa158015610f94573d6000803e3d6000fd5b505050506040513d6020811015610faa57600080fd5b810190808051906020019092919050505060ff16600a0a81610fc857fe5b0481101561103e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f20736d616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b611046611ee5565b8111156110bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f206c6172676500000000000000000000000000000000000081525060200191505060405180910390fd5b6110d08260055461260d90919063ffffffff16565b6005819055506007600401546005541115611153576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4d6178206361706163697479207265616368656400000000000000000000000081525060200191505060405180910390fd5b60405180608001604052806111b383601160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461260d90919063ffffffff16565b815260200160076001015481526020014281526020016111d1611dde565b815250601160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050506112538760035461260d90919063ffffffff16565b60038190555061126e8160045461260d90919063ffffffff16565b6004819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346552cc330836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561130557600080fd5b505af1158015611319573d6000803e3d6000fd5b50505050600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415801561137e57506000600254115b1561147e5760006113af620186a06113a1600254856121ab90919063ffffffff16565b61223190919063ffffffff16565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346552cc3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561146457600080fd5b505af1158015611478573d6000803e3d6000fd5b50505050505b6114eb337f0000000000000000000000000000000000000000000000000000000000000000897f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612695909392919063ffffffff16565b7fb7ce5a2d90f1705ca02547b0eb827724683e0df3b809477ae4326d0eefed0bc087826115266007600101544261260d90919063ffffffff16565b60405180848152602001838152602001828152602001935050505060405180910390a17f2cb17bd1fd2a1fecfefae2de1e6a59194abaa62179652924ccdca01617f0bf166115726128b6565b61157a611c28565b604051808381526020018281526020019250505060405180910390a161159e6129db565b8093505050509392505050565b60006115b56130af565b601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050600061163484610b9b565b9050612710811061176057601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000905550507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18483600001516000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a16117528483600001517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612b419092919063ffffffff16565b816000015192505050611951565b600061178d61271061177f8486600001516121ab90919063ffffffff16565b61223190919063ffffffff16565b905060405180608001604052806117b183866000015161227b90919063ffffffff16565b81526020016117e36117d086604001514261227b90919063ffffffff16565b866020015161227b90919063ffffffff16565b81526020014281526020018460600151815250601160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18582601160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a161194a85827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612b419092919063ffffffff16565b8093505050505b919050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611a17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806002819055505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b24576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000611b2e610c81565b14611b84576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806131556021913960400191505060405180910390fd5b6040518060a0016040528087815260200186815260200185815260200184815260200183815250600760008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050508060058190555042600681905550505050505050565b60116020528060005260406000206000915090508060000154908060010154908060020154908060030154905084565b6000611db5670de0b6b3a7640000611da7611da2611cfc7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611ca557600080fd5b505afa158015611cb9573d6000803e3d6000fd5b505050506040513d6020811015611ccf57600080fd5b810190808051906020019092919050505060ff16600a0a611cee610c81565b6121ab90919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d6257600080fd5b505afa158015611d76573d6000803e3d6000fd5b505050506040513d6020811015611d8c57600080fd5b81019080805190602001909291905050506122c5565b6125a6565b61223190919063ffffffff16565b905090565b60078060000154908060010154908060020154908060030154908060040154905085565b6000611eca611e9a60057f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4e57600080fd5b505afa158015611e62573d6000803e3d6000fd5b505050506040513d6020811015611e7857600080fd5b810190808051906020019092919050505060ff1661227b90919063ffffffff16565b600a0a611ebc611ea8611c28565b6007600001546121ab90919063ffffffff16565b61223190919063ffffffff16565b9050600760020154811015611ee25760076002015490505b90565b6000611fb4620186a0611fa66007600301547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5d57600080fd5b505afa158015611f71573d6000803e3d6000fd5b505050506040513d6020811015611f8757600080fd5b81019080805190602001909291905050506121ab90919063ffffffff16565b61223190919063ffffffff16565b905090565b600080611fd16006544261227b90919063ffffffff16565b9050611fff600760010154611ff1836005546121ab90919063ffffffff16565b61223190919063ffffffff16565b91506005548211156120115760055491505b5090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146120d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561215c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806131096026913960400191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60065481565b60055481565b6000808314156121be576000905061222b565b60008284029050828482816121cf57fe5b0414612226576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806131766021913960400191505060405180910390fd5b809150505b92915050565b600061227383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612d43565b905092915050565b60006122bd83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e1f565b905092915050565b6122cd6130d7565b60008211612326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061312f6026913960400191505060405180910390fd5b600083141561236457604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090506125a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71ffffffffffffffffffffffffffffffffffff16831161249d57600082607060ff1685901b816123b157fe5b0490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16811115612468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150506125a0565b60006124b9846e01000000000000000000000000000085612edf565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681111561256f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150505b92915050565b60006612725dd1d243ab82600001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16816125da57fe5b049050919050565b6125fe6125ed611fb9565b60055461227b90919063ffffffff16565b60058190555042600681905550565b60008082840190508381101561268b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600060608573ffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b868686604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106127955780518252602082019150602081019050602083039250612772565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146127f7576040519150601f19603f3d011682016040523d82523d6000602084013e6127fc565b606091505b509150915081801561283c575060008151148061283b575080806020019051602081101561282957600080fd5b81019080805190602001909291905050505b5b6128ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5452414e534645525f46524f4d5f4641494c454400000000000000000000000081525060200191505060405180910390fd5b505050505050565b60006129a261297260057f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561292657600080fd5b505afa15801561293a573d6000803e3d6000fd5b505050506040513d602081101561295057600080fd5b810190808051906020019092919050505060ff1661227b90919063ffffffff16565b600a0a612994612980611c28565b6007600001546121ab90919063ffffffff16565b61223190919063ffffffff16565b90506007600201548110156129be5760076002015490506129d8565b6000600760020154146129d75760006007600201819055505b5b90565b60006129fa600c60030154600c6004015461260d90919063ffffffff16565b90506000600c6001015414158015612a125750804210155b15612b3e5760006007600001549050600c60000160009054906101000a900460ff1615612a8157612a56600c6001015460076000015461260d90919063ffffffff16565b600760000181905550600c6002015460076000015410612a7c576000600c600101819055505b612ac5565b612a9e600c6001015460076000015461227b90919063ffffffff16565b600760000181905550600c6002015460076000015411612ac4576000600c600101819055505b5b42600c600401819055507fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a81600760000154600c60010154600c60000160009054906101000a900460ff1660405180858152602001848152602001838152602001821515815260200194505050505060405180910390a1505b50565b600060608473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b8585604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310612c235780518252602082019150602081019050602083039250612c00565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612c85576040519150601f19603f3d011682016040523d82523d6000602084013e612c8a565b606091505b5091509150818015612cca5750600081511480612cc95750808060200190516020811015612cb757600080fd5b81019080805190602001909291905050505b5b612d3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5452414e534645525f4641494c4544000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b60008083118290612def576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612db4578082015181840152602081019050612d99565b50505050905090810190601f168015612de15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612dfb57fe5b049050838581612e0757fe5b06818502018514612e1457fe5b809150509392505050565b6000838311158290612ecc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e91578082015181840152602081019050612e76565b50505050905090810190601f168015612ebe5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000806000612eee8686612fbf565b9150915060008480612efc57fe5b868809905082811115612f10576001820391505b80830392506000821415612f3257848381612f2757fe5b049350505050612fb8565b848210612fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f46756c6c4d6174683a2046554c4c4449565f4f564552464c4f5700000000000081525060200191505060405180910390fd5b612fb2838387613012565b93505050505b9392505050565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80612fec57fe5b8486099050838502925082810391508281101561300a576001820391505b509250929050565b600080826000038316905080838161302657fe5b04925080858161303257fe5b049450600181826000038161304357fe5b04018402850194506000600190508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808602925050509392505050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f44656274206d757374206265203020666f7220696e697469616c697a6174696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f757273a2646970667358221220a398d566c84c2d824714d49cad90ba9563c265e196bc1f54f3c159cc7e24714964736f6c63430007050033000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca0000000000000000000000000fe0ed7f146cb12e4b9759aff4fa8d34571802ca

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101735760003560e01c80638dbdbe6d116100de578063d502562511610097578063e392a26211610071578063e392a26214610682578063f2fde38b146106a0578063f5c2ab5b146106e4578063fc7b9c181461070257610173565b8063d50256251461060c578063d7ccfb0b14610646578063e0176de81461066457610173565b80638dbdbe6d1461040f57806395a2251f1461047b5780639c006085146104d3578063a50603b214610521578063cd1234b314610581578063cea55f57146105ee57610173565b8063507930ec11610130578063507930ec146102e7578063759076e51461033f5780637927ebf81461035d5780637cbe044c1461039f5780637fd6f15c146103bd5780638da5cb5b146103db57610173565b8063017e7e581461017857806301b88ee8146101ac5780631a3d0068146102045780631e321a0f146102525780632bab6bde1461028d578063451ee4a1146102ab575b600080fd5b610180610720565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ee600480360360208110156101c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610746565b6040518082815260200191505060405180910390f35b6102506004803603608081101561021a57600080fd5b810190808035151590602001909291908035906020019092919080359060200190929190803590602001909291905050506107dd565b005b61028b6004803603604081101561026857600080fd5b81019080803560ff169060200190929190803590602001909291905050506109bc565b005b610295610b64565b6040518082815260200191505060405180910390f35b6102b3610b6a565b6040518086151581526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b610329600480360360208110156102fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b9b565b6040518082815260200191505060405180910390f35b610347610c81565b6040518082815260200191505060405180910390f35b6103896004803603602081101561037357600080fd5b8101908080359060200190929190505050610ca4565b6040518082815260200191505060405180910390f35b6103a7610cdc565b6040518082815260200191505060405180910390f35b6103c5610ce2565b6040518082815260200191505060405180910390f35b6103e3610ce8565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104656004803603606081101561042557600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d0c565b6040518082815260200191505060405180910390f35b6104bd6004803603602081101561049157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115ab565b6040518082815260200191505060405180910390f35b61051f600480360360408110156104e957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611956565b005b61057f600480360360c081101561053757600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050611a63565b005b6105c36004803603602081101561059757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bf8565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b6105f6611c28565b6040518082815260200191505060405180910390f35b610614611dba565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b61064e611dde565b6040518082815260200191505060405180910390f35b61066c611ee5565b6040518082815260200191505060405180910390f35b61068a611fb9565b6040518082815260200191505060405180910390f35b6106e2600480360360208110156106b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612015565b005b6106ec61219f565b6040518082815260200191505060405180910390f35b61070a6121a5565b6040518082815260200191505060405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008061075283610b9b565b90506000601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154905061271082106107ac578092506107d6565b6107d36127106107c584846121ab90919063ffffffff16565b61223190919063ffffffff16565b92505b5050919050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461089e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6108cb6103e86108bd601e6007600001546121ab90919063ffffffff16565b61223190919063ffffffff16565b831115610940576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e6372656d656e7420746f6f206c617267650000000000000000000000000081525060200191505060405180910390fd5b6040518060a00160405280851515815260200184815260200183815260200182815260200142815250600c60008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015590505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a7d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60006002811115610a8a57fe5b826002811115610a9657fe5b1415610b07576201fa40811015610af8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806131ba6024913960400191505060405180910390fd5b80600760010181905550610b60565b60016002811115610b1457fe5b826002811115610b2057fe5b1415610b355780600760030181905550610b5f565b600280811115610b4157fe5b826002811115610b4d57fe5b1415610b5e57806007600401819055505b5b5b5050565b60045481565b600c8060000160009054906101000a900460ff16908060010154908060020154908060030154908060040154905085565b6000610ba56130af565b601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090506000610c3282604001514261227b90919063ffffffff16565b90506000826020015190506000811115610c7457610c6d81610c5f612710856121ab90919063ffffffff16565b61223190919063ffffffff16565b9350610c79565b600093505b505050919050565b6000610c9f610c8e611fb9565b60055461227b90919063ffffffff16565b905090565b6000610cd5633b9aca00610cc7610cc285610cbd611dde565b6122c5565b6125a6565b61223190919063ffffffff16565b9050919050565b60035481565b60025481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f496e76616c69642061646472657373000000000000000000000000000000000081525060200191505060405180910390fd5b610db86125e2565b6000610dc2611dde565b905080841015610e1d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131976023913960400191505060405180910390fd5b60007f000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca73ffffffffffffffffffffffffffffffffffffffff1663d1b317e57f0000000000000000000000000fe0ed7f146cb12e4b9759aff4fa8d34571802ca886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b158015610ece57600080fd5b505afa158015610ee2573d6000803e3d6000fd5b505050506040513d6020811015610ef857600080fd5b810190808051906020019092919050505090506000610f1682610ca4565b905060647f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610f8057600080fd5b505afa158015610f94573d6000803e3d6000fd5b505050506040513d6020811015610faa57600080fd5b810190808051906020019092919050505060ff16600a0a81610fc857fe5b0481101561103e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f20736d616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b611046611ee5565b8111156110bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f206c6172676500000000000000000000000000000000000081525060200191505060405180910390fd5b6110d08260055461260d90919063ffffffff16565b6005819055506007600401546005541115611153576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4d6178206361706163697479207265616368656400000000000000000000000081525060200191505060405180910390fd5b60405180608001604052806111b383601160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461260d90919063ffffffff16565b815260200160076001015481526020014281526020016111d1611dde565b815250601160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050506112538760035461260d90919063ffffffff16565b60038190555061126e8160045461260d90919063ffffffff16565b6004819055507f000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca73ffffffffffffffffffffffffffffffffffffffff166346552cc330836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561130557600080fd5b505af1158015611319573d6000803e3d6000fd5b50505050600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415801561137e57506000600254115b1561147e5760006113af620186a06113a1600254856121ab90919063ffffffff16565b61223190919063ffffffff16565b90507f000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca73ffffffffffffffffffffffffffffffffffffffff166346552cc3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561146457600080fd5b505af1158015611478573d6000803e3d6000fd5b50505050505b6114eb337f000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca897f0000000000000000000000000fe0ed7f146cb12e4b9759aff4fa8d34571802ca73ffffffffffffffffffffffffffffffffffffffff16612695909392919063ffffffff16565b7fb7ce5a2d90f1705ca02547b0eb827724683e0df3b809477ae4326d0eefed0bc087826115266007600101544261260d90919063ffffffff16565b60405180848152602001838152602001828152602001935050505060405180910390a17f2cb17bd1fd2a1fecfefae2de1e6a59194abaa62179652924ccdca01617f0bf166115726128b6565b61157a611c28565b604051808381526020018281526020019250505060405180910390a161159e6129db565b8093505050509392505050565b60006115b56130af565b601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050600061163484610b9b565b9050612710811061176057601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000905550507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18483600001516000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a16117528483600001517f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff16612b419092919063ffffffff16565b816000015192505050611951565b600061178d61271061177f8486600001516121ab90919063ffffffff16565b61223190919063ffffffff16565b905060405180608001604052806117b183866000015161227b90919063ffffffff16565b81526020016117e36117d086604001514261227b90919063ffffffff16565b866020015161227b90919063ffffffff16565b81526020014281526020018460600151815250601160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18582601160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a161194a85827f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff16612b419092919063ffffffff16565b8093505050505b919050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611a17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806002819055505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b24576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000611b2e610c81565b14611b84576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806131556021913960400191505060405180910390fd5b6040518060a0016040528087815260200186815260200185815260200184815260200183815250600760008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050508060058190555042600681905550505050505050565b60116020528060005260406000206000915090508060000154908060010154908060020154908060030154905084565b6000611db5670de0b6b3a7640000611da7611da2611cfc7f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611ca557600080fd5b505afa158015611cb9573d6000803e3d6000fd5b505050506040513d6020811015611ccf57600080fd5b810190808051906020019092919050505060ff16600a0a611cee610c81565b6121ab90919063ffffffff16565b7f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d6257600080fd5b505afa158015611d76573d6000803e3d6000fd5b505050506040513d6020811015611d8c57600080fd5b81019080805190602001909291905050506122c5565b6125a6565b61223190919063ffffffff16565b905090565b60078060000154908060010154908060020154908060030154908060040154905085565b6000611eca611e9a60057f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4e57600080fd5b505afa158015611e62573d6000803e3d6000fd5b505050506040513d6020811015611e7857600080fd5b810190808051906020019092919050505060ff1661227b90919063ffffffff16565b600a0a611ebc611ea8611c28565b6007600001546121ab90919063ffffffff16565b61223190919063ffffffff16565b9050600760020154811015611ee25760076002015490505b90565b6000611fb4620186a0611fa66007600301547f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5d57600080fd5b505afa158015611f71573d6000803e3d6000fd5b505050506040513d6020811015611f8757600080fd5b81019080805190602001909291905050506121ab90919063ffffffff16565b61223190919063ffffffff16565b905090565b600080611fd16006544261227b90919063ffffffff16565b9050611fff600760010154611ff1836005546121ab90919063ffffffff16565b61223190919063ffffffff16565b91506005548211156120115760055491505b5090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146120d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561215c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806131096026913960400191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60065481565b60055481565b6000808314156121be576000905061222b565b60008284029050828482816121cf57fe5b0414612226576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806131766021913960400191505060405180910390fd5b809150505b92915050565b600061227383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612d43565b905092915050565b60006122bd83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e1f565b905092915050565b6122cd6130d7565b60008211612326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061312f6026913960400191505060405180910390fd5b600083141561236457604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090506125a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71ffffffffffffffffffffffffffffffffffff16831161249d57600082607060ff1685901b816123b157fe5b0490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16811115612468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150506125a0565b60006124b9846e01000000000000000000000000000085612edf565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681111561256f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150505b92915050565b60006612725dd1d243ab82600001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16816125da57fe5b049050919050565b6125fe6125ed611fb9565b60055461227b90919063ffffffff16565b60058190555042600681905550565b60008082840190508381101561268b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600060608573ffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b868686604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106127955780518252602082019150602081019050602083039250612772565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146127f7576040519150601f19603f3d011682016040523d82523d6000602084013e6127fc565b606091505b509150915081801561283c575060008151148061283b575080806020019051602081101561282957600080fd5b81019080805190602001909291905050505b5b6128ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5452414e534645525f46524f4d5f4641494c454400000000000000000000000081525060200191505060405180910390fd5b505050505050565b60006129a261297260057f0000000000000000000000007b768470590b8a0d28fc714d0a70754d556d14ed73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561292657600080fd5b505afa15801561293a573d6000803e3d6000fd5b505050506040513d602081101561295057600080fd5b810190808051906020019092919050505060ff1661227b90919063ffffffff16565b600a0a612994612980611c28565b6007600001546121ab90919063ffffffff16565b61223190919063ffffffff16565b90506007600201548110156129be5760076002015490506129d8565b6000600760020154146129d75760006007600201819055505b5b90565b60006129fa600c60030154600c6004015461260d90919063ffffffff16565b90506000600c6001015414158015612a125750804210155b15612b3e5760006007600001549050600c60000160009054906101000a900460ff1615612a8157612a56600c6001015460076000015461260d90919063ffffffff16565b600760000181905550600c6002015460076000015410612a7c576000600c600101819055505b612ac5565b612a9e600c6001015460076000015461227b90919063ffffffff16565b600760000181905550600c6002015460076000015411612ac4576000600c600101819055505b5b42600c600401819055507fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a81600760000154600c60010154600c60000160009054906101000a900460ff1660405180858152602001848152602001838152602001821515815260200194505050505060405180910390a1505b50565b600060608473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b8585604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310612c235780518252602082019150602081019050602083039250612c00565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612c85576040519150601f19603f3d011682016040523d82523d6000602084013e612c8a565b606091505b5091509150818015612cca5750600081511480612cc95750808060200190516020811015612cb757600080fd5b81019080805190602001909291905050505b5b612d3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5452414e534645525f4641494c4544000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b60008083118290612def576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612db4578082015181840152602081019050612d99565b50505050905090810190601f168015612de15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612dfb57fe5b049050838581612e0757fe5b06818502018514612e1457fe5b809150509392505050565b6000838311158290612ecc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e91578082015181840152602081019050612e76565b50505050905090810190601f168015612ebe5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000806000612eee8686612fbf565b9150915060008480612efc57fe5b868809905082811115612f10576001820391505b80830392506000821415612f3257848381612f2757fe5b049350505050612fb8565b848210612fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f46756c6c4d6174683a2046554c4c4449565f4f564552464c4f5700000000000081525060200191505060405180910390fd5b612fb2838387613012565b93505050505b9392505050565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80612fec57fe5b8486099050838502925082810391508281101561300a576001820391505b509250929050565b600080826000038316905080838161302657fe5b04925080858161303257fe5b049450600181826000038161304357fe5b04018402850194506000600190508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808602925050509392505050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f44656274206d757374206265203020666f7220696e697469616c697a6174696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f757273a2646970667358221220a398d566c84c2d824714d49cad90ba9563c265e196bc1f54f3c159cc7e24714964736f6c63430007050033

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

000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca0000000000000000000000000fe0ed7f146cb12e4b9759aff4fa8d34571802ca

-----Decoded View---------------
Arg [0] : _treasury (address): 0x710154A8503428D53710A620B8A1C970BeDdB8CA
Arg [1] : _principalToken (address): 0x0fE0Ed7F146Cb12e4B9759afF4FA8d34571802ca

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000710154a8503428d53710a620b8a1c970beddb8ca
Arg [1] : 0000000000000000000000000fe0ed7f146cb12e4b9759aff4fa8d34571802ca


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.