ETH Price: $2,473.44 (+0.77%)
 

Overview

ETH Balance

0.000000078083093607 ETH

Eth Value

Less Than $0.01 (@ $2,473.44/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Liquidate Bonds127041922021-06-25 16:05:571227 days ago1624637157IN
0x52A1aD87...727e19C7d
0 ETH0.0282898549
Settle Tokens125960762021-06-08 20:34:121244 days ago1623184452IN
0x52A1aD87...727e19C7d
0 ETH0.0012519930
Renew Maturity125689992021-06-04 16:06:541248 days ago1622822814IN
0x52A1aD87...727e19C7d
0 ETH0.0498466824
Liquidate Bonds125689922021-06-04 16:05:111248 days ago1622822711IN
0x52A1aD87...727e19C7d
0 ETH0.0126232422
Claim Reward124985812021-05-24 18:15:201259 days ago1621880120IN
0x52A1aD87...727e19C7d
0 ETH0.0036492395
Claim Reward124985162021-05-24 17:59:571259 days ago1621879197IN
0x52A1aD87...727e19C7d
0 ETH0.0034571790
Remove Liquidity124901012021-05-23 10:50:551260 days ago1621767055IN
0x52A1aD87...727e19C7d
0 ETH0.0101483100
Claim Reward124453552021-05-16 12:04:401267 days ago1621166680IN
0x52A1aD87...727e19C7d
0 ETH0.009891850
Settle Tokens124453422021-05-16 12:02:431267 days ago1621166563IN
0x52A1aD87...727e19C7d
0 ETH0.0027543766
Settle Tokens124393182021-05-15 13:48:391268 days ago1621086519IN
0x52A1aD87...727e19C7d
0 ETH0.0036307787
Settle Tokens124385402021-05-15 10:50:301268 days ago1621075830IN
0x52A1aD87...727e19C7d
0 ETH0.0027961167
Claim Reward124361552021-05-15 1:51:521269 days ago1621043512IN
0x52A1aD87...727e19C7d
0 ETH0.01175316101
Settle Tokens124361442021-05-15 1:48:401269 days ago1621043320IN
0x52A1aD87...727e19C7d
0 ETH0.00542529130
Claim Reward124344142021-05-14 19:28:301269 days ago1621020510IN
0x52A1aD87...727e19C7d
0 ETH0.0107058592
Settle Tokens124341572021-05-14 18:28:441269 days ago1621016924IN
0x52A1aD87...727e19C7d
0 ETH0.00517489124
Settle Tokens124335602021-05-14 16:23:531269 days ago1621009433IN
0x52A1aD87...727e19C7d
0 ETH0.00843006202
Renew Maturity124335222021-05-14 16:13:421269 days ago1621008822IN
0x52A1aD87...727e19C7d
0 ETH0.31516011145.00000145
Liquidate Bonds124335062021-05-14 16:11:301269 days ago1621008690IN
0x52A1aD87...727e19C7d
0 ETH0.21551657169
Claim Reward124332332021-05-14 15:13:291269 days ago1621005209IN
0x52A1aD87...727e19C7d
0 ETH0.01532865189
Remove Liquidity124328892021-05-14 13:53:551269 days ago1621000435IN
0x52A1aD87...727e19C7d
0 ETH0.01182591145
Remove Liquidity124327442021-05-14 13:19:431269 days ago1620998383IN
0x52A1aD87...727e19C7d
0 ETH0.00881641108.1
Claim Reward124326192021-05-14 12:51:531269 days ago1620996713IN
0x52A1aD87...727e19C7d
0 ETH0.0053763384
Update Total Rew...124260222021-05-13 12:27:061270 days ago1620908826IN
0x52A1aD87...727e19C7d
0 ETH0.00772035150
Remove Liquidity124242642021-05-13 5:51:261270 days ago1620885086IN
0x52A1aD87...727e19C7d
0 ETH0.00843202107
Claim Reward124221222021-05-12 21:58:271271 days ago1620856707IN
0x52A1aD87...727e19C7d
0 ETH0.00680294177.1
View all transactions

Latest 12 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
125689992021-06-04 16:06:541248 days ago1622822814
0x52A1aD87...727e19C7d
9.3648122 ETH
124335222021-05-14 16:13:421269 days ago1621008822
0x52A1aD87...727e19C7d
257.24381715 ETH
124335062021-05-14 16:11:301269 days ago1621008690
0x52A1aD87...727e19C7d
15.71364145 ETH
124335062021-05-14 16:11:301269 days ago1621008690
0x52A1aD87...727e19C7d
15.71364145 ETH
124335062021-05-14 16:11:301269 days ago1621008690
0x52A1aD87...727e19C7d
5.77658378 ETH
124335062021-05-14 16:11:301269 days ago1621008690
0x52A1aD87...727e19C7d
25.56979974 ETH
123813512021-05-06 14:47:171277 days ago1620312437
0x52A1aD87...727e19C7d
0.01674235 ETH
123025072021-04-24 10:54:401289 days ago1619261680
0x52A1aD87...727e19C7d
3.3598 ETH
122984762021-04-23 19:52:591290 days ago1619207579
0x52A1aD87...727e19C7d
1.28794853 ETH
122975502021-04-23 16:31:111290 days ago1619195471
0x52A1aD87...727e19C7d
57.05226216 ETH
122975502021-04-23 16:31:111290 days ago1619195471
0x52A1aD87...727e19C7d
28.46919269 ETH
122693412021-04-19 8:09:001294 days ago1618819740
0x52A1aD87...727e19C7d
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SimpleAggregatorCollateralizedEth

Compiler Version
v0.7.1+commit.f4a555be

Optimization Enabled:
Yes with 200 runs

Other Settings:
constantinople EvmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-04-23
*/

// File: contracts/BondToken_and_GDOTC/util/TransferETHInterface.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.1;

interface TransferETHInterface {
    receive() external payable;

    event LogTransferETH(address indexed from, address indexed to, uint256 value);
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol



pragma solidity ^0.7.0;

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

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

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

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

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

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

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

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

// File: contracts/BondToken_and_GDOTC/bondToken/BondTokenInterface.sol


pragma solidity 0.7.1;



interface BondTokenInterface is IERC20 {
    event LogExpire(uint128 rateNumerator, uint128 rateDenominator, bool firstTime);

    function mint(address account, uint256 amount) external returns (bool success);

    function expire(uint128 rateNumerator, uint128 rateDenominator)
        external
        returns (bool firstTime);

    function simpleBurn(address account, uint256 amount) external returns (bool success);

    function burn(uint256 amount) external returns (bool success);

    function burnAll() external returns (uint256 amount);

    function getRate() external view returns (uint128 rateNumerator, uint128 rateDenominator);
}

// File: contracts/BondToken_and_GDOTC/oracle/LatestPriceOracleInterface.sol


pragma solidity 0.7.1;

/**
 * @dev Interface of the price oracle.
 */
interface LatestPriceOracleInterface {
    /**
     * @dev Returns `true`if oracle is working.
     */
    function isWorking() external returns (bool);

    /**
     * @dev Returns the last updated price. Decimals is 8.
     **/
    function latestPrice() external returns (uint256);

    /**
     * @dev Returns the timestamp of the last updated price.
     */
    function latestTimestamp() external returns (uint256);
}

// File: contracts/BondToken_and_GDOTC/oracle/PriceOracleInterface.sol


pragma solidity 0.7.1;


/**
 * @dev Interface of the price oracle.
 */
interface PriceOracleInterface is LatestPriceOracleInterface {
    /**
     * @dev Returns the latest id. The id start from 1 and increments by 1.
     */
    function latestId() external returns (uint256);

    /**
     * @dev Returns the historical price specified by `id`. Decimals is 8.
     */
    function getPrice(uint256 id) external returns (uint256);

    /**
     * @dev Returns the timestamp of historical price specified by `id`.
     */
    function getTimestamp(uint256 id) external returns (uint256);
}

// File: contracts/BondToken_and_GDOTC/bondMaker/BondMakerInterface.sol


pragma solidity 0.7.1;



interface BondMakerInterface {
    event LogNewBond(
        bytes32 indexed bondID,
        address indexed bondTokenAddress,
        uint256 indexed maturity,
        bytes32 fnMapID
    );

    event LogNewBondGroup(
        uint256 indexed bondGroupID,
        uint256 indexed maturity,
        uint64 indexed sbtStrikePrice,
        bytes32[] bondIDs
    );

    event LogIssueNewBonds(uint256 indexed bondGroupID, address indexed issuer, uint256 amount);

    event LogReverseBondGroupToCollateral(
        uint256 indexed bondGroupID,
        address indexed owner,
        uint256 amount
    );

    event LogExchangeEquivalentBonds(
        address indexed owner,
        uint256 indexed inputBondGroupID,
        uint256 indexed outputBondGroupID,
        uint256 amount
    );

    event LogLiquidateBond(bytes32 indexed bondID, uint128 rateNumerator, uint128 rateDenominator);

    function registerNewBond(uint256 maturity, bytes calldata fnMap)
        external
        returns (
            bytes32 bondID,
            address bondTokenAddress,
            bytes32 fnMapID
        );

    function registerNewBondGroup(bytes32[] calldata bondIDList, uint256 maturity)
        external
        returns (uint256 bondGroupID);

    function reverseBondGroupToCollateral(uint256 bondGroupID, uint256 amount)
        external
        returns (bool success);

    function exchangeEquivalentBonds(
        uint256 inputBondGroupID,
        uint256 outputBondGroupID,
        uint256 amount,
        bytes32[] calldata exceptionBonds
    ) external returns (bool);

    function liquidateBond(uint256 bondGroupID, uint256 oracleHintID)
        external
        returns (uint256 totalPayment);

    function collateralAddress() external view returns (address);

    function oracleAddress() external view returns (PriceOracleInterface);

    function feeTaker() external view returns (address);

    function decimalsOfBond() external view returns (uint8);

    function decimalsOfOraclePrice() external view returns (uint8);

    function maturityScale() external view returns (uint256);

    function nextBondGroupID() external view returns (uint256);

    function getBond(bytes32 bondID)
        external
        view
        returns (
            address bondAddress,
            uint256 maturity,
            uint64 solidStrikePrice,
            bytes32 fnMapID
        );

    function getFnMap(bytes32 fnMapID) external view returns (bytes memory fnMap);

    function getBondGroup(uint256 bondGroupID)
        external
        view
        returns (bytes32[] memory bondIDs, uint256 maturity);

    function generateFnMapID(bytes calldata fnMap) external view returns (bytes32 fnMapID);

    function generateBondID(uint256 maturity, bytes calldata fnMap)
        external
        view
        returns (bytes32 bondID);
}

// File: contracts/contracts/Interfaces/StrategyInterface.sol


pragma solidity 0.7.1;


interface SimpleStrategyInterface {
    function calcNextMaturity() external view returns (uint256 nextTimeStamp);

    function calcCallStrikePrice(
        uint256 currentPriceE8,
        uint64 priceUnit,
        bool isReversedOracle
    ) external pure returns (uint256 callStrikePrice);

    function calcRoundPrice(
        uint256 price,
        uint64 priceUnit,
        uint8 divisor
    ) external pure returns (uint256 roundedPrice);

    function getTrancheBonds(
        BondMakerInterface bondMaker,
        address aggregatorAddress,
        uint256 issueBondGroupIdOrStrikePrice,
        uint256 price,
        uint256[] calldata bondGroupList,
        uint64 priceUnit,
        bool isReversedOracle
    )
        external
        view
        returns (
            uint256 issueAmount,
            uint256 ethAmount,
            uint256[2] memory IDAndAmountOfBurn
        );

    function getCurrentStrikePrice(
        uint256 currentPriceE8,
        uint64 priceUnit,
        bool isReversedOracle
    ) external pure returns (uint256);

    function getCurrentSpread(
        address owner,
        address oracleAddress,
        bool isReversedOracle
    ) external view returns (int16);

    function registerCurrentFeeBase(
        int16 currentFeeBase,
        uint256 currentCollateralPerToken,
        uint256 nextCollateralPerToken,
        address owner,
        address oracleAddress,
        bool isReversedOracle
    ) external;
}

// File: contracts/contracts/Interfaces/SimpleAggragatorInterface.sol


pragma experimental ABIEncoderV2;
pragma solidity 0.7.1;

interface SimpleAggregatorInterface {
    struct TotalReward {
        uint64 term;
        uint64 value;
    }

    enum AggregatorPhase {BEFORE_START, ACTIVE, COOL_TIME, AFTER_MATURITY, EXPIRED}

    function renewMaturity() external;

    function removeLiquidity(uint128 amount) external returns (bool success);

    function settleTokens() external returns (uint256 unsentETH, uint256 unsentToken);

    function changeSpread() external;

    function liquidateBonds() external;

    function trancheBonds() external;

    function claimReward() external;

    function addSuitableBondGroup() external returns (uint256 bondGroupID);

    function getCollateralAddress() external view returns (address);

    function getCollateralAmount() external view returns (uint256);

    function getCollateralDecimal() external view returns (int16);

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

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

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

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

    function balanceOf(address _owner) external view returns (uint256 balance);

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

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

    function allowance(address _owner, address _spender) external view returns (uint256 remaining);

    function getExpectedBalance(address user, bool hasReservation)
        external
        view
        returns (uint256 expectedBalance);

    function getCurrentPhase() external view returns (AggregatorPhase);

    function updateStartBondGroupId() external;

    function getInfo()
        external
        view
        returns (
            address bondMaker,
            address strategy,
            address dotc,
            address bondPricerAddress,
            address oracleAddress,
            address rewardTokenAddress,
            address registratorAddress,
            address owner,
            bool reverseOracle,
            uint64 basePriceUnit,
            uint128 maxSupply
        );

    function getCurrentStatus()
        external
        view
        returns (
            uint256 term,
            int16 feeBase,
            uint32 uncheckbondGroupId,
            uint64 unit,
            uint64 trancheTime,
            bool isDanger
        );

    function getTermInfo(uint256 term)
        external
        view
        returns (
            uint64 maturity,
            uint64 solidStrikePrice,
            bytes32 SBTID
        );

    function getBondGroupIDFromTermAndPrice(uint256 term, uint256 price)
        external
        view
        returns (uint256 bondGroupID);

    function getRewardAmount(address user) external view returns (uint64);

    function getTotalRewards() external view returns (TotalReward[] memory);

    function isTotalSupplySafe() external view returns (bool);

    function getTotalUnmovedAssets() external view returns (uint256, uint256);

    function totalShareData(uint256 term)
        external
        view
        returns (uint128 totalShare, uint128 totalCollateralPerToken);

    function getCollateralPerToken(uint256 term) external view returns (uint256);

    function getBondGroupIdFromStrikePrice(uint256 term, uint256 strikePrice)
        external
        view
        returns (uint256);

    function getBalanceData(address user)
        external
        view
        returns (
            uint128 amount,
            uint64 term,
            uint64 rewardAmount
        );

    function getIssuableBondGroups() external view returns (uint256[] memory);

    function getLiquidationData(uint256 term)
        external
        view
        returns (
            bool isLiquidated,
            uint32 liquidatedBondGroupID,
            uint32 endBondGroupId
        );
}

// File: contracts/contracts/Interfaces/VolatilityOracleInterface.sol


pragma solidity 0.7.1;

interface VolatilityOracleInterface {
    function getVolatility(uint64 untilMaturity) external view returns (uint64 volatilityE8);
}

// File: contracts/BondToken_and_GDOTC/bondPricer/Enums.sol


pragma solidity 0.7.1;

/**
    Pure SBT:
        ___________
       /
      /
     /
    /

    LBT Shape:
              /
             /
            /
           /
    ______/

    SBT Shape:
              ______
             /
            /
    _______/

    Triangle:
              /\
             /  \
            /    \
    _______/      \________
 */
enum BondType {NONE, PURE_SBT, SBT_SHAPE, LBT_SHAPE, TRIANGLE}

// File: contracts/BondToken_and_GDOTC/bondPricer/BondPricerInterface.sol


pragma solidity 0.7.1;


interface BondPricerInterface {
    /**
     * @notice Calculate bond price and leverage by black-scholes formula.
     * @param bondType type of target bond.
     * @param points coodinates of polyline which is needed for price calculation
     * @param spotPrice is a oracle price.
     * @param volatilityE8 is a oracle volatility.
     * @param untilMaturity Remaining period of target bond in second
     **/
    function calcPriceAndLeverage(
        BondType bondType,
        uint256[] calldata points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) external view returns (uint256 price, uint256 leverageE8);
}

// File: @openzeppelin/contracts/GSN/Context.sol



pragma solidity ^0.7.0;

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

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// File: @openzeppelin/contracts/math/SafeMath.sol



pragma solidity ^0.7.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    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;
    }

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

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

// File: @openzeppelin/contracts/utils/Address.sol



pragma solidity ^0.7.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

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

// File: @openzeppelin/contracts/token/ERC20/ERC20.sol



pragma solidity ^0.7.0;





/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

// File: contracts/contracts/Interfaces/ExchangeInterface.sol


pragma solidity 0.7.1;





interface ExchangeInterface {
    function changeSpread(int16 spread) external;

    function createVsBondPool(
        BondMakerInterface bondMakerForUserAddress,
        VolatilityOracleInterface volatilityOracleAddress,
        BondPricerInterface bondPricerForUserAddress,
        BondPricerInterface bondPricerAddress,
        int16 feeBaseE4
    ) external returns (bytes32 poolID);

    function createVsErc20Pool(
        ERC20 swapPairAddress,
        LatestPriceOracleInterface swapPairOracleAddress,
        BondPricerInterface bondPricerAddress,
        int16 feeBaseE4,
        bool isBondSale
    ) external returns (bytes32 poolID);

    function createVsEthPool(
        LatestPriceOracleInterface ethOracleAddress,
        BondPricerInterface bondPricerAddress,
        int16 feeBaseE4,
        bool isBondSale
    ) external returns (bytes32 poolID);

    function updateVsBondPool(
        bytes32 poolID,
        VolatilityOracleInterface volatilityOracleAddress,
        BondPricerInterface bondPricerForUserAddress,
        BondPricerInterface bondPricerAddress,
        int16 feeBaseE4
    ) external;

    function updateVsErc20Pool(
        bytes32 poolID,
        LatestPriceOracleInterface swapPairOracleAddress,
        BondPricerInterface bondPricerAddress,
        int16 feeBaseE4
    ) external;

    function updateVsEthPool(
        bytes32 poolID,
        LatestPriceOracleInterface ethOracleAddress,
        BondPricerInterface bondPricerAddress,
        int16 feeBaseE4
    ) external;

    function generateVsBondPoolID(address seller, address bondMakerForUser)
        external
        view
        returns (bytes32 poolID);

    function generateVsErc20PoolID(
        address seller,
        address swapPairAddress,
        bool isBondSale
    ) external view returns (bytes32 poolID);

    function generateVsEthPoolID(address seller, bool isBondSale)
        external
        view
        returns (bytes32 poolID);

    function withdrawEth() external;

    function depositEth() external payable;

    function ethAllowance(address owner) external view returns (uint256 amount);

    function bondMakerAddress() external view returns (BondMakerInterface);
}

// File: @openzeppelin/contracts/math/SignedSafeMath.sol



pragma solidity ^0.7.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMath {
    int256 constant private _INT256_MIN = -2**255;

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

        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

        return c;
    }

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

        return c;
    }
}

// File: @openzeppelin/contracts/utils/SafeCast.sol



pragma solidity ^0.7.0;


/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        require(value < 2**255, "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// File: contracts/BondToken_and_GDOTC/math/UseSafeMath.sol


pragma solidity 0.7.1;




/**
 * @notice ((a - 1) / b) + 1 = (a + b -1) / b
 * for example a.add(10**18 -1).div(10**18) = a.sub(1).div(10**18) + 1
 */

library SafeMathDivRoundUp {
    using SafeMath for uint256;

    function divRoundUp(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        require(b > 0, errorMessage);
        return ((a - 1) / b) + 1;
    }

    function divRoundUp(uint256 a, uint256 b) internal pure returns (uint256) {
        return divRoundUp(a, b, "SafeMathDivRoundUp: modulo by zero");
    }
}

/**
 * @title UseSafeMath
 * @dev One can use SafeMath for not only uint256 but also uin64 or uint16,
 * and also can use SafeCast for uint256.
 * For example:
 *   uint64 a = 1;
 *   uint64 b = 2;
 *   a = a.add(b).toUint64() // `a` become 3 as uint64
 * In addition, one can use SignedSafeMath and SafeCast.toUint256(int256) for int256.
 * In the case of the operation to the uint64 value, one needs to cast the value into int256 in
 * advance to use `sub` as SignedSafeMath.sub not SafeMath.sub.
 * For example:
 *   int256 a = 1;
 *   uint64 b = 2;
 *   int256 c = 3;
 *   a = a.add(int256(b).sub(c)); // `a` becomes 0 as int256
 *   b = a.toUint256().toUint64(); // `b` becomes 0 as uint64
 */
abstract contract UseSafeMath {
    using SafeMath for uint256;
    using SafeMathDivRoundUp for uint256;
    using SafeMath for uint64;
    using SafeMathDivRoundUp for uint64;
    using SafeMath for uint16;
    using SignedSafeMath for int256;
    using SafeCast for uint256;
    using SafeCast for int256;
}

// File: contracts/BondToken_and_GDOTC/math/AdvancedMath.sol


pragma solidity 0.7.1;

abstract contract AdvancedMath {
    /**
     * @dev sqrt(2*PI) * 10^8
     */
    int256 internal constant SQRT_2PI_E8 = 250662827;
    int256 internal constant PI_E8 = 314159265;
    int256 internal constant E_E8 = 271828182;
    int256 internal constant INV_E_E8 = 36787944; // 1/e
    int256 internal constant LOG2_E8 = 30102999;
    int256 internal constant LOG3_E8 = 47712125;

    int256 internal constant p = 23164190;
    int256 internal constant b1 = 31938153;
    int256 internal constant b2 = -35656378;
    int256 internal constant b3 = 178147793;
    int256 internal constant b4 = -182125597;
    int256 internal constant b5 = 133027442;

    /**
     * @dev Calcurate an approximate value of the square root of x by Babylonian method.
     */
    function _sqrt(int256 x) internal pure returns (int256 y) {
        require(x >= 0, "cannot calculate the square root of a negative number");
        int256 z = (x + 1) / 2;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
    }

    /**
     * @dev Returns log(x) for any positive x.
     */
    function _logTaylor(int256 inputE4) internal pure returns (int256 outputE4) {
        require(inputE4 > 1, "input should be positive number");
        int256 inputE8 = inputE4 * 10**4;
        // input x for _logTayler1 is adjusted to 1/e < x < 1.
        while (inputE8 < INV_E_E8) {
            inputE8 = (inputE8 * E_E8) / 10**8;
            outputE4 -= 10**4;
        }
        while (inputE8 > 10**8) {
            inputE8 = (inputE8 * INV_E_E8) / 10**8;
            outputE4 += 10**4;
        }
        outputE4 += _logTaylor1(inputE8 / 10**4 - 10**4);
    }

    /**
     * @notice Calculate an approximate value of the logarithm of input value by
     * Taylor expansion around 1.
     * @dev log(x + 1) = x - 1/2 x^2 + 1/3 x^3 - 1/4 x^4 + 1/5 x^5
     *                     - 1/6 x^6 + 1/7 x^7 - 1/8 x^8 + ...
     */
    function _logTaylor1(int256 inputE4) internal pure returns (int256 outputE4) {
        outputE4 =
            inputE4 -
            inputE4**2 /
            (2 * 10**4) +
            inputE4**3 /
            (3 * 10**8) -
            inputE4**4 /
            (4 * 10**12) +
            inputE4**5 /
            (5 * 10**16) -
            inputE4**6 /
            (6 * 10**20) +
            inputE4**7 /
            (7 * 10**24) -
            inputE4**8 /
            (8 * 10**28);
    }

    /**
     * @notice Calculate the cumulative distribution function of standard normal
     * distribution.
     * @dev Abramowitz and Stegun, Handbook of Mathematical Functions (1964)
     * http://people.math.sfu.ca/~cbm/aands/
     */
    function _calcPnorm(int256 inputE4) internal pure returns (int256 outputE8) {
        require(inputE4 < 440 * 10**4 && inputE4 > -440 * 10**4, "input is too large");
        int256 _inputE4 = inputE4 > 0 ? inputE4 : inputE4 * (-1);
        int256 t = 10**16 / (10**8 + (p * _inputE4) / 10**4);
        int256 X2 = (inputE4 * inputE4) / 2;
        int256 exp2X2 = 10**8 +
            X2 +
            (X2**2 / (2 * 10**8)) +
            (X2**3 / (6 * 10**16)) +
            (X2**4 / (24 * 10**24)) +
            (X2**5 / (120 * 10**32)) +
            (X2**6 / (720 * 10**40));
        int256 Z = (10**24 / exp2X2) / SQRT_2PI_E8;
        int256 y = (b5 * t) / 10**8;
        y = ((y + b4) * t) / 10**8;
        y = ((y + b3) * t) / 10**8;
        y = ((y + b2) * t) / 10**8;
        y = 10**8 - (Z * ((y + b1) * t)) / 10**16;
        return inputE4 > 0 ? y : 10**8 - y;
    }
}

// File: contracts/BondToken_and_GDOTC/bondPricer/GeneralizedPricing.sol


pragma solidity 0.7.1;




/**
 * @dev The decimals of price, point, spotPrice and strikePrice are all the same.
 */
contract GeneralizedPricing is AdvancedMath {
    using SafeMath for uint256;

    /**
     * @dev sqrt(365*86400) * 10^8
     */
    int256 internal constant SQRT_YEAR_E8 = 5615.69229926 * 10**8;

    int256 internal constant MIN_ND1_E8 = 0.0001 * 10**8;
    int256 internal constant MAX_ND1_E8 = 0.9999 * 10**8;
    uint256 internal constant MAX_LEVERAGE_E8 = 1000 * 10**8;

    /**
     * @notice Calculate bond price and leverage by black-scholes formula.
     * @param bondType type of target bond.
     * @param points coodinates of polyline which is needed for price calculation
     * @param untilMaturity Remaining period of target bond in second
     **/
    function calcPriceAndLeverage(
        BondType bondType,
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) public pure returns (uint256 price, uint256 leverageE8) {
        if (bondType == BondType.LBT_SHAPE) {
            (price, leverageE8) = _calcLbtShapePriceAndLeverage(
                points,
                spotPrice,
                volatilityE8,
                untilMaturity
            );
        } else if (bondType == BondType.SBT_SHAPE) {
            (price, leverageE8) = _calcSbtShapePrice(
                points,
                spotPrice,
                volatilityE8,
                untilMaturity
            );
        } else if (bondType == BondType.TRIANGLE) {
            (price, leverageE8) = _calcTrianglePrice(
                points,
                spotPrice,
                volatilityE8,
                untilMaturity
            );
        } else if (bondType == BondType.PURE_SBT) {
            (price, leverageE8) = _calcPureSBTPrice(points, spotPrice, volatilityE8, untilMaturity);
        }
    }

    /**
     * @notice Calculate pure call option price and multiply incline of LBT.
     **/

    function _calcLbtShapePriceAndLeverage(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) internal pure returns (uint256 price, uint256 leverageE8) {
        require(points.length == 3, "3 coordinates is needed for LBT price calculation");
        uint256 inclineE8 = (points[2].mul(10**8)).div(points[1].sub(points[0]));
        (uint256 callOptionPriceE8, int256 nd1E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[0]),
            volatilityE8,
            untilMaturity
        );
        price = (callOptionPriceE8 * inclineE8) / 10**8;
        leverageE8 = _calcLbtLeverage(
            uint256(spotPrice),
            price,
            (nd1E8 * int256(inclineE8)) / 10**8
        );
    }

    /**
     * @notice Calculate (etherPrice - call option price at strike price of SBT).
     **/
    function _calcPureSBTPrice(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) internal pure returns (uint256 price, uint256 leverageE8) {
        require(points.length == 1, "1 coordinate is needed for pure SBT price calculation");
        (uint256 callOptionPrice1, int256 nd1E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[0]),
            volatilityE8,
            untilMaturity
        );
        price = uint256(spotPrice) > callOptionPrice1 ? (uint256(spotPrice) - callOptionPrice1) : 0;
        leverageE8 = _calcLbtLeverage(uint256(spotPrice), price, 10**8 - nd1E8);
    }

    /**
     * @notice Calculate (call option1  - call option2) * incline of SBT.

              ______                 /
             /                      /
            /          =           /        -                   /
    _______/               _______/                 ___________/
    SBT SHAPE BOND         CALL OPTION 1            CALL OPTION 2
     **/
    function _calcSbtShapePrice(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) internal pure returns (uint256 price, uint256 leverageE8) {
        require(points.length == 3, "3 coordinates is needed for SBT price calculation");
        uint256 inclineE8 = (points[2].mul(10**8)).div(points[1].sub(points[0]));
        (uint256 callOptionPrice1, int256 nd11E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[0]),
            volatilityE8,
            untilMaturity
        );
        (uint256 callOptionPrice2, int256 nd12E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[1]),
            volatilityE8,
            untilMaturity
        );
        price = callOptionPrice1 > callOptionPrice2
            ? (inclineE8 * (callOptionPrice1 - callOptionPrice2)) / 10**8
            : 0;
        leverageE8 = _calcLbtLeverage(
            uint256(spotPrice),
            price,
            (int256(inclineE8) * (nd11E8 - nd12E8)) / 10**8
        );
    }

    /**
      * @notice Calculate (call option1 * left incline) - (call option2 * (left incline + right incline)) + (call option3 * right incline).

                                                                   /
                                                                  /
                                                                 /
              /\                            /                    \
             /  \                          /                      \
            /    \            =           /     -                  \          +
    _______/      \________       _______/               _______    \             __________________
                                                                     \                          \
                                                                      \                          \

    **/
    function _calcTrianglePrice(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) internal pure returns (uint256 price, uint256 leverageE8) {
        require(
            points.length == 4,
            "4 coordinates is needed for triangle option price calculation"
        );
        uint256 incline1E8 = (points[2].mul(10**8)).div(points[1].sub(points[0]));
        uint256 incline2E8 = (points[2].mul(10**8)).div(points[3].sub(points[1]));
        (uint256 callOptionPrice1, int256 nd11E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[0]),
            volatilityE8,
            untilMaturity
        );
        (uint256 callOptionPrice2, int256 nd12E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[1]),
            volatilityE8,
            untilMaturity
        );
        (uint256 callOptionPrice3, int256 nd13E8) = calcCallOptionPrice(
            spotPrice,
            int256(points[3]),
            volatilityE8,
            untilMaturity
        );
        int256 nd1E8 = ((nd11E8 * int256(incline1E8)) +
            (nd13E8 * int256(incline2E8)) -
            (int256(incline1E8 + incline2E8) * nd12E8)) / 10**8;

        uint256 price12 = (callOptionPrice1 * incline1E8) + (callOptionPrice3 * incline2E8);
        price = price12 > (incline1E8 + incline2E8) * callOptionPrice2
            ? (price12 - ((incline1E8 + incline2E8) * callOptionPrice2)) / 10**8
            : 0;
        leverageE8 = _calcLbtLeverage(uint256(spotPrice), price, nd1E8);
    }

    /**
     * @dev calcCallOptionPrice() imposes the restrictions of strikePrice, spotPrice, nd1E8 and nd2E8.
     */
    function _calcLbtPrice(
        int256 spotPrice,
        int256 strikePrice,
        int256 nd1E8,
        int256 nd2E8
    ) internal pure returns (int256 lbtPrice) {
        int256 lowestPrice = (spotPrice > strikePrice) ? spotPrice - strikePrice : 0;
        lbtPrice = (spotPrice * nd1E8 - strikePrice * nd2E8) / 10**8;
        if (lbtPrice < lowestPrice) {
            lbtPrice = lowestPrice;
        }
    }

    /**
     * @dev calcCallOptionPrice() imposes the restrictions of spotPrice, lbtPrice and nd1E8.
     */
    function _calcLbtLeverage(
        uint256 spotPrice,
        uint256 lbtPrice,
        int256 nd1E8
    ) internal pure returns (uint256 lbtLeverageE8) {
        int256 modifiedNd1E8 = nd1E8 < MIN_ND1_E8 ? MIN_ND1_E8 : nd1E8 > MAX_ND1_E8
            ? MAX_ND1_E8
            : nd1E8;
        return lbtPrice != 0 ? (uint256(modifiedNd1E8) * spotPrice) / lbtPrice : MAX_LEVERAGE_E8;
    }

    /**
     * @notice Calculate pure call option price and N(d1) by black-scholes formula.
     * @param spotPrice is a oracle price.
     * @param strikePrice Strike price of call option
     * @param volatilityE8 is a oracle volatility.
     * @param untilMaturity Remaining period of target bond in second
     **/
    function calcCallOptionPrice(
        int256 spotPrice,
        int256 strikePrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) public pure returns (uint256 price, int256 nd1E8) {
        require(spotPrice > 0 && spotPrice < 10**13, "oracle price should be between 0 and 10^13");
        require(
            volatilityE8 > 0 && volatilityE8 < 10 * 10**8,
            "oracle volatility should be between 0% and 1000%"
        );
        require(
            untilMaturity > 0 && untilMaturity < 31536000,
            "the bond should not have expired and less than 1 year"
        );
        require(
            strikePrice > 0 && strikePrice < 10**13,
            "strike price should be between 0 and 10^13"
        );

        int256 spotPerStrikeE4 = (spotPrice * 10**4) / strikePrice;
        int256 sigE8 = (volatilityE8 * (_sqrt(untilMaturity)) * (10**8)) / SQRT_YEAR_E8;

        int256 logSigE4 = _logTaylor(spotPerStrikeE4);
        int256 d1E4 = ((logSigE4 * 10**8) / sigE8) + (sigE8 / (2 * 10**4));
        nd1E8 = _calcPnorm(d1E4);

        int256 d2E4 = d1E4 - (sigE8 / 10**4);
        int256 nd2E8 = _calcPnorm(d2E4);
        price = uint256(_calcLbtPrice(spotPrice, strikePrice, nd1E8, nd2E8));
    }
}

// File: contracts/BondToken_and_GDOTC/bondPricer/CustomGeneralizedPricing.sol


pragma solidity 0.7.1;



abstract contract CustomGeneralizedPricing is BondPricerInterface {
    using SafeMath for uint256;

    GeneralizedPricing internal immutable _originalBondPricerAddress;

    constructor(address originalBondPricerAddress) {
        _originalBondPricerAddress = GeneralizedPricing(originalBondPricerAddress);
    }

    function calcPriceAndLeverage(
        BondType bondType,
        uint256[] calldata points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity
    ) external view override returns (uint256 price, uint256 leverageE8) {
        (price, leverageE8) = _originalBondPricerAddress.calcPriceAndLeverage(
            bondType,
            points,
            spotPrice,
            volatilityE8,
            untilMaturity
        );
        if (bondType == BondType.LBT_SHAPE) {
            require(
                _isAcceptableLbt(points, spotPrice, volatilityE8, untilMaturity, price, leverageE8),
                "the liquid bond is not acceptable"
            );
        } else if (bondType == BondType.SBT_SHAPE) {
            require(
                _isAcceptableSbt(points, spotPrice, volatilityE8, untilMaturity, price, leverageE8),
                "the solid bond is not acceptable"
            );
        } else if (bondType == BondType.TRIANGLE) {
            require(
                _isAcceptableTriangleBond(
                    points,
                    spotPrice,
                    volatilityE8,
                    untilMaturity,
                    price,
                    leverageE8
                ),
                "the triangle bond is not acceptable"
            );
        } else if (bondType == BondType.PURE_SBT) {
            require(
                _isAcceptablePureSbt(
                    points,
                    spotPrice,
                    volatilityE8,
                    untilMaturity,
                    price,
                    leverageE8
                ),
                "the pure solid bond is not acceptable"
            );
        } else {
            require(
                _isAcceptableOtherBond(
                    points,
                    spotPrice,
                    volatilityE8,
                    untilMaturity,
                    price,
                    leverageE8
                ),
                "the bond is not acceptable"
            );
        }
    }

    function originalBondPricer() external view returns (address originalBondPricerAddress) {
        originalBondPricerAddress = address(_originalBondPricerAddress);
    }

    function _isAcceptableLbt(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity,
        uint256 bondPrice,
        uint256 bondLeverageE8
    ) internal view virtual returns (bool);

    function _isAcceptableSbt(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity,
        uint256 bondPrice,
        uint256 bondLeverageE8
    ) internal view virtual returns (bool);

    function _isAcceptableTriangleBond(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity,
        uint256 bondPrice,
        uint256 bondLeverageE8
    ) internal view virtual returns (bool);

    function _isAcceptablePureSbt(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity,
        uint256 bondPrice,
        uint256 bondLeverageE8
    ) internal view virtual returns (bool);

    function _isAcceptableOtherBond(
        uint256[] memory points,
        int256 spotPrice,
        int256 volatilityE8,
        int256 untilMaturity,
        uint256 bondPrice,
        uint256 bondLeverageE8
    ) internal view virtual returns (bool);
}

// File: @openzeppelin/contracts/access/Ownable.sol



pragma solidity ^0.7.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// File: contracts/BondToken_and_GDOTC/util/Time.sol


pragma solidity 0.7.1;

abstract contract Time {
    function _getBlockTimestampSec() internal view returns (uint256 unixtimesec) {
        unixtimesec = block.timestamp; // solhint-disable-line not-rely-on-time
    }
}

// File: contracts/contracts/SimpleAggregator/BondPricerWithAcceptableMaturity.sol


pragma solidity 0.7.1;





contract BondPricerWithAcceptableMaturity is CustomGeneralizedPricing, Ownable, Time {
    using SafeMath for uint256;

    uint256 internal _acceptableMaturity;

    event LogUpdateAcceptableMaturity(uint256 acceptableMaturity);

    constructor(address originalBondPricerAddress)
        CustomGeneralizedPricing(originalBondPricerAddress)
    {
        _updateAcceptableMaturity(0);
    }

    function updateAcceptableMaturity(uint256 acceptableMaturity) external onlyOwner {
        _updateAcceptableMaturity(acceptableMaturity);
    }

    function getAcceptableMaturity() external view returns (uint256 acceptableMaturity) {
        acceptableMaturity = _acceptableMaturity;
    }

    function _updateAcceptableMaturity(uint256 acceptableMaturity) internal {
        _acceptableMaturity = acceptableMaturity;
        emit LogUpdateAcceptableMaturity(acceptableMaturity);
    }

    function _isAcceptableLbt(
        uint256[] memory,
        int256 etherPriceE8,
        int256 ethVolatilityE8,
        int256 untilMaturity,
        uint256,
        uint256
    ) internal view override returns (bool) {
        _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity);
        return true;
    }

    function _isAcceptableSbt(
        uint256[] memory,
        int256 etherPriceE8,
        int256 ethVolatilityE8,
        int256 untilMaturity,
        uint256,
        uint256
    ) internal view override returns (bool) {
        _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity);
        return true;
    }

    function _isAcceptableTriangleBond(
        uint256[] memory,
        int256 etherPriceE8,
        int256 ethVolatilityE8,
        int256 untilMaturity,
        uint256,
        uint256
    ) internal view override returns (bool) {
        _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity);
        return true;
    }

    function _isAcceptablePureSbt(
        uint256[] memory,
        int256 etherPriceE8,
        int256 ethVolatilityE8,
        int256 untilMaturity,
        uint256,
        uint256
    ) internal view override returns (bool) {
        _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity);
        return true;
    }

    function _isAcceptableOtherBond(
        uint256[] memory,
        int256,
        int256,
        int256,
        uint256,
        uint256
    ) internal pure override returns (bool) {
        revert("the bond is not pure SBT type");
    }

    /**
     * @notice Add this function to CustomGeneralizedPricing
     * When user sells bond which expired or whose maturity is after the aggregator's maturity, revert the transaction
     */
    function _isAcceptable(
        int256 etherPriceE8,
        int256 ethVolatilityE8,
        int256 untilMaturity
    ) internal view {
        require(
            etherPriceE8 > 0 && etherPriceE8 < 100000 * 10**8,
            "ETH price should be between $0 and $100000"
        );
        require(
            ethVolatilityE8 > 0 && ethVolatilityE8 < 10 * 10**8,
            "ETH volatility should be between 0% and 1000%"
        );
        require(untilMaturity >= 0, "the bond has been expired");
        require(untilMaturity <= 12 weeks, "the bond maturity must be less than 12 weeks");
        require(
            _getBlockTimestampSec().add(uint256(untilMaturity)) <= _acceptableMaturity,
            "the bond maturity must not exceed the current maturity of aggregator"
        );
    }
}

// File: contracts/contracts/Interfaces/BondRegistratorInterface.sol



pragma solidity 0.7.1;


interface BondRegistratorInterface {
    struct Points {
        uint64 x1;
        uint64 y1;
        uint64 x2;
        uint64 y2;
    }

    function getFnMap(Points[] memory points)
        external
        pure
        returns (bytes memory fnMap);

    function registerSBT(
        BondMakerInterface bondMaker,
        uint64 sbtStrikePrice,
        uint64 maturity
    ) external returns (bytes32);

    function registerBondGroup(
        BondMakerInterface bondMaker,
        uint256 callStrikePrice,
        uint64 sbtStrikePrice,
        uint64 maturity,
        bytes32 SBTId
    ) external returns (uint256 bondGroupId);

    function registerBond(
        BondMakerInterface bondMaker,
        Points[] memory points,
        uint256 maturity
    ) external returns (bytes32);
}

// File: contracts/contracts/Interfaces/UseVolatilityOracle.sol


pragma solidity 0.7.1;




contract UseVolatilityOracle {
    using SafeMath for uint256;
    using SafeCast for uint256;
    VolatilityOracleInterface volOracle;

    constructor(VolatilityOracleInterface _volOracle) {
        volOracle = _volOracle;
    }

    function _getVolatility(uint256 maturity) internal view returns (uint256) {
        return volOracle.getVolatility(maturity.sub(block.timestamp).toUint64());
    }
}

// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol



pragma solidity ^0.7.0;




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

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

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

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

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

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

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

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

// File: contracts/contracts/SimpleAggregator/SimpleAggregator.sol


pragma solidity 0.7.1;













abstract contract SimpleAggregator is SimpleAggregatorInterface, UseVolatilityOracle {
    using SafeMath for uint256;
    using SafeCast for uint256;
    using SafeERC20 for ERC20;
    struct ReceivedCollateral {
        uint128 term;
        uint128 value;
    }
    struct UnRemovedToken {
        uint128 term;
        uint128 value;
    }
    struct LiquidationData {
        uint32 endBondGroupId;
        uint32 liquidatedBondGroupID;
        bool isLiquidated;
    }
    struct TermInfo {
        uint64 maturity;
        uint64 strikePrice;
        bytes32 SBTId;
    }
    struct ShareData {
        uint128 totalShare;
        uint128 totalCollateralPerToken;
    }
    struct BalanceData {
        uint128 balance;
        uint64 rewardAmount;
        uint64 term;
    }

    uint256 constant INFINITY = uint256(-1);
    uint256 constant COOLTIME = 3600 * 24 * 3;
    SimpleStrategyInterface internal immutable STRATEGY;
    ExchangeInterface internal immutable DOTC;
    ERC20 internal immutable REWARD_TOKEN;
    BondPricerWithAcceptableMaturity internal immutable BOND_PRICER;
    LatestPriceOracleInterface internal immutable ORACLE;
    BondMakerInterface internal immutable BONDMAKER;
    BondRegistratorInterface internal immutable BOND_REGISTRATOR;
    address internal immutable OWNER;
    bool internal immutable REVERSE_ORACLE;
    int16 internal constant MAX_SUPPLY_DENUMERATOR = 8;
    uint64 internal immutable BASE_PRICE_UNIT;

    mapping(uint256 => TermInfo) internal termInfo;

    mapping(uint256 => uint256[]) internal issuableBondGroupIds;
    mapping(uint256 => mapping(uint256 => uint256)) internal strikePriceToBondGroup;

    TotalReward[] internal totalRewards;
    // Aggregator Status
    mapping(uint256 => LiquidationData) internal liquidationData;
    mapping(uint256 => ShareData) internal shareData;
    uint256 internal currentTerm;
    uint64 internal priceUnit;
    uint64 internal lastTrancheTime;
    uint32 internal startBondGroupId = 1;
    int16 internal currentFeeBase;
    bool internal isTotalSupplyDanger;

    mapping(address => ReceivedCollateral) internal receivedCollaterals;
    mapping(address => UnRemovedToken) internal unremovedTokens;
    mapping(address => BalanceData) internal balance;
    mapping(address => mapping(address => uint128)) internal allowances;

    uint8 public constant override decimals = 8;
    string public constant override symbol = "LASH";
    string public constant override name = "LIEN_AGGREGATOR_SHARE";

    mapping(uint256 => uint128) internal totalReceivedCollateral;
    mapping(uint256 => uint128) internal totalUnremovedTokens;

    event Transfer(address indexed from, address indexed to, uint256 value);

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

    event SetAddLiquidity(address indexed user, uint256 indexed term, uint256 collateralAmount);

    event SetRemoveLiquidity(address indexed user, uint256 indexed term, uint256 tokenAmount);

    event SettleLiquidity(
        address indexed user,
        uint256 indexed term,
        uint256 collateralAmount,
        uint256 tokenAmount
    );

    event TrancheBond(
        uint64 indexed issueBondGroupId,
        uint64 issueAmount,
        uint64 indexed burnBondGroupId,
        uint64 burnAmount
    );

    event UpdateMaturity(uint64 indexed term, int16 newFeeBase, uint64 maturity);

    event AddLiquidity(address indexed user, uint256 tokenAmount);

    modifier isActive() {
        require(block.timestamp <= termInfo[currentTerm].maturity, "Not active");
        _;
    }

    modifier endCoolTime() {
        require(block.timestamp > lastTrancheTime + COOLTIME, "Cool Time");
        _;
    }

    modifier afterMaturity() {
        require(block.timestamp > termInfo[currentTerm].maturity, "Not Matured");
        _;
    }

    modifier isRunning() {
        require(currentTerm != 0, "Not running");
        _;
    }

    // When collateralPerToken becomes very small value, total supply of share token can overflow
    modifier isSafeSupply() {
        require(!isTotalSupplyDanger, "Unsafe supply");
        _;
    }

    modifier onlyBonusProvider() {
        require(msg.sender == OWNER, "Only provider");
        _;
    }

    constructor(
        LatestPriceOracleInterface _oracle,
        BondPricerWithAcceptableMaturity _pricer,
        SimpleStrategyInterface _strategy,
        ERC20 _rewardToken,
        BondRegistratorInterface _registrator,
        ExchangeInterface _exchangeAddress,
        uint64 _priceUnit,
        uint64 _firstRewardRate,
        bool _reverseOracle,
        VolatilityOracleInterface _volOracle
    ) UseVolatilityOracle(_volOracle) {
        BONDMAKER = _exchangeAddress.bondMakerAddress();
        BOND_PRICER = _pricer;
        ORACLE = _oracle;
        BASE_PRICE_UNIT = _priceUnit;
        REVERSE_ORACLE = _reverseOracle;
        REWARD_TOKEN = _rewardToken;
        BOND_REGISTRATOR = _registrator;
        DOTC = _exchangeAddress;

        STRATEGY = _strategy;

        totalRewards.push(TotalReward(1, _firstRewardRate));
        priceUnit = _priceUnit;
        OWNER = msg.sender;
        require(
            _firstRewardRate >= 10**decimals && _firstRewardRate <= 1000000 * 10**decimals,
            "Out of range"
        );
    }

    /**
     * @notice Update maturity and strike price of SBT
     * Then, determine total amount of collateral asset and totalSupply of share token
     * Collateral asset to be withdrawn in `settleTokens()` is sent for reserve contract
     */
    function renewMaturity() public override {
        uint256 totalUnsentTokens;
        uint256 collateralPerTokenE8;
        uint256 _currentTerm = currentTerm;
        uint256 currentUnremoved = totalUnremovedTokens[_currentTerm];
        require(liquidationData[_currentTerm].isLiquidated || _currentTerm == 0, "Not expired yet");
        uint256 totalShare = shareData[_currentTerm].totalShare;
        if (totalShare > 0) {
            uint256 collateralAmount = getCollateralAmount();
            collateralPerTokenE8 = _applyDecimalGap(
                collateralAmount.mul(10**decimals).div(totalShare),
                true
            );
            totalUnsentTokens = _applyDecimalGap(
                uint256(totalReceivedCollateral[_currentTerm]).mul(10**decimals) /
                    collateralPerTokenE8,
                true
            );
        } else if (totalReceivedCollateral[_currentTerm] > 0) {
            totalUnsentTokens = _applyDecimalGap(totalReceivedCollateral[_currentTerm], true);
            collateralPerTokenE8 = 10**decimals;
        }

        uint256 _totalSupply = totalShare + totalUnsentTokens;
        shareData[_currentTerm + 1].totalCollateralPerToken = collateralPerTokenE8.toUint128();
        shareData[_currentTerm + 1].totalShare = uint256(totalShare)
            .add(totalUnsentTokens)
            .sub(currentUnremoved)
            .toUint128();

        if (
            shareData[_currentTerm + 1].totalShare >
            uint128(-1) / 10**uint128(MAX_SUPPLY_DENUMERATOR)
        ) {
            isTotalSupplyDanger = true;
        }

        if (_currentTerm != 0) {
            _updateFeeBase();
        }

        if (_totalSupply > 0 && currentUnremoved > 0) {
            _reserveAsset(collateralPerTokenE8);
        }
        _updateBondGroupData();

        emit UpdateMaturity(currentTerm.toUint64(), currentFeeBase, termInfo[currentTerm].maturity);
    }

    /**
     * @notice Update total reward token amount for one term
     * Only owner can call this function
     * @param rewardRate is restricted from 10**8 (1 LIEN) to 10**14 (total supply of Lien token)
     */
    function updateTotalReward(uint64 rewardRate) public onlyBonusProvider isRunning {
        require(rewardRate >= 10**decimals && rewardRate <= 1000000 * 10**decimals, "Out of range");
        totalRewards.push(TotalReward(currentTerm.toUint64() + 1, rewardRate));
    }

    function _updateBondGroupData() internal {
        uint256 nextTimeStamp = STRATEGY.calcNextMaturity();
        uint256 currentPriceE8 = ORACLE.latestPrice();
        uint256 currentStrikePrice = STRATEGY.getCurrentStrikePrice(
            currentPriceE8,
            priceUnit,
            REVERSE_ORACLE
        );

        _updatePriceUnit(currentPriceE8);

        // Register SBT for next term
        bytes32 SBTId = BOND_REGISTRATOR.registerSBT(
            BONDMAKER,
            currentStrikePrice.toUint64(),
            nextTimeStamp.toUint64()
        );
        (address sbtAddress, , , ) = BONDMAKER.getBond(SBTId);
        IERC20(sbtAddress).approve(address(DOTC), INFINITY);

        currentTerm += 1;
        TermInfo memory newTermInfo = TermInfo(
            nextTimeStamp.toUint64(),
            currentStrikePrice.toUint64(),
            SBTId
        );
        termInfo[currentTerm] = newTermInfo;
        BOND_PRICER.updateAcceptableMaturity(nextTimeStamp);
    }

    function _addLiquidity(uint256 amount) internal returns (bool success) {
        (, uint256 unsentToken, uint256 addLiquidityTerm) = _settleTokens();
        _updateBalanceDataForLiquidityMove(msg.sender, unsentToken, 0, addLiquidityTerm);
        uint256 _currentTerm = currentTerm;
        if (receivedCollaterals[msg.sender].value == 0) {
            receivedCollaterals[msg.sender].term = uint128(_currentTerm);
        }
        receivedCollaterals[msg.sender].value += amount.toUint128();
        totalReceivedCollateral[_currentTerm] += amount.toUint128();
        emit SetAddLiquidity(msg.sender, _currentTerm, amount);
        return true;
    }

    /**
     * @notice Make a reservation for removing liquidity
     * Collateral asset can be withdrawn from next term
     * Share token to be removed is burned at this point
     * Before remove liquidity, run _settleTokens()
     */

    function removeLiquidity(uint128 amount) external override returns (bool success) {
        (, uint256 unsentToken, uint256 addLiquidityTerm) = _settleTokens();
        uint256 _currentTerm = currentTerm;
        if (unremovedTokens[msg.sender].value == 0) {
            unremovedTokens[msg.sender].term = uint128(_currentTerm);
        }
        unremovedTokens[msg.sender].value += amount;
        totalUnremovedTokens[_currentTerm] += amount;
        _updateBalanceDataForLiquidityMove(msg.sender, unsentToken, amount, addLiquidityTerm);
        emit SetRemoveLiquidity(msg.sender, _currentTerm, amount);
        return true;
    }

    function _settleTokens()
        internal
        returns (
            uint256 unsentETH,
            uint256 unsentToken,
            uint256 addLiquidityTerm
        )
    {
        uint256 _currentTerm = currentTerm;
        uint128 lastRemoveLiquidityTerm = unremovedTokens[msg.sender].term;
        uint128 lastRemoveLiquidityValue = unremovedTokens[msg.sender].value;
        uint128 lastAddLiquidityTerm = receivedCollaterals[msg.sender].term;
        uint128 lastAddLiquidityValue = receivedCollaterals[msg.sender].value;
        if (_currentTerm == 0) {
            return (0, 0, 0);
        }

        if (lastRemoveLiquidityValue != 0 && _currentTerm > lastRemoveLiquidityTerm) {
            unsentETH = _applyDecimalGap(
                uint256(lastRemoveLiquidityValue)
                    .mul(shareData[uint256(lastRemoveLiquidityTerm + 1)].totalCollateralPerToken)
                    .div(10**decimals),
                false
            );
            if (unsentETH > 0) {
                _sendTokens(msg.sender, unsentETH);
            }
            delete unremovedTokens[msg.sender];
        }

        if (lastAddLiquidityValue != 0 && _currentTerm > lastAddLiquidityTerm) {
            unsentToken = _applyDecimalGap(
                uint256(lastAddLiquidityValue).mul(10**decimals).div(
                    uint256(shareData[lastAddLiquidityTerm + 1].totalCollateralPerToken)
                ),
                true
            );
            addLiquidityTerm = lastAddLiquidityTerm;
            delete receivedCollaterals[msg.sender];
        }
        emit SettleLiquidity(msg.sender, _currentTerm, unsentETH, unsentToken);
    }

    /**
     * @notice Increment share token for addLiquidity data
     * Transfer collateral asset for remove liquidity data
     */
    function settleTokens() external override returns (uint256 unsentETH, uint256 unsentToken) {
        uint256 addLiquidityTerm;
        (unsentETH, unsentToken, addLiquidityTerm) = _settleTokens();
        _updateBalanceDataForLiquidityMove(msg.sender, unsentToken, 0, addLiquidityTerm);
    }

    /**
     * @notice Update `startBondGroupId` to run `liquidateBonds()` more efficiently
     * All bond groups before `startBondGroupId` has expired before maturity of previous term
     */
    function updateStartBondGroupId() external override isRunning {
        uint32 _startBondGroupId = startBondGroupId;
        uint64 previousMaturity = termInfo[currentTerm - 1].maturity;
        require(previousMaturity != 0, "Maturity shoudld exist");
        while (true) {
            (, uint256 maturity) = BONDMAKER.getBondGroup(_startBondGroupId);
            if (maturity >= previousMaturity) {
                startBondGroupId = _startBondGroupId;
                return;
            }
            _startBondGroupId += 1;
        }
    }

    /**
     * @notice Liquidate and burn all bonds in this aggregator
     * Aggregator can search for 50 bondGroup and burn 10 bonds one time
     */
    function liquidateBonds() public override afterMaturity {
        uint256 _currentTerm = currentTerm;
        require(!liquidationData[_currentTerm].isLiquidated, "Expired");
        if (liquidationData[_currentTerm].endBondGroupId == 0) {
            liquidationData[_currentTerm].endBondGroupId = BONDMAKER.nextBondGroupID().toUint32();
        }
        // ToDo: Register least bond group ID
        uint32 endIndex;
        uint32 startIndex;
        uint32 liquidateBondNumber;
        uint64 maturity = termInfo[_currentTerm].maturity;
        uint64 previousMaturity = termInfo[_currentTerm - 1].maturity;
        {
            uint256 ethAllowance = DOTC.ethAllowance(address(this));
            if (ethAllowance > 0) {
                DOTC.withdrawEth();
            }
        }

        if (liquidationData[_currentTerm].liquidatedBondGroupID == 0) {
            startIndex = startBondGroupId;
        } else {
            startIndex = liquidationData[_currentTerm].liquidatedBondGroupID;
        }

        if (liquidationData[_currentTerm].endBondGroupId - startIndex > 50) {
            endIndex = startIndex + 50;
            liquidationData[_currentTerm].liquidatedBondGroupID = endIndex;
        } else {
            endIndex = liquidationData[_currentTerm].endBondGroupId;
        }

        for (uint256 i = startIndex; i < endIndex; i++) {
            liquidateBondNumber = _liquidateBondGroup(
                i,
                liquidateBondNumber,
                maturity,
                previousMaturity
            );

            if (liquidateBondNumber > 9) {
                if (i == endIndex - 1) {
                    liquidationData[_currentTerm].isLiquidated = true;
                } else {
                    liquidationData[_currentTerm].liquidatedBondGroupID = uint32(i + 1);
                }
                return;
            }
        }

        if (endIndex == liquidationData[_currentTerm].endBondGroupId) {
            liquidationData[_currentTerm].isLiquidated = true;
        } else {
            liquidationData[_currentTerm].liquidatedBondGroupID = endIndex;
        }
    }

    function addSuitableBondGroup() external override isActive returns (uint256 bondGroupID) {
        uint256 currentPriceE8 = ORACLE.latestPrice();
        return _addSuitableBondGroup(currentPriceE8);
    }

    /**
     * @notice Can not tranche bonds for 3 days from last execution of this function
     */
    function trancheBonds() external override isActive endCoolTime {
        uint256 currentPriceE8 = ORACLE.latestPrice();
        uint256 bondGroupId = _getSuitableBondGroup(currentPriceE8);
        if (bondGroupId == 0) {
            bondGroupId = _addSuitableBondGroup(currentPriceE8);
        }

        (uint256 amount, uint256 ethAmount, uint256[2] memory reverseBonds) = STRATEGY
            .getTrancheBonds(
            BONDMAKER,
            address(this),
            bondGroupId,
            currentPriceE8,
            issuableBondGroupIds[currentTerm],
            priceUnit,
            REVERSE_ORACLE
        );

        if (ethAmount > 0) {
            DOTC.depositEth{value: ethAmount}();
        }

        if (amount > 0) {
            _issueBonds(bondGroupId, amount);
        }

        if (reverseBonds[1] > 0) {
            // Burn bond and get collateral asset
            require(
                BONDMAKER.reverseBondGroupToCollateral(reverseBonds[0], reverseBonds[1]),
                "Reverse"
            );
        }
        lastTrancheTime = block.timestamp.toUint64();
        emit TrancheBond(
            uint64(bondGroupId),
            uint64(amount),
            uint64(reverseBonds[0]),
            uint64(reverseBonds[1])
        );
    }

    function _burnBond(
        uint256 bondGroupId,
        address bondAddress,
        uint32 liquidateBondNumber,
        bool isLiquidated
    ) internal returns (uint32, bool) {
        BondTokenInterface bond = BondTokenInterface(bondAddress);
        if (bond.balanceOf(address(this)) > 0) {
            if (!isLiquidated) {
                // If this bond group is not liquidated in _liquidateBondGroup, try liquidate
                // BondMaker contract does not revert even if someone else calls 'BONDMAKER.liquidateBond()'
                BONDMAKER.liquidateBond(bondGroupId, 0);
                isLiquidated = true;
            }
            bond.burnAll();
            liquidateBondNumber += 1;
        }
        return (liquidateBondNumber, isLiquidated);
    }

    function _liquidateBondGroup(
        uint256 bondGroupId,
        uint32 liquidateBondNumber,
        uint64 maturity,
        uint64 previousMaturity
    ) internal returns (uint32) {
        (bytes32[] memory bondIds, uint256 _maturity) = BONDMAKER.getBondGroup(bondGroupId);
        if (_maturity > maturity || (_maturity < previousMaturity && previousMaturity != 0)) {
            return liquidateBondNumber;
        }
        bool isLiquidated;
        for (uint256 i = 0; i < bondIds.length; i++) {
            (address bondAddress, , , ) = BONDMAKER.getBond(bondIds[i]);
            (liquidateBondNumber, isLiquidated) = _burnBond(
                bondGroupId,
                bondAddress,
                liquidateBondNumber,
                isLiquidated
            );
        }
        return liquidateBondNumber;
    }

    function _getSuitableBondGroup(uint256 currentPriceE8) internal view returns (uint256) {
        uint256 roundedPrice = STRATEGY.calcRoundPrice(currentPriceE8, priceUnit, 1);


            mapping(uint256 => uint256) storage priceToGroupBondId
         = strikePriceToBondGroup[currentTerm];
        if (priceToGroupBondId[roundedPrice] != 0) {
            return priceToGroupBondId[roundedPrice];
        }
        // Suitable bond range is in between current price +- 2 * priceUnit
        for (uint256 i = 1; i <= 2; i++) {
            if (priceToGroupBondId[roundedPrice - priceUnit * i] != 0) {
                return priceToGroupBondId[roundedPrice - priceUnit * i];
            }

            if (priceToGroupBondId[roundedPrice + priceUnit * i] != 0) {
                return priceToGroupBondId[roundedPrice + priceUnit * i];
            }
        }
    }

    function _addSuitableBondGroup(uint256 currentPriceE8) internal returns (uint256 bondGroupID) {
        uint256 callStrikePrice = STRATEGY.calcCallStrikePrice(
            currentPriceE8,
            priceUnit,
            REVERSE_ORACLE
        );
        uint256 _currentTerm = currentTerm;
        TermInfo memory info = termInfo[_currentTerm];
        callStrikePrice = _adjustPrice(info.strikePrice, callStrikePrice);
        bondGroupID = BOND_REGISTRATOR.registerBondGroup(
            BONDMAKER,
            callStrikePrice,
            info.strikePrice,
            info.maturity,
            info.SBTId
        );
        // If reverse oracle is set to aggregator, make Collateral/USD price
        if (REVERSE_ORACLE) {
            _addBondGroup(
                bondGroupID,
                STRATEGY.calcCallStrikePrice(currentPriceE8, priceUnit, false)
            );
        } else {
            _addBondGroup(bondGroupID, callStrikePrice);
        }
    }

    function _addBondGroup(uint256 bondGroupId, uint256 callStrikePriceInEthUSD) internal {
        // Register bond group info
        issuableBondGroupIds[currentTerm].push(bondGroupId);
        strikePriceToBondGroup[currentTerm][callStrikePriceInEthUSD] = bondGroupId;

        (bytes32[] memory bondIDs, ) = BONDMAKER.getBondGroup(bondGroupId);
        (address bondType1Address, , , ) = BONDMAKER.getBond(bondIDs[1]);

        // Infinite approve if no approval
        if (IERC20(bondType1Address).allowance(address(this), address(DOTC)) == 0) {
            IERC20(bondType1Address).approve(address(DOTC), INFINITY);
        }

        (address bondType2Address, , , ) = BONDMAKER.getBond(bondIDs[2]);

        if (IERC20(bondType2Address).allowance(address(this), address(DOTC)) == 0) {
            IERC20(bondType2Address).approve(address(DOTC), INFINITY);
        }
        (address bondType3Address, , , ) = BONDMAKER.getBond(bondIDs[3]);
        if (IERC20(bondType3Address).allowance(address(this), address(DOTC)) == 0) {
            IERC20(bondType3Address).approve(address(DOTC), INFINITY);
        }
    }

    function _updatePriceUnit(uint256 currentPriceE8) internal {
        uint256 multiplyer = currentPriceE8.div(50 * BASE_PRICE_UNIT);
        if (multiplyer == 0) {
            priceUnit = BASE_PRICE_UNIT;
        } else {
            priceUnit = ((25 * multiplyer * BASE_PRICE_UNIT) / 10).toUint64();
        }
    }

    function _updateFeeBase() internal {
        STRATEGY.registerCurrentFeeBase(
            currentFeeBase,
            shareData[currentTerm].totalCollateralPerToken,
            shareData[currentTerm + 1].totalCollateralPerToken,
            OWNER,
            address(ORACLE),
            REVERSE_ORACLE
        );
        changeSpread();
    }

    /**
     * @dev When sbtStrikePrice and callStrikePrice have different remainder of 2,
     * decrease callStrikePrice by 1 to avoid invalid line segment for register new bond
     */
    function _adjustPrice(uint64 sbtStrikePrice, uint256 callStrikePrice)
        internal
        pure
        returns (uint256)
    {
        return callStrikePrice.sub(callStrikePrice.sub(sbtStrikePrice) % 2);
    }

    function changeSpread() public virtual override {}

    function _sendTokens(address user, uint256 amount) internal virtual {}

    function _reserveAsset(uint256 reserveAmountRatioE8) internal virtual {}

    function _issueBonds(uint256 bondgroupID, uint256 amount) internal virtual {}

    function getCollateralAddress() external view virtual override returns (address) {}

    function _applyDecimalGap(uint256 amount, bool isDiv) internal view virtual returns (uint256) {}

    function getCollateralDecimal() external view virtual override returns (int16) {}

    function getReserveAddress() external view virtual returns (address) {}

    function getCollateralAmount() public view virtual override returns (uint256) {}

    // Reward functions
    /**
     * @dev Update reward amount, then update balance
     */
    function _updateBalanceData(address owner, int256 amount) internal {
        BalanceData memory balanceData = balance[owner];
        balanceData.rewardAmount = _calcNextReward(balanceData, currentTerm);
        balanceData.term = uint64(currentTerm);
        if (amount < 0) {
            balanceData.balance = uint256(balanceData.balance)
                .sub(uint256(amount * -1))
                .toUint128();
        } else {
            balanceData.balance = uint256(balanceData.balance).add(uint256(amount)).toUint128();
        }
        balance[owner] = balanceData;
    }

    function _updateBalanceDataForLiquidityMove(
        address owner,
        uint256 addAmount,
        uint256 removeAmount,
        uint256 term
    ) internal {
        BalanceData memory balanceData = balance[owner];
        // Update reward amount before addliquidity
        if (addAmount != 0) {
            balanceData.rewardAmount = _calcNextReward(balanceData, term);
            balanceData.term = uint64(term);
            balanceData.balance = balanceData.balance = uint256(balanceData.balance)
                .add(uint256(addAmount))
                .toUint128();
        }
        // Update reward amount after addliquidity
        balanceData.rewardAmount = _calcNextReward(balanceData, currentTerm);
        balanceData.term = uint64(currentTerm);
        // Update balance if remove liquidity
        if (removeAmount != 0) {
            balanceData.balance = uint256(balanceData.balance).sub(removeAmount).toUint128();
        }
        balance[owner] = balanceData;
    }

    /**
     * @dev This function is called before change balance of share token
     * @param term Reward amount is calculated from next term after this function is called to  term `term`
     */
    function _calcNextReward(BalanceData memory balanceData, uint256 term)
        internal
        view
        returns (uint64 rewardAmount)
    {
        rewardAmount = balanceData.rewardAmount;
        if (balanceData.balance > 0 && balanceData.term < term) {
            uint64 index = uint64(totalRewards.length - 1);
            uint64 referenceTerm = totalRewards[index].term;
            uint64 rewardTotal = totalRewards[index].value;

            for (uint256 i = term; i > balanceData.term; i--) {
                if (i < referenceTerm) {
                    // If i is smaller than the term in which total reward amount is changed, update total reward amount
                    index -= 1;
                    rewardTotal = totalRewards[index].value;
                    referenceTerm = totalRewards[index].term;
                }
                // Reward amount is calculated by `total reward amount * user balance / total share`
                rewardAmount = uint256(rewardAmount)
                    .add(
                    (uint256(rewardTotal).mul(balanceData.balance)).div(shareData[i].totalShare)
                )
                    .toUint64();
            }
        }
    }

    /**
     * @notice update reward amount and transfer reward token, then change reward amount to 0
     */
    function claimReward() public override {
        BalanceData memory userData = balance[msg.sender];
        userData.rewardAmount = _calcNextReward(userData, currentTerm);
        userData.term = uint64(currentTerm);
        require(userData.rewardAmount > 0, "No Reward");
        uint256 rewardAmount = userData.rewardAmount;
        userData.rewardAmount = 0;
        balance[msg.sender] = userData;
        REWARD_TOKEN.safeTransfer(msg.sender, rewardAmount);
    }

    // ERC20 functions

    /**
     * @param amount If this value is uint256(-1) infinite approve
     */
    function approve(address spender, uint256 amount) external override returns (bool) {
        if (amount == uint256(-1)) {
            amount = uint128(-1);
        }
        allowances[msg.sender][spender] = amount.toUint128();
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function transfer(address recipient, uint256 amount) external override returns (bool) {
        return _transferToken(msg.sender, recipient, amount.toUint128());
    }

    /**
     * @notice If allowance amount is uint128(-1), allowance amount is not updated
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external override returns (bool) {
        uint128 currentAllowance = allowances[sender][msg.sender];
        if (currentAllowance < amount) {
            return false;
        }
        // Skip if infinity approve
        if (currentAllowance != uint128(-1)) {
            allowances[sender][msg.sender] = uint256(allowances[sender][msg.sender])
                .sub(amount)
                .toUint128();
        }
        _transferToken(sender, recipient, amount.toUint128());
        return true;
    }

    /**
     * @dev Balance is changed by `_updateBalanceData` to reflect correct reward amount
     */
    function _transferToken(
        address from,
        address to,
        uint128 amount
    ) internal returns (bool) {
        if (balance[from].balance < amount) {
            return false;
        }
        _updateBalanceData(from, -1 * int256(amount));
        _updateBalanceData(to, int256(amount));
        emit Transfer(from, to, uint256(amount));
        return true;
    }

    function balanceOf(address user) public view override returns (uint256) {
        return balance[user].balance;
    }

    function totalSupply() public view override returns (uint256) {
        return uint256(shareData[currentTerm].totalShare).sub(totalUnremovedTokens[currentTerm]);
    }

    function getLiquidityReservationData(address user)
        public
        view
        returns (
            uint128 receivedCollateralTerm,
            uint128 receivedCollateralAmount,
            uint128 removeTokenTerm,
            uint128 removeTokenAmount
        )
    {
        return (
            receivedCollaterals[user].term,
            receivedCollaterals[user].value,
            unremovedTokens[user].term,
            unremovedTokens[user].value
        );
    }

    function getCurrentStatus()
        public
        view
        override
        returns (
            uint256 term,
            int16 feeBase,
            uint32 uncheckbondGroupId,
            uint64 unit,
            uint64 trancheTime,
            bool isDanger
        )
    {
        return (
            currentTerm,
            currentFeeBase,
            startBondGroupId,
            priceUnit,
            lastTrancheTime,
            isTotalSupplyDanger
        );
    }

    function getLiquidationData(uint256 term)
        public
        view
        override
        returns (
            bool isLiquidated,
            uint32 liquidatedBondGroupID,
            uint32 endBondGroupId
        )
    {
        if (term == 0) {
            term = currentTerm;
        }
        isLiquidated = liquidationData[term].isLiquidated;
        liquidatedBondGroupID = liquidationData[term].liquidatedBondGroupID;
        endBondGroupId = liquidationData[term].endBondGroupId;
    }

    function totalShareData(uint256 term)
        public
        view
        override
        returns (uint128 totalShare, uint128 totalCollateralPerToken)
    {
        if (term == 0) {
            term = currentTerm;
        }
        return (shareData[term].totalShare, shareData[term].totalCollateralPerToken);
    }

    function getBondGroupIDFromTermAndPrice(uint256 term, uint256 price)
        public
        view
        override
        returns (uint256 bondGroupID)
    {
        price = STRATEGY.calcRoundPrice(price, priceUnit, 1);

        if (term == 0) {
            term = currentTerm;
        }
        return strikePriceToBondGroup[term][price];
    }

    function getInfo()
        public
        view
        override
        returns (
            address bondMaker,
            address strategy,
            address dotc,
            address bondPricerAddress,
            address oracleAddress,
            address rewardTokenAddress,
            address registratorAddress,
            address owner,
            bool reverseOracle,
            uint64 basePriceUnit,
            uint128 maxSupply
        )
    {
        return (
            address(BONDMAKER),
            address(STRATEGY),
            address(DOTC),
            address(BOND_PRICER),
            address(ORACLE),
            address(REWARD_TOKEN),
            address(BOND_REGISTRATOR),
            OWNER,
            REVERSE_ORACLE,
            BASE_PRICE_UNIT,
            uint128(uint128(-1) / (10**uint256(MAX_SUPPLY_DENUMERATOR)))
        );
    }

    function getTermInfo(uint256 term)
        public
        view
        override
        returns (
            uint64 maturity,
            uint64 solidStrikePrice,
            bytes32 SBTID
        )
    {
        if (term == 0) {
            term = currentTerm;
        }
        return (termInfo[term].maturity, termInfo[term].strikePrice, termInfo[term].SBTId);
    }

    /**
     * @notice return user's balance including unsettled share token
     */
    function getExpectedBalance(address user, bool hasReservation)
        external
        view
        override
        returns (uint256 expectedBalance)
    {
        expectedBalance = balance[user].balance;
        if (receivedCollaterals[user].value != 0) {
            hasReservation = true;
            if (currentTerm > receivedCollaterals[msg.sender].term) {
                expectedBalance += _applyDecimalGap(
                    uint256(receivedCollaterals[msg.sender].value).mul(10**decimals).div(
                        uint256(
                            shareData[receivedCollaterals[msg.sender].term + 1]
                                .totalCollateralPerToken
                        )
                    ),
                    true
                );
            }
        }
    }

    /**
     * @notice Return current phase of aggregator
     */
    function getCurrentPhase() public view override returns (AggregatorPhase) {
        if (currentTerm == 0) {
            return AggregatorPhase.BEFORE_START;
        } else if (block.timestamp <= termInfo[currentTerm].maturity) {
            if (block.timestamp <= lastTrancheTime + COOLTIME) {
                return AggregatorPhase.COOL_TIME;
            }
            return AggregatorPhase.ACTIVE;
        } else if (
            block.timestamp > termInfo[currentTerm].maturity &&
            !liquidationData[currentTerm].isLiquidated
        ) {
            return AggregatorPhase.AFTER_MATURITY;
        }
        return AggregatorPhase.EXPIRED;
    }

    /**
     * @notice Calculate expected reward amount at this point
     */
    function getRewardAmount(address user) public view override returns (uint64) {
        return _calcNextReward(balance[user], currentTerm);
    }

    function getTotalRewards() public view override returns (TotalReward[] memory) {
        return totalRewards;
    }

    function isTotalSupplySafe() public view override returns (bool) {
        return !isTotalSupplyDanger;
    }

    function getTotalUnmovedAssets() public view override returns (uint256, uint256) {
        return (totalReceivedCollateral[currentTerm], totalUnremovedTokens[currentTerm]);
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return allowances[owner][spender];
    }

    function getCollateralPerToken(uint256 term) public view override returns (uint256) {
        return shareData[term].totalCollateralPerToken;
    }

    function getBondGroupIdFromStrikePrice(uint256 term, uint256 strikePrice)
        public
        view
        override
        returns (uint256)
    {
        return strikePriceToBondGroup[term][strikePrice];
    }

    function getBalanceData(address user)
        external
        view
        override
        returns (
            uint128 amount,
            uint64 term,
            uint64 rewardAmount
        )
    {
        return (balance[user].balance, balance[user].term, balance[user].rewardAmount);
    }

    /**
     * @notice Get suitable bond groups for current price
     */
    function getIssuableBondGroups() public view override returns (uint256[] memory) {
        return issuableBondGroupIds[currentTerm];
    }
}

// File: contracts/BondToken_and_GDOTC/bondMaker/BondMakerCollateralizedEthInterface.sol


pragma solidity 0.7.1;


interface BondMakerCollateralizedEthInterface is BondMakerInterface {
    function issueNewBonds(uint256 bondGroupID) external payable returns (uint256 amount);
}

// File: contracts/BondToken_and_GDOTC/util/TransferETH.sol


pragma solidity 0.7.1;


abstract contract TransferETH is TransferETHInterface {
    receive() external payable override {
        emit LogTransferETH(msg.sender, address(this), msg.value);
    }

    function _hasSufficientBalance(uint256 amount) internal view returns (bool ok) {
        address thisContract = address(this);
        return amount <= thisContract.balance;
    }

    /**
     * @notice transfer `amount` ETH to the `recipient` account with emitting log
     */
    function _transferETH(
        address payable recipient,
        uint256 amount,
        string memory errorMessage
    ) internal {
        require(_hasSufficientBalance(amount), errorMessage);
        (bool success, ) = recipient.call{value: amount}(""); // solhint-disable-line avoid-low-level-calls
        require(success, "transferring Ether failed");
        emit LogTransferETH(address(this), recipient, amount);
    }

    function _transferETH(address payable recipient, uint256 amount) internal {
        _transferETH(recipient, amount, "TransferETH: transfer amount exceeds balance");
    }
}

// File: contracts/contracts/SimpleAggregator/ReserveETH.sol


pragma solidity 0.7.1;


contract ReserveEth is TransferETH {
    address owner;
    modifier onlyOwner() {
        require(msg.sender == owner, "Error: Only owner can execute this function");
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    /**
     * @notice Send ETH to user
     * Only aggregator can call this function
     */
    function sendAsset(address payable user, uint256 amount) public onlyOwner {
        _transferETH(user, amount);
    }
}

// File: contracts/contracts/SimpleAggregator/SimpleAggregatorCollateralizedEth.sol


pragma solidity 0.7.1;






contract SimpleAggregatorCollateralizedEth is SimpleAggregator, TransferETH {
    using SafeMath for uint256;
    ReserveEth internal immutable reserveEth;
    uint16 internal constant DECIMAL_GAP = 10;

    constructor(
        LatestPriceOracleInterface _ethOracle,
        BondPricerWithAcceptableMaturity _pricer,
        SimpleStrategyInterface strategy,
        ERC20 _rewardToken,
        BondRegistratorInterface _registrator,
        ExchangeInterface exchangeAddress,
        VolatilityOracleInterface _volOracle,
        uint64 _priceUnit,
        uint64 _firstRewardRate
    )
        SimpleAggregator(
            _ethOracle,
            _pricer,
            strategy,
            _rewardToken,
            _registrator,
            exchangeAddress,
            _priceUnit,
            _firstRewardRate,
            false,
            _volOracle
        )
    {
        BondMakerInterface _bondMaker = exchangeAddress.bondMakerAddress();
        int16 feeBaseE4 = strategy.getCurrentSpread(msg.sender, address(_ethOracle), false);
        currentFeeBase = feeBaseE4;
        exchangeAddress.createVsBondPool(_bondMaker, _volOracle, _pricer, _pricer, feeBaseE4);
        exchangeAddress.createVsEthPool(_ethOracle, _pricer, feeBaseE4, true);
        exchangeAddress.createVsEthPool(_ethOracle, _pricer, feeBaseE4, false);

        reserveEth = new ReserveEth();
    }

    function changeSpread() public override {
        int16 _currentFeeBase = STRATEGY.getCurrentSpread(OWNER, address(ORACLE), false);

        require(_currentFeeBase <= 1000 && _currentFeeBase >= 5, "Invalid feebase");
        bytes32 poolIDETHSell = DOTC.generateVsEthPoolID(address(this), true);
        bytes32 poolIDETHBuy = DOTC.generateVsEthPoolID(address(this), false);

        bytes32 poolIDBond = DOTC.generateVsBondPoolID(address(this), address(BONDMAKER));

        DOTC.updateVsEthPool(poolIDETHSell, ORACLE, BOND_PRICER, _currentFeeBase);

        DOTC.updateVsEthPool(poolIDETHBuy, ORACLE, BOND_PRICER, _currentFeeBase);

        DOTC.updateVsBondPool(poolIDBond, volOracle, BOND_PRICER, BOND_PRICER, _currentFeeBase);
        currentFeeBase = _currentFeeBase;
    }

    /**
     * @notice Receive ETH, then call _addLiquidity
     */
    function addLiquidity() external payable isSafeSupply returns (bool success) {
        success = _addLiquidity(msg.value);
    }

    function _sendTokens(address user, uint256 amount) internal override {
        reserveEth.sendAsset(payable(user), amount);
    }

    function _reserveAsset(uint256 collateralPerTokenE8) internal override {
        uint256 amount = _applyDecimalGap(
            uint256(totalUnremovedTokens[currentTerm]).mul(collateralPerTokenE8).div(10**decimals),
            false
        );
        _transferETH(address(reserveEth), amount);
    }

    function _issueBonds(uint256 bondgroupID, uint256 amount) internal override {
        BondMakerCollateralizedEthInterface bm = BondMakerCollateralizedEthInterface(
            address(BONDMAKER)
        );
        bm.issueNewBonds{value: amount.mul(10**DECIMAL_GAP).mul(1002).div(1000)}(bondgroupID);
    }

    function getCollateralAddress() external pure override returns (address) {
        return address(0);
    }

    /**
     * @dev Decimal gap between ETH and share token is 10
     */
    function _applyDecimalGap(uint256 amount, bool isDiv) internal pure override returns (uint256) {
        if (isDiv) {
            return amount / 10**DECIMAL_GAP;
        } else {
            return amount * 10**DECIMAL_GAP;
        }
    }

    /**
     * @notice Get available collateral amount in this term
     */
    function getCollateralAmount() public view override returns (uint256) {
        return address(this).balance.sub(totalReceivedCollateral[currentTerm]);
    }

    function getCollateralDecimal() external pure override returns (int16) {
        return 18;
    }

    function getReserveAddress() external view override returns (address) {
        return address(reserveEth);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract LatestPriceOracleInterface","name":"_ethOracle","type":"address"},{"internalType":"contract BondPricerWithAcceptableMaturity","name":"_pricer","type":"address"},{"internalType":"contract SimpleStrategyInterface","name":"strategy","type":"address"},{"internalType":"contract ERC20","name":"_rewardToken","type":"address"},{"internalType":"contract BondRegistratorInterface","name":"_registrator","type":"address"},{"internalType":"contract ExchangeInterface","name":"exchangeAddress","type":"address"},{"internalType":"contract VolatilityOracleInterface","name":"_volOracle","type":"address"},{"internalType":"uint64","name":"_priceUnit","type":"uint64"},{"internalType":"uint64","name":"_firstRewardRate","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogTransferETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"SetAddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"SetRemoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"SettleLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"issueBondGroupId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"issueAmount","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"burnBondGroupId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"burnAmount","type":"uint64"}],"name":"TrancheBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"term","type":"uint64"},{"indexed":false,"internalType":"int16","name":"newFeeBase","type":"int16"},{"indexed":false,"internalType":"uint64","name":"maturity","type":"uint64"}],"name":"UpdateMaturity","type":"event"},{"inputs":[],"name":"addLiquidity","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"addSuitableBondGroup","outputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"changeSpread","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getBalanceData","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint64","name":"term","type":"uint64"},{"internalType":"uint64","name":"rewardAmount","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"getBondGroupIDFromTermAndPrice","outputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"strikePrice","type":"uint256"}],"name":"getBondGroupIdFromStrikePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getCollateralAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralDecimal","outputs":[{"internalType":"int16","name":"","type":"int16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"getCollateralPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPhase","outputs":[{"internalType":"enum SimpleAggregatorInterface.AggregatorPhase","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentStatus","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"int16","name":"feeBase","type":"int16"},{"internalType":"uint32","name":"uncheckbondGroupId","type":"uint32"},{"internalType":"uint64","name":"unit","type":"uint64"},{"internalType":"uint64","name":"trancheTime","type":"uint64"},{"internalType":"bool","name":"isDanger","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"hasReservation","type":"bool"}],"name":"getExpectedBalance","outputs":[{"internalType":"uint256","name":"expectedBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInfo","outputs":[{"internalType":"address","name":"bondMaker","type":"address"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"dotc","type":"address"},{"internalType":"address","name":"bondPricerAddress","type":"address"},{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"address","name":"rewardTokenAddress","type":"address"},{"internalType":"address","name":"registratorAddress","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"reverseOracle","type":"bool"},{"internalType":"uint64","name":"basePriceUnit","type":"uint64"},{"internalType":"uint128","name":"maxSupply","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIssuableBondGroups","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"getLiquidationData","outputs":[{"internalType":"bool","name":"isLiquidated","type":"bool"},{"internalType":"uint32","name":"liquidatedBondGroupID","type":"uint32"},{"internalType":"uint32","name":"endBondGroupId","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getLiquidityReservationData","outputs":[{"internalType":"uint128","name":"receivedCollateralTerm","type":"uint128"},{"internalType":"uint128","name":"receivedCollateralAmount","type":"uint128"},{"internalType":"uint128","name":"removeTokenTerm","type":"uint128"},{"internalType":"uint128","name":"removeTokenAmount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserveAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRewardAmount","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"getTermInfo","outputs":[{"internalType":"uint64","name":"maturity","type":"uint64"},{"internalType":"uint64","name":"solidStrikePrice","type":"uint64"},{"internalType":"bytes32","name":"SBTID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRewards","outputs":[{"components":[{"internalType":"uint64","name":"term","type":"uint64"},{"internalType":"uint64","name":"value","type":"uint64"}],"internalType":"struct SimpleAggregatorInterface.TotalReward[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalUnmovedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTotalSupplySafe","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidateBonds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"removeLiquidity","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renewMaturity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleTokens","outputs":[{"internalType":"uint256","name":"unsentETH","type":"uint256"},{"internalType":"uint256","name":"unsentToken","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"totalShareData","outputs":[{"internalType":"uint128","name":"totalShare","type":"uint128"},{"internalType":"uint128","name":"totalCollateralPerToken","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheBonds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateStartBondGroupId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"rewardRate","type":"uint64"}],"name":"updateTotalReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101e06040526008805463ffffffff60801b19167001000000000000000000000000000000001790553480156200003557600080fd5b506040516200693738038062006937833981016040819052620000589162000652565b888888888888878760008b80806000806101000a8154816001600160a01b0302191690836001600160a01b0316021790555050846001600160a01b0316630b1a35546040518163ffffffff1660e01b815260040160206040518083038186803b158015620000c557600080fd5b505afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062c565b6001600160601b0319606091821b8116610120528a821b811660e0528b821b8116610100526001600160c01b031960c087811b919091166101a05284151560f81b6101805289831b8216905287821b81166101405286821b811660a05289821b166080526040805180820190915260018082526001600160401b038681166020840181815260048054948501815560005293517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9093018054945183166801000000000000000002600160401b600160801b03199484166001600160401b031996871617949094169390931790925560088054909316908816179091553390911b610160526305f5e10011801590620002285750655af3107a40006001600160401b03841611155b6200026a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200026190620007cb565b60405180910390fd5b505050505050505050506000846001600160a01b0316630b1a35546040518163ffffffff1660e01b815260040160206040518083038186803b158015620002b057600080fd5b505afa158015620002c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002eb91906200062c565b90506000886001600160a01b031663601b45e2338d60006040518463ffffffff1660e01b8152600401620003229392919062000745565b60206040518083038186803b1580156200033b57600080fd5b505afa15801562000350573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000376919062000722565b6008805461ffff60a01b19167401000000000000000000000000000000000000000061ffff600185900b16021790556040517f78f286d90000000000000000000000000000000000000000000000000000000081529091506001600160a01b038716906378f286d990620003f790859089908f908190889060040162000769565b602060405180830381600087803b1580156200041257600080fd5b505af115801562000427573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200044d919062000613565b506040517f241d92290000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063241d9229906200049c908e908e9086906001906004016200079f565b602060405180830381600087803b158015620004b757600080fd5b505af1158015620004cc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004f2919062000613565b506040517f241d92290000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063241d92299062000541908e908e9086906000906004016200079f565b602060405180830381600087803b1580156200055c57600080fd5b505af115801562000571573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000597919062000613565b50604051620005a690620005e7565b604051809103906000f080158015620005c3573d6000803e3d6000fd5b5060601b6001600160601b0319166101c052506200081b9950505050505050505050565b61039380620065a483390190565b80516001600160401b03811681146200060d57600080fd5b92915050565b60006020828403121562000625578081fd5b5051919050565b6000602082840312156200063e578081fd5b81516200064b8162000802565b9392505050565b60008060008060008060008060006101208a8c03121562000671578485fd5b89516200067e8162000802565b60208b0151909950620006918162000802565b60408b0151909850620006a48162000802565b60608b0151909750620006b78162000802565b60808b0151909650620006ca8162000802565b60a08b0151909550620006dd8162000802565b60c08b0151909450620006f08162000802565b9250620007018b60e08c01620005f5565b9150620007138b6101008c01620005f5565b90509295985092959850929598565b60006020828403121562000734578081fd5b81518060010b81146200064b578182fd5b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b03958616815293851660208501529184166040840152909216606082015260019190910b608082015260a00190565b6001600160a01b03948516815292909316602083015260010b6040820152901515606082015260800190565b6020808252600c908201527f4f7574206f662072616e67650000000000000000000000000000000000000000604082015260600190565b6001600160a01b03811681146200081857600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160f81c6101a05160c01c6101c05160601c615b9862000a0c6000398061198a5280612bd652806141f152508061164d528061410d528061414b528061418a52508061162b5280611c895280612b335280612d8052806136a05280613847525080610c5f5280611609528061271c5280612aef5250806115e75280612e07528061379a52508061083c5280610ead528061151b5280611c575280611db352806121445280612e365280612edd52806137c75280613ad65280613c225280613d1652806142d55280614365528061456352806147615280614a98525080610c815280610f82528061104652806115a352806118a65280611b425280612b115280612c94525080610fa452806110685280611111528061158152806130da5250806115c55280612004525080610d4c5280610dda5280610e7d5280610f53528061101552806110dc528061155f5280611d10528061224552806122d45280612fa1528061443f52806144df528061463d52806146dd528061483b52806148db525080610c32528061153d5280611c2a52806125a85280612a9d5280612bff5280612d455280613665528061388b528061395a5250615b986000f3fe60806040526004361061024a5760003560e01c806392da91ad11610139578063b88a802f116100b6578063dd62ed3e1161007a578063dd62ed3e146106f4578063e0e54dec14610714578063e627f2db14610734578063e8078d9414610756578063ef4498ff1461075e578063fde6fad91461077e5761028d565b8063b88a802f14610673578063c82e377814610688578063cc4df8ae146106aa578063d28f3330146106bf578063d3339533146106d45761028d565b80639a8fac74116100fd5780639a8fac74146105e0578063a3a40ea5146105f5578063a3dd261914610617578063a9059cbb1461063e578063ae1162561461065e5761028d565b806392da91ad1461055257806395d89b41146105725780639649a73714610587578063979c6fe61461059c5780639960d742146105cb5761028d565b80633beeae20116101c75780635a9b0b891161018b5780635a9b0b89146104855780636c13ba78146104b157806370a08231146104e15780638417cb13146105015780638c5301c0146105235761028d565b80633beeae20146103d257806344a040f5146103e75780634759898f146104145780634fac075b14610436578063506718ef146104655761028d565b806318160ddd1161020e57806318160ddd1461035157806323b872dd146103665780632e20da2714610386578063313ce5671461039b578063315deeaa146103bd5761028d565b806302ecdef21461029257806306fdde03146102a9578063095ea7b3146102d45780630dad4e4b1461030157806315e524871461032e5761028d565b3661028d57604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061028390349061532b565b60405180910390a3005b600080fd5b34801561029e57600080fd5b506102a76107ac565b005b3480156102b557600080fd5b506102be610914565b6040516102cb9190615503565b60405180910390f35b3480156102e057600080fd5b506102f46102ef366004614eb8565b610945565b6040516102cb9190615302565b34801561030d57600080fd5b5061032161031c366004614e8b565b6109e9565b6040516102cb919061532b565b34801561033a57600080fd5b50610343610abe565b6040516102cb9291906159e7565b34801561035d57600080fd5b50610321610aed565b34801561037257600080fd5b506102f4610381366004614e4b565b610b26565b34801561039257600080fd5b506102a7610c18565b3480156103a757600080fd5b506103b0611199565b6040516102cb9190615a9b565b3480156103c957600080fd5b5061032161119e565b3480156103de57600080fd5b506102a76111c5565b3480156103f357600080fd5b50610407610402366004614df7565b611447565b6040516102cb9190615a49565b34801561042057600080fd5b506104296114b3565b6040516102cb9190615493565b34801561044257600080fd5b50610456610451366004615051565b6114b8565b6040516102cb9392919061530d565b34801561047157600080fd5b50610321610480366004615051565b6114f7565b34801561049157600080fd5b5061049a611519565b6040516102cb9b9a999897969594939291906151be565b3480156104bd57600080fd5b506104d16104cc366004614df7565b61167e565b6040516102cb9493929190615953565b3480156104ed57600080fd5b506103216104fc366004614df7565b6116c5565b34801561050d57600080fd5b506105166116e9565b6040516102cb919061515c565b34801561052f57600080fd5b5061054361053e366004614df7565b6116ee565b6040516102cb9392919061597e565b34801561055e57600080fd5b506102f461056d36600461502a565b61172e565b34801561057e57600080fd5b506102be611848565b34801561059357600080fd5b50610321611868565b3480156105a857600080fd5b506105bc6105b7366004615051565b611948565b6040516102cb93929190615a77565b3480156105d757600080fd5b50610516611988565b3480156105ec57600080fd5b506102f46119ac565b34801561060157600080fd5b5061060a6119bd565b6040516102cb919061547f565b34801561062357600080fd5b5061062c611a77565b6040516102cb969594939291906159a8565b34801561064a57600080fd5b506102f4610659366004614eb8565b611abd565b34801561066a57600080fd5b506102a7611acd565b34801561067f57600080fd5b506102a7611ed9565b34801561069457600080fd5b5061069d61202b565b6040516102cb91906152be565b3480156106b657600080fd5b5061034361208e565b3480156106cb57600080fd5b506102a76120b4565b3480156106e057600080fd5b506103216106ef366004615069565b61253a565b34801561070057600080fd5b5061032161070f366004614e13565b612557565b34801561072057600080fd5b5061032161072f366004615069565b61258b565b34801561074057600080fd5b50610749612665565b6040516102cb9190615262565b6102f46126db565b34801561076a57600080fd5b506102a7610779366004615104565b612711565b34801561078a57600080fd5b5061079e610799366004615051565b612842565b6040516102cb929190615939565b6007546107d45760405162461bcd60e51b81526004016107cb90615870565b60405180910390fd5b60085460075460001901600090815260016020526040902054600160801b90910463ffffffff16906001600160401b0316806108225760405162461bcd60e51b81526004016107cb90615809565b6040516301e5ddfb60e71b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2eefd8090610871908690600401615a38565b60006040518083038186803b15801561088957600080fd5b505afa15801561089d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108c59190810190614f2b565b915050816001600160401b031681106109035750506008805463ffffffff909216600160801b0263ffffffff60801b19909216919091179055610912565b60018301925050610822565b50505b565b604051806040016040528060158152602001744c49454e5f41474752454741544f525f534841524560581b81525081565b600060001982141561095c576001600160801b0391505b61096582612879565b336000818152600c602090815260408083206001600160a01b03891680855292529182902080546001600160801b0319166001600160801b039590951694909417909355517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109d790869061532b565b60405180910390a35060015b92915050565b6001600160a01b0382166000908152600b60209081526040808320546009909252909120546001600160801b0391821691600160801b90910416156109e35733600090815260096020526040902054600754600193506001600160801b0390911610156109e357336000818152600960208181526040808420546001600160801b0380821660010181168652600684529185205495909452919052610ab792610ab092600160801b91829004831692610aaa92909104166305f5e1006128a2565b906128dc565b600161291e565b0192915050565b6007546000908152600d6020908152604080832054600e909252909120546001600160801b0391821691169091565b6007546000908152600e60209081526040808320546006909252822054610b20916001600160801b039182169116612942565b90505b90565b6001600160a01b0383166000908152600c602090815260408083203384529091528120546001600160801b031682811015610b65576000915050610c11565b6001600160801b0381811614610bf7576001600160a01b0385166000908152600c60209081526040808320338452909152902054610bb590610bb0906001600160801b031685612942565b612879565b6001600160a01b0386166000908152600c60209081526040808320338452909152902080546001600160801b0319166001600160801b03929092169190911790555b610c0a8585610c0586612879565b612984565b5060019150505b9392505050565b60405163300da2f160e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063601b45e290610cab907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090869060040161523e565b60206040518083038186803b158015610cc357600080fd5b505afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190615009565b90506103e88160010b13158015610d16575060058160010b12155b610d325760405162461bcd60e51b81526004016107cb9061571c565b6040516311ed607760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906311ed607790610d8490309060019060040161518a565b60206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166311ed60773060006040518363ffffffff1660e01b8152600401610e2792919061518a565b60206040518083038186803b158015610e3f57600080fd5b505afa158015610e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e779190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663488abbfc307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401610ee9929190615170565b60206040518083038186803b158015610f0157600080fd5b505afa158015610f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f399190614ff1565b604051631711ddb160e21b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635c4776c490610fce9086907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615334565b600060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b5050604051631711ddb160e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250635c4776c491506110929085907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615334565b600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b5050600054604051630ccb63b760e41b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116945063ccb63b70935061113d9286929116907f00000000000000000000000000000000000000000000000000000000000000009081908b9060040161535c565b600060405180830381600087803b15801561115757600080fd5b505af115801561116b573d6000803e3d6000fd5b50506008805460019790970b61ffff16600160a01b0261ffff60a01b19909716969096179095555050505050565b600881565b6007546000908152600d6020526040812054610b20903031906001600160801b0316612942565b6007546000818152600e602090815260408083205460059092528220549192839290916001600160801b031690600160401b900460ff1680611205575081155b6112215760405162461bcd60e51b81526004016107cb90615536565b6000828152600660205260409020546001600160801b031680156112a657600061124961119e565b9050611260610ab083610aaa846305f5e1006128a2565b6000858152600d602052604090205490955061129e90869061128f906001600160801b03166305f5e1006128a2565b8161129657fe5b04600161291e565b9550506112f0565b6000838152600d60205260409020546001600160801b0316156112f0576000838152600d60205260409020546112e6906001600160801b0316600161291e565b94506305f5e10093505b8085016112fc85612879565b60018501600090815260066020526040902080546001600160801b03928316600160801b029216919091179055611340610bb08461133a858a612a40565b90612942565b60018501600090815260066020526040902080546001600160801b0319166001600160801b0392831617908190556c2af31dc4611873bf3f70834acd91161115611398576008805460ff60b01b1916600160b01b1790555b83156113a6576113a6612a65565b6000811180156113b65750600083115b156113c4576113c485612b95565b6113cc612bfb565b6113d7600754613151565b6008546007546000908152600160208190526040918290205491516001600160401b03948516947fb6468ad5c9ad279cc97382791cf54035b2adbdc6126bee312967c4fdbb9a56da9461143794600160a01b90910490930b9216906154e7565b60405180910390a2505050505050565b6001600160a01b0381166000908152600b60209081526040808320815160608101835290546001600160801b03811682526001600160401b03600160801b8204811694830194909452600160c01b9004909216908201526007546114ab9190613176565b90505b919050565b601290565b60008080836114c75760075493505b50505060009081526005602052604090205460ff600160401b8204169163ffffffff600160201b83048116921690565b600090815260066020526040902054600160801b90046001600160801b031690565b7f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906c2af31dc4611873bf3f70834acd90565b6001600160a01b0316600090815260096020908152604080832054600a909252909120546001600160801b0380831693600160801b93849004821693828416930490911690565b6001600160a01b03166000908152600b60205260409020546001600160801b031690565b600090565b6001600160a01b03166000908152600b60205260409020546001600160801b038116916001600160401b03600160c01b8304811692600160801b90041690565b600080600061173b613309565b600754336000908152600a60205260409020549295509093509150600160801b90046001600160801b031661179357336000908152600a6020526040902080546001600160801b0319166001600160801b0383161790555b336000818152600a6020908152604080832080546001600160801b03600160801b80830482168d0182160291811691909117909155858452600e9092529091208054808316890183166001600160801b0319919091161790556117fb919085908816856134c1565b80336001600160a01b03167f3518f79326efc4570db0ebb1195252c857df4c2beb5932ab886faa94251a50e0876040516118359190615925565b60405180910390a3506001949350505050565b6040518060400160405280600481526020016309882a6960e31b81525081565b6007546000908152600160205260408120546001600160401b03164211156118a25760405162461bcd60e51b81526004016107cb90615600565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190614ff1565b905061194281613646565b91505090565b60008080836119575760075493505b505050600090815260016020819052604090912080549101546001600160401b0380831693600160401b9093041691565b7f000000000000000000000000000000000000000000000000000000000000000090565b600854600160b01b900460ff161590565b6000600754600014156119d257506000610b23565b6007546000908152600160205260409020546001600160401b03164211611a22576008546001600160401b03600160401b909104166203f480014211611a1a57506002610b23565b506001610b23565b6007546000908152600160205260409020546001600160401b031642118015611a645750600754600090815260056020526040902054600160401b900460ff16155b15611a7157506003610b23565b50600490565b6007546008549091600160a01b820460010b91600160801b810463ffffffff16916001600160401b0380831692600160401b810490911691600160b01b90910460ff1690565b6000610c113384610c0585612879565b6007546000908152600160205260409020546001600160401b0316421115611b075760405162461bcd60e51b81526004016107cb90615600565b6008546001600160401b03600160401b909104166203f480014211611b3e5760405162461bcd60e51b81526004016107cb90615596565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd39190614ff1565b90506000611be08261393b565b905080611bf357611bf082613646565b90505b600080611bfe614db9565b6007546000908152600260205260409081902060085491516329069bdd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926329069bdd92611cb1927f00000000000000000000000000000000000000000000000000000000000000009230928b928d926001600160401b0316907f00000000000000000000000000000000000000000000000000000000000000009060040161538d565b60806040518083038186803b158015611cc957600080fd5b505afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d01919061508a565b919450925090508115611d83577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663439370b1836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050505b8215611d9357611d938484613ad4565b602081015115611e5c578051602082015160405163b9601d7760e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169263b9601d7792611dee926004016159e7565b602060405180830381600087803b158015611e0857600080fd5b505af1158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e409190614fd5565b611e5c5760405162461bcd60e51b81526004016107cb9061577c565b611e6542613151565b6008805467ffffffffffffffff60401b1916600160401b6001600160401b039384160217905581516020830151604051918316928716917f2eaafc32eed9e5ff41c1b57ddd1ef894ec4eb7499efb581d50edffa27f6af23291611eca91889190615a5d565b60405180910390a35050505050565b611ee1614dd7565b50336000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754611f42908290613176565b6001600160401b03908116602083018190526007549091166040830152611f7b5760405162461bcd60e51b81526004016107cb906156d2565b60208181018051600080835233808252600b909452604090819020855181549451928701516001600160801b03199095166001600160801b039091161767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b9483169490940293909317909255169061090f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169083613b9a565b60075460009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561208457602002820191906000526020600020905b815481526020019060010190808311612070575b5050505050905090565b600080600061209b613309565b919450925090506120af33836000846134c1565b509091565b6007546000908152600160205260409020546001600160401b031642116120ed5760405162461bcd60e51b81526004016107cb906158df565b600754600081815260056020526040902054600160401b900460ff16156121265760405162461bcd60e51b81526004016107cb90615904565b60008181526005602052604090205463ffffffff166121ff576121d87f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac3fd8866040518163ffffffff1660e01b815260040160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190614ff1565b613bf5565b6000828152600560205260409020805463ffffffff191663ffffffff929092169190911790555b6000818152600160205260408082205460001984018352818320549151631c1b06f760e11b8152839283926001600160401b039081169291169083906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906338360dee9061227a90309060040161515c565b60206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca9190614ff1565b90508015612346577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a0ef91df6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561232d57600080fd5b505af1158015612341573d6000803e3d6000fd5b505050505b50600086815260056020526040902054600160201b900463ffffffff1661237e57600854600160801b900463ffffffff16935061239d565b600086815260056020526040902054600160201b900463ffffffff1693505b600086815260056020526040902054603263ffffffff91821686900390911611156123ff576000868152600560205260409020805463ffffffff60328701908116600160201b0267ffffffff0000000019909216919091179091559450612417565b60008681526005602052604090205463ffffffff1694505b63ffffffff84165b8563ffffffff168110156124c25761243981858585613c1a565b935060098463ffffffff1611156124ba576001860363ffffffff1681141561247f576000878152600560205260409020805460ff60401b1916600160401b1790556124ae565b6000878152600560205260409020805467ffffffff000000001916600160201b6001840163ffffffff16021790555b50505050505050610912565b60010161241f565b5060008681526005602052604090205463ffffffff86811691161415612506576000868152600560205260409020805460ff60401b1916600160401b179055612532565b6000868152600560205260409020805467ffffffff000000001916600160201b63ffffffff8816021790555b505050505050565b600091825260036020908152604080842092845291905290205490565b6001600160a01b039182166000908152600c602090815260408083209390941682529190915220546001600160801b031690565b6008546040516351d19dc760e11b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a3a33b8e916125ea9186916001600160401b031690600190600401615a16565b60206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a9190614ff1565b9150826126475760075492505b50600091825260036020908152604080842092845291905290205490565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156126d257600084815260209081902060408051808201909152908401546001600160401b038082168352600160401b9091041681830152825260019092019101612689565b50505050905090565b600854600090600160b01b900460ff16156127085760405162461bcd60e51b81526004016107cb906156f5565b610b2034613df2565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146127595760405162461bcd60e51b81526004016107cb906156ab565b6007546127785760405162461bcd60e51b81526004016107cb90615870565b6305f5e1006001600160401b038216108015906127a45750655af3107a40006001600160401b03821611155b6127c05760405162461bcd60e51b81526004016107cb9061579d565b600460405180604001604052806127d8600754613151565b60019081016001600160401b03908116835294851660209283015283549081018455600093845292819020825193018054929091015167ffffffffffffffff199092169284169290921767ffffffffffffffff60401b1916600160401b9190931602919091179055565b600080826128505760075492505b50506000908152600660205260409020546001600160801b0380821692600160801b9092041690565b6000600160801b821061289e5760405162461bcd60e51b81526004016107cb906155b9565b5090565b6000826128b1575060006109e3565b828202828482816128be57fe5b0414610c115760405162461bcd60e51b81526004016107cb90615624565b6000610c1183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f0c565b6000811561293457506402540be40082046109e3565b506402540be40082026109e3565b6000610c1183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613f43565b6001600160a01b0383166000908152600b60205260408120546001600160801b03808416911610156129b857506000610c11565b6129cf84836001600160801b031660001902613f6f565b6129e283836001600160801b0316613f6f565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846001600160801b0316604051612a2e919061532b565b60405180910390a35060019392505050565b600082820183811015610c115760405162461bcd60e51b81526004016107cb9061555f565b6008546007546000818152600660205260408082205460019384018352918190205490516379b347db60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946379b347db94612b5b94600160a01b909204900b926001600160801b03600160801b928390048116939290910416907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906004016154a1565b600060405180830381600087803b158015612b7557600080fd5b505af1158015612b89573d6000803e3d6000fd5b50505050610912610c18565b6007546000908152600e6020526040812054612bcf90612bc8906305f5e10090610aaa906001600160801b0316866128a2565b600061291e565b905061090f7f0000000000000000000000000000000000000000000000000000000000000000826140d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca579d0a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e9190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612ced57600080fd5b505af1158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d259190614ff1565b600854604051637298096d60e11b81529192506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e53012da91612da89186916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b158015612dc057600080fd5b505afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df89190614ff1565b9050612e03826140fb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a38593887f0000000000000000000000000000000000000000000000000000000000000000612e5e85613151565b612e6788613151565b6040518463ffffffff1660e01b8152600401612e8593929190615455565b602060405180830381600087803b158015612e9f57600080fd5b505af1158015612eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed79190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b836040518263ffffffff1660e01b8152600401612f27919061532b565b60806040518083038186803b158015612f3f57600080fd5b505afa158015612f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f779190614ee3565b505060405163095ea7b360e01b8152919250506001600160a01b0382169063095ea7b390612fcd907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b158015612fe757600080fd5b505af1158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614fd5565b50600780546001019055613031614dd7565b604051806060016040528061304588613151565b6001600160401b0316815260200161305c86613151565b6001600160401b039081168252602091820186905260075460009081526001808452604091829020855181549587015167ffffffffffffffff199096169085161767ffffffffffffffff60401b1916600160401b959094169490940292909217835583810151929091019190915551631d3b07f760e21b81529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906374ec1fdc9061311790899060040161532b565b600060405180830381600087803b15801561313157600080fd5b505af1158015613145573d6000803e3d6000fd5b50505050505050505050565b6000600160401b821061289e5760405162461bcd60e51b81526004016107cb90615665565b602082015182516001600160801b0316158015906131a057508183604001516001600160401b0316105b156109e357600480546000198101916000916001600160401b0384169081106131c557fe5b6000918252602082200154600480546001600160401b039283169450909185169081106131ee57fe5b600091825260209091200154600160401b90046001600160401b03169050845b86604001516001600160401b03168111156132ff57826001600160401b03168110156132a1576001840393506004846001600160401b03168154811061325057fe5b9060005260206000200160000160089054906101000a90046001600160401b031691506004846001600160401b03168154811061328957fe5b6000918252602090912001546001600160401b031692505b60008181526006602052604090205487516132f4916132ef916132df916001600160801b0390811691610aaa916001600160401b03891691166128a2565b6001600160401b03881690612a40565b613151565b94506000190161320e565b5050505092915050565b600754336000908152600a602090815260408083205460099092528220549192839283926001600160801b0380821692600160801b92839004821692818316929104168461336657600080600097509750975050505050506134bc565b6001600160801b038316158015906133865750836001600160801b031685115b156133ef576001600160801b036001850181166000908152600660205260409020546133cc91612bc8916305f5e10091610aaa9188821691600160801b909104166128a2565b975087156133de576133de33896141da565b336000908152600a60205260408120555b6001600160801b0381161580159061340f5750816001600160801b031685115b15613472576001600160801b0360018301811660009081526006602052604090205461345391610ab091600160801b9004811690610aaa9085166305f5e1006128a2565b3360009081526009602052604081205596506001600160801b03821695505b84336001600160a01b03167fb11715e80d7e8d99a84fdd2112e0c3b821523d7416cb2082ec62d76c76f6f0168a8a6040516134ae9291906159e7565b60405180910390a350505050505b909192565b6134c9614dd7565b506001600160a01b0384166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b9004909116918101919091528315613571576135358183613176565b6001600160401b03908116602083015282166040820152805161356590610bb0906001600160801b031686612a40565b6001600160801b031681525b61357d81600754613176565b6001600160401b03908116602083015260075416604082015282156135c15780516135b590610bb0906001600160801b031685612942565b6001600160801b031681525b6001600160a01b03949094166000908152600b6020908152604091829020865181549288015193909701516001600160801b03199092166001600160801b039097169690961767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b929091169190910217909355505050565b60085460405163a072a3e560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a072a3e5916136c89187916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b1580156136e057600080fd5b505afa1580156136f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137189190614ff1565b600754909150613726614dd7565b50600081815260016020818152604092839020835160608101855281546001600160401b038082168352600160401b9091041692810183905292015492820192909252906137749084614256565b602082015182516040808501519051635b1caa5760e11b81529396506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169363b63954ae936137f1937f0000000000000000000000000000000000000000000000000000000000000000938a9360040161541e565b602060405180830381600087803b15801561380b57600080fd5b505af115801561381f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138439190614ff1565b93507f0000000000000000000000000000000000000000000000000000000000000000156139295760085460405163a072a3e560e01b81526139249186916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a072a3e5916138cf918b916001600160401b03909116906000906004016159f5565b60206040518083038186803b1580156138e757600080fd5b505afa1580156138fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391f9190614ff1565b614280565b613933565b6139338484614280565b505050919050565b6008546040516351d19dc760e11b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a3a33b8e9161399e9187916001600160401b0390911690600190600401615a16565b60206040518083038186803b1580156139b657600080fd5b505afa1580156139ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ee9190614ff1565b600754600090815260036020908152604080832084845291829052909120549192509015613a2a576000918252602052604090205490506114ae565b60015b60028111613933576008546001600160401b03168102830360009081526020839052604090205415613a80576008546001600160401b0316029091036000908152602091909152604090205490506114ae565b6008546001600160401b03168102830160009081526020839052604090205415613acc576008546001600160401b031602919091016000908152602091909152604090205490506114ae565b600101613a2d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038116638376c24d613b256103e8610aaa6103ea613b1f886402540be4006128a2565b906128a2565b856040518363ffffffff1660e01b8152600401613b42919061532b565b6020604051808303818588803b158015613b5b57600080fd5b505af1158015613b6f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613b949190614ff1565b50505050565b613bf08363a9059cbb60e01b8484604051602401613bb99291906151a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614962565b505050565b6000600160201b821061289e5760405162461bcd60e51b81526004016107cb906157c3565b6000606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2eefd80886040518263ffffffff1660e01b8152600401613c6c919061532b565b60006040518083038186803b158015613c8457600080fd5b505afa158015613c98573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc09190810190614f2b565b91509150846001600160401b0316811180613cf65750836001600160401b031681108015613cf657506001600160401b03841615155b15613d05578592505050613dea565b6000805b8351811015613de25760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b868481518110613d4f57fe5b60200260200101516040518263ffffffff1660e01b8152600401613d73919061532b565b60806040518083038186803b158015613d8b57600080fd5b505afa158015613d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dc39190614ee3565b5050509050613dd48a828b866149f1565b909950925050600101613d09565b508693505050505b949350505050565b6000806000613dff613309565b9250925050613e1133836000846134c1565b60075433600090815260096020526040902054600160801b90046001600160801b0316613e615733600090815260096020526040902080546001600160801b0319166001600160801b0383161790555b613e6a85612879565b33600090815260096020526040902080546001600160801b03600160801b808304821690940181169093029216919091179055613ea685612879565b6000828152600d60205260409081902080546001600160801b031981166001600160801b0391821694909401169290921790915551819033907f4c86739b331ba35e12897451019b4a8cca47a228be900c18ab3a8ffa5dfe7e539061183590899061532b565b60008183613f2d5760405162461bcd60e51b81526004016107cb9190615503565b506000838581613f3957fe5b0495945050505050565b60008184841115613f675760405162461bcd60e51b81526004016107cb9190615503565b505050900390565b613f77614dd7565b506001600160a01b0382166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754613fe1908290613176565b6001600160401b039081166020830152600754166040820152600082121561403057805161402090610bb0906001600160801b03166000859003612942565b6001600160801b03168152614055565b805161404990610bb0906001600160801b031684612a40565b6001600160801b031681525b6001600160a01b03929092166000908152600b6020908152604091829020845181549286015193909501516001600160801b03199092166001600160801b039095169490941767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b92909116919091021790915550565b61090f82826040518060600160405280602c8152602001615b37602c9139614bb0565b6000614133826001600160401b0360327f000000000000000000000000000000000000000000000000000000000000000002166128dc565b90508061417b576008805467ffffffffffffffff19167f00000000000000000000000000000000000000000000000000000000000000006001600160401b031617905561090f565b6141b5600a6001600160401b037f000000000000000000000000000000000000000000000000000000000000000016830260190204613151565b6008805467ffffffffffffffff19166001600160401b03929092169190911790555050565b60405163ed3de48760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ed3de4879061422890859085906004016151a5565b600060405180830381600087803b15801561424257600080fd5b505af1158015612532573d6000803e3d6000fd5b6000610c116002614270846001600160401b038716612942565b8161427757fe5b84919006612942565b60078054600090815260026020908152604080832080546001810182559084528284200186905592548252600381528282208483529052819020839055516301e5ddfb60e71b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2eefd809061430a90869060040161532b565b60006040518083038186803b15801561432257600080fd5b505afa158015614336573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261435e9190810190614f2b565b50905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8360018151811061439f57fe5b60200260200101516040518263ffffffff1660e01b81526004016143c3919061532b565b60806040518083038186803b1580156143db57600080fd5b505afa1580156143ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144139190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906144679030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561447f57600080fd5b505afa158015614493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b79190614ff1565b61455f5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061450b907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455d9190614fd5565b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8460028151811061459d57fe5b60200260200101516040518263ffffffff1660e01b81526004016145c1919061532b565b60806040518083038186803b1580156145d957600080fd5b505afa1580156145ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146119190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906146659030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561467d57600080fd5b505afa158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b59190614ff1565b61475d5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614709907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561472357600080fd5b505af1158015614737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061475b9190614fd5565b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8560038151811061479b57fe5b60200260200101516040518263ffffffff1660e01b81526004016147bf919061532b565b60806040518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906148639030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561487b57600080fd5b505afa15801561488f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b39190614ff1565b6125325760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614907907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561492157600080fd5b505af1158015614935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149599190614fd5565b50505050505050565b60606149b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614ca69092919063ffffffff16565b805190915015613bf057808060200190518101906149d59190614fd5565b613bf05760405162461bcd60e51b81526004016107cb90615895565b6040516370a0823160e01b81526000908190859082906001600160a01b038316906370a0823190614a2690309060040161515c565b60206040518083038186803b158015614a3e57600080fd5b505afa158015614a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a769190614ff1565b1115614ba35783614b28576040516301bc8ef560e61b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636f23bd4090614ad0908a906000906004016159e7565b602060405180830381600087803b158015614aea57600080fd5b505af1158015614afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b229190614ff1565b50600193505b806001600160a01b0316639975038c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b9b9190614ff1565b506001850194505b5092959194509092505050565b614bb982614cb5565b8190614bd85760405162461bcd60e51b81526004016107cb9190615503565b506000836001600160a01b031683604051614bf290610b23565b60006040518083038185875af1925050503d8060008114614c2f576040519150601f19603f3d011682016040523d82523d6000602084013e614c34565b606091505b5050905080614c555760405162461bcd60e51b81526004016107cb90615745565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c85604051614c98919061532b565b60405180910390a350505050565b6060613dea8484600085614cbc565b3031101590565b6060614cc785614d80565b614ce35760405162461bcd60e51b81526004016107cb90615839565b60006060866001600160a01b03168587604051614d009190615140565b60006040518083038185875af1925050503d8060008114614d3d576040519150601f19603f3d011682016040523d82523d6000602084013e614d42565b606091505b50915091508115614d56579150613dea9050565b805115614d665780518082602001fd5b8360405162461bcd60e51b81526004016107cb9190615503565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613dea575050151592915050565b60405180604001604052806002906020820280368337509192915050565b604080516060810182526000808252602082018190529181019190915290565b600060208284031215614e08578081fd5b8135610c1181615afb565b60008060408385031215614e25578081fd5b8235614e3081615afb565b91506020830135614e4081615afb565b809150509250929050565b600080600060608486031215614e5f578081fd5b8335614e6a81615afb565b92506020840135614e7a81615afb565b929592945050506040919091013590565b60008060408385031215614e9d578182fd5b8235614ea881615afb565b91506020830135614e4081615b13565b60008060408385031215614eca578182fd5b8235614ed581615afb565b946020939093013593505050565b60008060008060808587031215614ef8578081fd5b8451614f0381615afb565b602086015160408701519195509350614f1b81615b21565b6060959095015193969295505050565b60008060408385031215614f3d578182fd5b82516001600160401b0380821115614f53578384fd5b818501915085601f830112614f66578384fd5b815181811115614f74578485fd5b60209150818102614f86838201615aa9565b8281528381019085850183870186018b1015614fa0578889fd5b8896505b84871015614fc2578051835260019690960195918501918501614fa4565b5097909301519698969750505050505050565b600060208284031215614fe6578081fd5b8151610c1181615b13565b600060208284031215615002578081fd5b5051919050565b60006020828403121561501a578081fd5b81518060010b8114610c11578182fd5b60006020828403121561503b578081fd5b81356001600160801b0381168114610c11578182fd5b600060208284031215615062578081fd5b5035919050565b6000806040838503121561507b578182fd5b50508035926020909101359150565b60008060006080848603121561509e578081fd5b83519250602080850151925085605f8601126150b8578182fd5b6150c26040615aa9565b8060408701886080890111156150d6578485fd5b845b60028110156150f5578151845292840192908401906001016150d8565b50508093505050509250925092565b600060208284031215615115578081fd5b8135610c1181615b21565b15159052565b6001600160801b03169052565b6001600160401b03169052565b60008251615152818460208701615acf565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038c811682528b811660208301528a811660408301528981166060830152888116608083015287811660a083015286811660c0830152851660e08201528315156101008201526001600160401b038316610120820152610160810161522e610140830184615126565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152901515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156152b157815180516001600160401b039081168652908701511686850152928401929085019060010161527f565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152f6578351835292840192918401916001016152da565b50909695505050505050565b901515815260200190565b921515835263ffffffff918216602084015216604082015260600190565b90815260200190565b9384526001600160a01b0392831660208501529116604083015260010b606082015260800190565b9485526001600160a01b0393841660208601529183166040850152909116606083015260010b608082015260a00190565b600060e0820160018060a01b03808b1684526020818b168186015289604086015288606086015260e060808601528291508754808452610100860192508885528185209350845b818110156153f0578454845260019485019493830193016153d4565b505050809250505061540560a0830185615133565b61541260c0830184615120565b98975050505050505050565b6001600160a01b0395909516855260208501939093526001600160401b039182166040850152166060830152608082015260a00190565b6001600160a01b039390931683526001600160401b03918216602084015216604082015260600190565b602081016005831061548d57fe5b91905290565b60019190910b815260200190565b60019690960b86526001600160801b0394851660208701529290931660408501526001600160a01b0390811660608501529091166080830152151560a082015260c00190565b60019290920b82526001600160401b0316602082015260400190565b6000602082528251806020840152615522816040850160208701615acf565b601f01601f19169190910160400192915050565b6020808252600f908201526e139bdd08195e1c1a5c9959081e595d608a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260099082015268436f6f6c2054696d6560b81b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600a90820152694e6f742061637469766560b01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b6020808252600d908201526c27b7363c90383937bb34b232b960991b604082015260600190565b602080825260099082015268139bc814995dd85c9960ba1b604082015260600190565b6020808252600d908201526c556e7361666520737570706c7960981b604082015260600190565b6020808252600f908201526e496e76616c6964206665656261736560881b604082015260600190565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252600790820152665265766572736560c81b604082015260600190565b6020808252600c908201526b4f7574206f662072616e676560a01b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360408201526532206269747360d01b606082015260800190565b60208082526016908201527513585d1d5c9a5d1e481cda1bdd591b1908195e1a5cdd60521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a4e6f742072756e6e696e6760a81b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600b908201526a139bdd0813585d1d5c995960aa1b604082015260600190565b602080825260079082015266115e1c1a5c995960ca1b604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526001600160401b03918216602084015216604082015260600190565b95865260019490940b602086015263ffffffff9290921660408501526001600160401b039081166060850152166080830152151560a082015260c00190565b918252602082015260400190565b9283526001600160401b039190911660208301521515604082015260600190565b9283526001600160401b0391909116602083015260ff16604082015260600190565b63ffffffff91909116815260200190565b6001600160401b0391909116815260200190565b6001600160401b0392831681529116602082015260400190565b6001600160401b039384168152919092166020820152604081019190915260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ac757600080fd5b604052919050565b60005b83811015615aea578181015183820152602001615ad2565b83811115613b945750506000910152565b6001600160a01b0381168114615b1057600080fd5b50565b8015158114615b1057600080fd5b6001600160401b0381168114615b1057600080fdfe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a264697066735822122002e2720145b831229dc25d43b34aff7140055dd20fc8f575bd19116ae9ed92a464736f6c63430007010033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610361806100326000396000f3fe6080604052600436106100225760003560e01c8063ed3de4871461006a57610065565b3661006557604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061005b9034906102f6565b60405180910390a3005b600080fd5b34801561007657600080fd5b5061008a6100853660046101e8565b61008c565b005b6000546001600160a01b031633146100bf5760405162461bcd60e51b81526004016100b6906102ab565b60405180910390fd5b6100c982826100cd565b5050565b6100c982826040518060600160405280602c8152602001610300602c91396100f4826101e1565b81906101135760405162461bcd60e51b81526004016100b69190610221565b506000836001600160a01b03168360405161012d9061021e565b60006040518083038185875af1925050503d806000811461016a576040519150601f19603f3d011682016040523d82523d6000602084013e61016f565b606091505b50509050806101905760405162461bcd60e51b81526004016100b690610274565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c856040516101d391906102f6565b60405180910390a350505050565b3031101590565b600080604083850312156101fa578182fd5b82356001600160a01b0381168114610210578283fd5b946020939093013593505050565b90565b6000602080835283518082850152825b8181101561024d57858101830151858201604001528201610231565b8181111561025e5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252602b908201527f4572726f723a204f6e6c79206f776e65722063616e206578656375746520746860408201526a34b990333ab731ba34b7b760a91b606082015260800190565b9081526020019056fe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a26469706673582212204f0a0f8dfa8207815122cdcd7e302a058c41e7aa8d8ee8daf858e9b12287afea64736f6c634300070100330000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d00000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b81700000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000174876e800

Deployed Bytecode

0x60806040526004361061024a5760003560e01c806392da91ad11610139578063b88a802f116100b6578063dd62ed3e1161007a578063dd62ed3e146106f4578063e0e54dec14610714578063e627f2db14610734578063e8078d9414610756578063ef4498ff1461075e578063fde6fad91461077e5761028d565b8063b88a802f14610673578063c82e377814610688578063cc4df8ae146106aa578063d28f3330146106bf578063d3339533146106d45761028d565b80639a8fac74116100fd5780639a8fac74146105e0578063a3a40ea5146105f5578063a3dd261914610617578063a9059cbb1461063e578063ae1162561461065e5761028d565b806392da91ad1461055257806395d89b41146105725780639649a73714610587578063979c6fe61461059c5780639960d742146105cb5761028d565b80633beeae20116101c75780635a9b0b891161018b5780635a9b0b89146104855780636c13ba78146104b157806370a08231146104e15780638417cb13146105015780638c5301c0146105235761028d565b80633beeae20146103d257806344a040f5146103e75780634759898f146104145780634fac075b14610436578063506718ef146104655761028d565b806318160ddd1161020e57806318160ddd1461035157806323b872dd146103665780632e20da2714610386578063313ce5671461039b578063315deeaa146103bd5761028d565b806302ecdef21461029257806306fdde03146102a9578063095ea7b3146102d45780630dad4e4b1461030157806315e524871461032e5761028d565b3661028d57604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061028390349061532b565b60405180910390a3005b600080fd5b34801561029e57600080fd5b506102a76107ac565b005b3480156102b557600080fd5b506102be610914565b6040516102cb9190615503565b60405180910390f35b3480156102e057600080fd5b506102f46102ef366004614eb8565b610945565b6040516102cb9190615302565b34801561030d57600080fd5b5061032161031c366004614e8b565b6109e9565b6040516102cb919061532b565b34801561033a57600080fd5b50610343610abe565b6040516102cb9291906159e7565b34801561035d57600080fd5b50610321610aed565b34801561037257600080fd5b506102f4610381366004614e4b565b610b26565b34801561039257600080fd5b506102a7610c18565b3480156103a757600080fd5b506103b0611199565b6040516102cb9190615a9b565b3480156103c957600080fd5b5061032161119e565b3480156103de57600080fd5b506102a76111c5565b3480156103f357600080fd5b50610407610402366004614df7565b611447565b6040516102cb9190615a49565b34801561042057600080fd5b506104296114b3565b6040516102cb9190615493565b34801561044257600080fd5b50610456610451366004615051565b6114b8565b6040516102cb9392919061530d565b34801561047157600080fd5b50610321610480366004615051565b6114f7565b34801561049157600080fd5b5061049a611519565b6040516102cb9b9a999897969594939291906151be565b3480156104bd57600080fd5b506104d16104cc366004614df7565b61167e565b6040516102cb9493929190615953565b3480156104ed57600080fd5b506103216104fc366004614df7565b6116c5565b34801561050d57600080fd5b506105166116e9565b6040516102cb919061515c565b34801561052f57600080fd5b5061054361053e366004614df7565b6116ee565b6040516102cb9392919061597e565b34801561055e57600080fd5b506102f461056d36600461502a565b61172e565b34801561057e57600080fd5b506102be611848565b34801561059357600080fd5b50610321611868565b3480156105a857600080fd5b506105bc6105b7366004615051565b611948565b6040516102cb93929190615a77565b3480156105d757600080fd5b50610516611988565b3480156105ec57600080fd5b506102f46119ac565b34801561060157600080fd5b5061060a6119bd565b6040516102cb919061547f565b34801561062357600080fd5b5061062c611a77565b6040516102cb969594939291906159a8565b34801561064a57600080fd5b506102f4610659366004614eb8565b611abd565b34801561066a57600080fd5b506102a7611acd565b34801561067f57600080fd5b506102a7611ed9565b34801561069457600080fd5b5061069d61202b565b6040516102cb91906152be565b3480156106b657600080fd5b5061034361208e565b3480156106cb57600080fd5b506102a76120b4565b3480156106e057600080fd5b506103216106ef366004615069565b61253a565b34801561070057600080fd5b5061032161070f366004614e13565b612557565b34801561072057600080fd5b5061032161072f366004615069565b61258b565b34801561074057600080fd5b50610749612665565b6040516102cb9190615262565b6102f46126db565b34801561076a57600080fd5b506102a7610779366004615104565b612711565b34801561078a57600080fd5b5061079e610799366004615051565b612842565b6040516102cb929190615939565b6007546107d45760405162461bcd60e51b81526004016107cb90615870565b60405180910390fd5b60085460075460001901600090815260016020526040902054600160801b90910463ffffffff16906001600160401b0316806108225760405162461bcd60e51b81526004016107cb90615809565b6040516301e5ddfb60e71b81526000906001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0169063f2eefd8090610871908690600401615a38565b60006040518083038186803b15801561088957600080fd5b505afa15801561089d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108c59190810190614f2b565b915050816001600160401b031681106109035750506008805463ffffffff909216600160801b0263ffffffff60801b19909216919091179055610912565b60018301925050610822565b50505b565b604051806040016040528060158152602001744c49454e5f41474752454741544f525f534841524560581b81525081565b600060001982141561095c576001600160801b0391505b61096582612879565b336000818152600c602090815260408083206001600160a01b03891680855292529182902080546001600160801b0319166001600160801b039590951694909417909355517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109d790869061532b565b60405180910390a35060015b92915050565b6001600160a01b0382166000908152600b60209081526040808320546009909252909120546001600160801b0391821691600160801b90910416156109e35733600090815260096020526040902054600754600193506001600160801b0390911610156109e357336000818152600960208181526040808420546001600160801b0380821660010181168652600684529185205495909452919052610ab792610ab092600160801b91829004831692610aaa92909104166305f5e1006128a2565b906128dc565b600161291e565b0192915050565b6007546000908152600d6020908152604080832054600e909252909120546001600160801b0391821691169091565b6007546000908152600e60209081526040808320546006909252822054610b20916001600160801b039182169116612942565b90505b90565b6001600160a01b0383166000908152600c602090815260408083203384529091528120546001600160801b031682811015610b65576000915050610c11565b6001600160801b0381811614610bf7576001600160a01b0385166000908152600c60209081526040808320338452909152902054610bb590610bb0906001600160801b031685612942565b612879565b6001600160a01b0386166000908152600c60209081526040808320338452909152902080546001600160801b0319166001600160801b03929092169190911790555b610c0a8585610c0586612879565b612984565b5060019150505b9392505050565b60405163300da2f160e11b81526000906001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169063601b45e290610cab907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d90869060040161523e565b60206040518083038186803b158015610cc357600080fd5b505afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190615009565b90506103e88160010b13158015610d16575060058160010b12155b610d325760405162461bcd60e51b81526004016107cb9061571c565b6040516311ed607760e01b81526000906001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd716906311ed607790610d8490309060019060040161518a565b60206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190614ff1565b905060007f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b03166311ed60773060006040518363ffffffff1660e01b8152600401610e2792919061518a565b60206040518083038186803b158015610e3f57600080fd5b505afa158015610e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e779190614ff1565b905060007f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663488abbfc307f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06040518363ffffffff1660e01b8152600401610ee9929190615170565b60206040518083038186803b158015610f0157600080fd5b505afa158015610f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f399190614ff1565b604051631711ddb160e21b81529091506001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd71690635c4776c490610fce9086907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0908a90600401615334565b600060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b5050604051631711ddb160e21b81526001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7169250635c4776c491506110929085907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0908a90600401615334565b600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b5050600054604051630ccb63b760e41b81526001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd78116945063ccb63b70935061113d9286929116907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d09081908b9060040161535c565b600060405180830381600087803b15801561115757600080fd5b505af115801561116b573d6000803e3d6000fd5b50506008805460019790970b61ffff16600160a01b0261ffff60a01b19909716969096179095555050505050565b600881565b6007546000908152600d6020526040812054610b20903031906001600160801b0316612942565b6007546000818152600e602090815260408083205460059092528220549192839290916001600160801b031690600160401b900460ff1680611205575081155b6112215760405162461bcd60e51b81526004016107cb90615536565b6000828152600660205260409020546001600160801b031680156112a657600061124961119e565b9050611260610ab083610aaa846305f5e1006128a2565b6000858152600d602052604090205490955061129e90869061128f906001600160801b03166305f5e1006128a2565b8161129657fe5b04600161291e565b9550506112f0565b6000838152600d60205260409020546001600160801b0316156112f0576000838152600d60205260409020546112e6906001600160801b0316600161291e565b94506305f5e10093505b8085016112fc85612879565b60018501600090815260066020526040902080546001600160801b03928316600160801b029216919091179055611340610bb08461133a858a612a40565b90612942565b60018501600090815260066020526040902080546001600160801b0319166001600160801b0392831617908190556c2af31dc4611873bf3f70834acd91161115611398576008805460ff60b01b1916600160b01b1790555b83156113a6576113a6612a65565b6000811180156113b65750600083115b156113c4576113c485612b95565b6113cc612bfb565b6113d7600754613151565b6008546007546000908152600160208190526040918290205491516001600160401b03948516947fb6468ad5c9ad279cc97382791cf54035b2adbdc6126bee312967c4fdbb9a56da9461143794600160a01b90910490930b9216906154e7565b60405180910390a2505050505050565b6001600160a01b0381166000908152600b60209081526040808320815160608101835290546001600160801b03811682526001600160401b03600160801b8204811694830194909452600160c01b9004909216908201526007546114ab9190613176565b90505b919050565b601290565b60008080836114c75760075493505b50505060009081526005602052604090205460ff600160401b8204169163ffffffff600160201b83048116921690565b600090815260066020526040902054600160801b90046001600160801b031690565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0907f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e907f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000003b9aca00906c2af31dc4611873bf3f70834acd90565b6001600160a01b0316600090815260096020908152604080832054600a909252909120546001600160801b0380831693600160801b93849004821693828416930490911690565b6001600160a01b03166000908152600b60205260409020546001600160801b031690565b600090565b6001600160a01b03166000908152600b60205260409020546001600160801b038116916001600160401b03600160c01b8304811692600160801b90041690565b600080600061173b613309565b600754336000908152600a60205260409020549295509093509150600160801b90046001600160801b031661179357336000908152600a6020526040902080546001600160801b0319166001600160801b0383161790555b336000818152600a6020908152604080832080546001600160801b03600160801b80830482168d0182160291811691909117909155858452600e9092529091208054808316890183166001600160801b0319919091161790556117fb919085908816856134c1565b80336001600160a01b03167f3518f79326efc4570db0ebb1195252c857df4c2beb5932ab886faa94251a50e0876040516118359190615925565b60405180910390a3506001949350505050565b6040518060400160405280600481526020016309882a6960e31b81525081565b6007546000908152600160205260408120546001600160401b03164211156118a25760405162461bcd60e51b81526004016107cb90615600565b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190614ff1565b905061194281613646565b91505090565b60008080836119575760075493505b505050600090815260016020819052604090912080549101546001600160401b0380831693600160401b9093041691565b7f00000000000000000000000026541e091025d4601aed5ca7d8c7e0755fdf738b90565b600854600160b01b900460ff161590565b6000600754600014156119d257506000610b23565b6007546000908152600160205260409020546001600160401b03164211611a22576008546001600160401b03600160401b909104166203f480014211611a1a57506002610b23565b506001610b23565b6007546000908152600160205260409020546001600160401b031642118015611a645750600754600090815260056020526040902054600160401b900460ff16155b15611a7157506003610b23565b50600490565b6007546008549091600160a01b820460010b91600160801b810463ffffffff16916001600160401b0380831692600160401b810490911691600160b01b90910460ff1690565b6000610c113384610c0585612879565b6007546000908152600160205260409020546001600160401b0316421115611b075760405162461bcd60e51b81526004016107cb90615600565b6008546001600160401b03600160401b909104166203f480014211611b3e5760405162461bcd60e51b81526004016107cb90615596565b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd39190614ff1565b90506000611be08261393b565b905080611bf357611bf082613646565b90505b600080611bfe614db9565b6007546000908152600260205260409081902060085491516329069bdd60e01b81526001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd416926329069bdd92611cb1927f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef09230928b928d926001600160401b0316907f00000000000000000000000000000000000000000000000000000000000000009060040161538d565b60806040518083038186803b158015611cc957600080fd5b505afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d01919061508a565b919450925090508115611d83577f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663439370b1836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050505b8215611d9357611d938484613ad4565b602081015115611e5c578051602082015160405163b9601d7760e01b81527f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03169263b9601d7792611dee926004016159e7565b602060405180830381600087803b158015611e0857600080fd5b505af1158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e409190614fd5565b611e5c5760405162461bcd60e51b81526004016107cb9061577c565b611e6542613151565b6008805467ffffffffffffffff60401b1916600160401b6001600160401b039384160217905581516020830151604051918316928716917f2eaafc32eed9e5ff41c1b57ddd1ef894ec4eb7499efb581d50edffa27f6af23291611eca91889190615a5d565b60405180910390a35050505050565b611ee1614dd7565b50336000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754611f42908290613176565b6001600160401b03908116602083018190526007549091166040830152611f7b5760405162461bcd60e51b81526004016107cb906156d2565b60208181018051600080835233808252600b909452604090819020855181549451928701516001600160801b03199095166001600160801b039091161767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b9483169490940293909317909255169061090f906001600160a01b037f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e169083613b9a565b60075460009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561208457602002820191906000526020600020905b815481526020019060010190808311612070575b5050505050905090565b600080600061209b613309565b919450925090506120af33836000846134c1565b509091565b6007546000908152600160205260409020546001600160401b031642116120ed5760405162461bcd60e51b81526004016107cb906158df565b600754600081815260056020526040902054600160401b900460ff16156121265760405162461bcd60e51b81526004016107cb90615904565b60008181526005602052604090205463ffffffff166121ff576121d87f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b031663ac3fd8866040518163ffffffff1660e01b815260040160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190614ff1565b613bf5565b6000828152600560205260409020805463ffffffff191663ffffffff929092169190911790555b6000818152600160205260408082205460001984018352818320549151631c1b06f760e11b8152839283926001600160401b039081169291169083906001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd716906338360dee9061227a90309060040161515c565b60206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca9190614ff1565b90508015612346577f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663a0ef91df6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561232d57600080fd5b505af1158015612341573d6000803e3d6000fd5b505050505b50600086815260056020526040902054600160201b900463ffffffff1661237e57600854600160801b900463ffffffff16935061239d565b600086815260056020526040902054600160201b900463ffffffff1693505b600086815260056020526040902054603263ffffffff91821686900390911611156123ff576000868152600560205260409020805463ffffffff60328701908116600160201b0267ffffffff0000000019909216919091179091559450612417565b60008681526005602052604090205463ffffffff1694505b63ffffffff84165b8563ffffffff168110156124c25761243981858585613c1a565b935060098463ffffffff1611156124ba576001860363ffffffff1681141561247f576000878152600560205260409020805460ff60401b1916600160401b1790556124ae565b6000878152600560205260409020805467ffffffff000000001916600160201b6001840163ffffffff16021790555b50505050505050610912565b60010161241f565b5060008681526005602052604090205463ffffffff86811691161415612506576000868152600560205260409020805460ff60401b1916600160401b179055612532565b6000868152600560205260409020805467ffffffff000000001916600160201b63ffffffff8816021790555b505050505050565b600091825260036020908152604080842092845291905290205490565b6001600160a01b039182166000908152600c602090815260408083209390941682529190915220546001600160801b031690565b6008546040516351d19dc760e11b81526000916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a3a33b8e916125ea9186916001600160401b031690600190600401615a16565b60206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a9190614ff1565b9150826126475760075492505b50600091825260036020908152604080842092845291905290205490565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156126d257600084815260209081902060408051808201909152908401546001600160401b038082168352600160401b9091041681830152825260019092019101612689565b50505050905090565b600854600090600160b01b900460ff16156127085760405162461bcd60e51b81526004016107cb906156f5565b610b2034613df2565b336001600160a01b037f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d8016146127595760405162461bcd60e51b81526004016107cb906156ab565b6007546127785760405162461bcd60e51b81526004016107cb90615870565b6305f5e1006001600160401b038216108015906127a45750655af3107a40006001600160401b03821611155b6127c05760405162461bcd60e51b81526004016107cb9061579d565b600460405180604001604052806127d8600754613151565b60019081016001600160401b03908116835294851660209283015283549081018455600093845292819020825193018054929091015167ffffffffffffffff199092169284169290921767ffffffffffffffff60401b1916600160401b9190931602919091179055565b600080826128505760075492505b50506000908152600660205260409020546001600160801b0380821692600160801b9092041690565b6000600160801b821061289e5760405162461bcd60e51b81526004016107cb906155b9565b5090565b6000826128b1575060006109e3565b828202828482816128be57fe5b0414610c115760405162461bcd60e51b81526004016107cb90615624565b6000610c1183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f0c565b6000811561293457506402540be40082046109e3565b506402540be40082026109e3565b6000610c1183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613f43565b6001600160a01b0383166000908152600b60205260408120546001600160801b03808416911610156129b857506000610c11565b6129cf84836001600160801b031660001902613f6f565b6129e283836001600160801b0316613f6f565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846001600160801b0316604051612a2e919061532b565b60405180910390a35060019392505050565b600082820183811015610c115760405162461bcd60e51b81526004016107cb9061555f565b6008546007546000818152600660205260408082205460019384018352918190205490516379b347db60e01b81526001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd416946379b347db94612b5b94600160a01b909204900b926001600160801b03600160801b928390048116939290910416907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f0000000000000000000000000000000000000000000000000000000000000000906004016154a1565b600060405180830381600087803b158015612b7557600080fd5b505af1158015612b89573d6000803e3d6000fd5b50505050610912610c18565b6007546000908152600e6020526040812054612bcf90612bc8906305f5e10090610aaa906001600160801b0316866128a2565b600061291e565b905061090f7f00000000000000000000000026541e091025d4601aed5ca7d8c7e0755fdf738b826140d8565b60007f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd46001600160a01b031663ca579d0a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e9190614ff1565b905060007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612ced57600080fd5b505af1158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d259190614ff1565b600854604051637298096d60e11b81529192506000916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163e53012da91612da89186916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b158015612dc057600080fd5b505afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df89190614ff1565b9050612e03826140fb565b60007f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b8176001600160a01b031663a38593887f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0612e5e85613151565b612e6788613151565b6040518463ffffffff1660e01b8152600401612e8593929190615455565b602060405180830381600087803b158015612e9f57600080fd5b505af1158015612eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed79190614ff1565b905060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b836040518263ffffffff1660e01b8152600401612f27919061532b565b60806040518083038186803b158015612f3f57600080fd5b505afa158015612f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f779190614ee3565b505060405163095ea7b360e01b8152919250506001600160a01b0382169063095ea7b390612fcd907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b158015612fe757600080fd5b505af1158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614fd5565b50600780546001019055613031614dd7565b604051806060016040528061304588613151565b6001600160401b0316815260200161305c86613151565b6001600160401b039081168252602091820186905260075460009081526001808452604091829020855181549587015167ffffffffffffffff199096169085161767ffffffffffffffff60401b1916600160401b959094169490940292909217835583810151929091019190915551631d3b07f760e21b81529091507f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d06001600160a01b0316906374ec1fdc9061311790899060040161532b565b600060405180830381600087803b15801561313157600080fd5b505af1158015613145573d6000803e3d6000fd5b50505050505050505050565b6000600160401b821061289e5760405162461bcd60e51b81526004016107cb90615665565b602082015182516001600160801b0316158015906131a057508183604001516001600160401b0316105b156109e357600480546000198101916000916001600160401b0384169081106131c557fe5b6000918252602082200154600480546001600160401b039283169450909185169081106131ee57fe5b600091825260209091200154600160401b90046001600160401b03169050845b86604001516001600160401b03168111156132ff57826001600160401b03168110156132a1576001840393506004846001600160401b03168154811061325057fe5b9060005260206000200160000160089054906101000a90046001600160401b031691506004846001600160401b03168154811061328957fe5b6000918252602090912001546001600160401b031692505b60008181526006602052604090205487516132f4916132ef916132df916001600160801b0390811691610aaa916001600160401b03891691166128a2565b6001600160401b03881690612a40565b613151565b94506000190161320e565b5050505092915050565b600754336000908152600a602090815260408083205460099092528220549192839283926001600160801b0380821692600160801b92839004821692818316929104168461336657600080600097509750975050505050506134bc565b6001600160801b038316158015906133865750836001600160801b031685115b156133ef576001600160801b036001850181166000908152600660205260409020546133cc91612bc8916305f5e10091610aaa9188821691600160801b909104166128a2565b975087156133de576133de33896141da565b336000908152600a60205260408120555b6001600160801b0381161580159061340f5750816001600160801b031685115b15613472576001600160801b0360018301811660009081526006602052604090205461345391610ab091600160801b9004811690610aaa9085166305f5e1006128a2565b3360009081526009602052604081205596506001600160801b03821695505b84336001600160a01b03167fb11715e80d7e8d99a84fdd2112e0c3b821523d7416cb2082ec62d76c76f6f0168a8a6040516134ae9291906159e7565b60405180910390a350505050505b909192565b6134c9614dd7565b506001600160a01b0384166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b9004909116918101919091528315613571576135358183613176565b6001600160401b03908116602083015282166040820152805161356590610bb0906001600160801b031686612a40565b6001600160801b031681525b61357d81600754613176565b6001600160401b03908116602083015260075416604082015282156135c15780516135b590610bb0906001600160801b031685612942565b6001600160801b031681525b6001600160a01b03949094166000908152600b6020908152604091829020865181549288015193909701516001600160801b03199092166001600160801b039097169690961767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b929091169190910217909355505050565b60085460405163a072a3e560e01b815260009182916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a072a3e5916136c89187916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b1580156136e057600080fd5b505afa1580156136f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137189190614ff1565b600754909150613726614dd7565b50600081815260016020818152604092839020835160608101855281546001600160401b038082168352600160401b9091041692810183905292015492820192909252906137749084614256565b602082015182516040808501519051635b1caa5760e11b81529396506001600160a01b037f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817169363b63954ae936137f1937f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0938a9360040161541e565b602060405180830381600087803b15801561380b57600080fd5b505af115801561381f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138439190614ff1565b93507f0000000000000000000000000000000000000000000000000000000000000000156139295760085460405163a072a3e560e01b81526139249186916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a072a3e5916138cf918b916001600160401b03909116906000906004016159f5565b60206040518083038186803b1580156138e757600080fd5b505afa1580156138fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391f9190614ff1565b614280565b613933565b6139338484614280565b505050919050565b6008546040516351d19dc760e11b815260009182916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a3a33b8e9161399e9187916001600160401b0390911690600190600401615a16565b60206040518083038186803b1580156139b657600080fd5b505afa1580156139ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ee9190614ff1565b600754600090815260036020908152604080832084845291829052909120549192509015613a2a576000918252602052604090205490506114ae565b60015b60028111613933576008546001600160401b03168102830360009081526020839052604090205415613a80576008546001600160401b0316029091036000908152602091909152604090205490506114ae565b6008546001600160401b03168102830160009081526020839052604090205415613acc576008546001600160401b031602919091016000908152602091909152604090205490506114ae565b600101613a2d565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b038116638376c24d613b256103e8610aaa6103ea613b1f886402540be4006128a2565b906128a2565b856040518363ffffffff1660e01b8152600401613b42919061532b565b6020604051808303818588803b158015613b5b57600080fd5b505af1158015613b6f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613b949190614ff1565b50505050565b613bf08363a9059cbb60e01b8484604051602401613bb99291906151a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614962565b505050565b6000600160201b821061289e5760405162461bcd60e51b81526004016107cb906157c3565b6000606060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b031663f2eefd80886040518263ffffffff1660e01b8152600401613c6c919061532b565b60006040518083038186803b158015613c8457600080fd5b505afa158015613c98573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc09190810190614f2b565b91509150846001600160401b0316811180613cf65750836001600160401b031681108015613cf657506001600160401b03841615155b15613d05578592505050613dea565b6000805b8351811015613de25760007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b868481518110613d4f57fe5b60200260200101516040518263ffffffff1660e01b8152600401613d73919061532b565b60806040518083038186803b158015613d8b57600080fd5b505afa158015613d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dc39190614ee3565b5050509050613dd48a828b866149f1565b909950925050600101613d09565b508693505050505b949350505050565b6000806000613dff613309565b9250925050613e1133836000846134c1565b60075433600090815260096020526040902054600160801b90046001600160801b0316613e615733600090815260096020526040902080546001600160801b0319166001600160801b0383161790555b613e6a85612879565b33600090815260096020526040902080546001600160801b03600160801b808304821690940181169093029216919091179055613ea685612879565b6000828152600d60205260409081902080546001600160801b031981166001600160801b0391821694909401169290921790915551819033907f4c86739b331ba35e12897451019b4a8cca47a228be900c18ab3a8ffa5dfe7e539061183590899061532b565b60008183613f2d5760405162461bcd60e51b81526004016107cb9190615503565b506000838581613f3957fe5b0495945050505050565b60008184841115613f675760405162461bcd60e51b81526004016107cb9190615503565b505050900390565b613f77614dd7565b506001600160a01b0382166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754613fe1908290613176565b6001600160401b039081166020830152600754166040820152600082121561403057805161402090610bb0906001600160801b03166000859003612942565b6001600160801b03168152614055565b805161404990610bb0906001600160801b031684612a40565b6001600160801b031681525b6001600160a01b03929092166000908152600b6020908152604091829020845181549286015193909501516001600160801b03199092166001600160801b039095169490941767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b92909116919091021790915550565b61090f82826040518060600160405280602c8152602001615b37602c9139614bb0565b6000614133826001600160401b0360327f000000000000000000000000000000000000000000000000000000003b9aca0002166128dc565b90508061417b576008805467ffffffffffffffff19167f000000000000000000000000000000000000000000000000000000003b9aca006001600160401b031617905561090f565b6141b5600a6001600160401b037f000000000000000000000000000000000000000000000000000000003b9aca0016830260190204613151565b6008805467ffffffffffffffff19166001600160401b03929092169190911790555050565b60405163ed3de48760e01b81526001600160a01b037f00000000000000000000000026541e091025d4601aed5ca7d8c7e0755fdf738b169063ed3de4879061422890859085906004016151a5565b600060405180830381600087803b15801561424257600080fd5b505af1158015612532573d6000803e3d6000fd5b6000610c116002614270846001600160401b038716612942565b8161427757fe5b84919006612942565b60078054600090815260026020908152604080832080546001810182559084528284200186905592548252600381528282208483529052819020839055516301e5ddfb60e71b81526060906001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0169063f2eefd809061430a90869060040161532b565b60006040518083038186803b15801561432257600080fd5b505afa158015614336573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261435e9190810190614f2b565b50905060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8360018151811061439f57fe5b60200260200101516040518263ffffffff1660e01b81526004016143c3919061532b565b60806040518083038186803b1580156143db57600080fd5b505afa1580156143ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144139190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906144679030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561447f57600080fd5b505afa158015614493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b79190614ff1565b61455f5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061450b907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455d9190614fd5565b505b60007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8460028151811061459d57fe5b60200260200101516040518263ffffffff1660e01b81526004016145c1919061532b565b60806040518083038186803b1580156145d957600080fd5b505afa1580156145ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146119190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906146659030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561467d57600080fd5b505afa158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b59190614ff1565b61475d5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614709907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561472357600080fd5b505af1158015614737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061475b9190614fd5565b505b60007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8560038151811061479b57fe5b60200260200101516040518263ffffffff1660e01b81526004016147bf919061532b565b60806040518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906148639030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561487b57600080fd5b505afa15801561488f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b39190614ff1565b6125325760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614907907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561492157600080fd5b505af1158015614935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149599190614fd5565b50505050505050565b60606149b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614ca69092919063ffffffff16565b805190915015613bf057808060200190518101906149d59190614fd5565b613bf05760405162461bcd60e51b81526004016107cb90615895565b6040516370a0823160e01b81526000908190859082906001600160a01b038316906370a0823190614a2690309060040161515c565b60206040518083038186803b158015614a3e57600080fd5b505afa158015614a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a769190614ff1565b1115614ba35783614b28576040516301bc8ef560e61b81526001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef01690636f23bd4090614ad0908a906000906004016159e7565b602060405180830381600087803b158015614aea57600080fd5b505af1158015614afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b229190614ff1565b50600193505b806001600160a01b0316639975038c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b9b9190614ff1565b506001850194505b5092959194509092505050565b614bb982614cb5565b8190614bd85760405162461bcd60e51b81526004016107cb9190615503565b506000836001600160a01b031683604051614bf290610b23565b60006040518083038185875af1925050503d8060008114614c2f576040519150601f19603f3d011682016040523d82523d6000602084013e614c34565b606091505b5050905080614c555760405162461bcd60e51b81526004016107cb90615745565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c85604051614c98919061532b565b60405180910390a350505050565b6060613dea8484600085614cbc565b3031101590565b6060614cc785614d80565b614ce35760405162461bcd60e51b81526004016107cb90615839565b60006060866001600160a01b03168587604051614d009190615140565b60006040518083038185875af1925050503d8060008114614d3d576040519150601f19603f3d011682016040523d82523d6000602084013e614d42565b606091505b50915091508115614d56579150613dea9050565b805115614d665780518082602001fd5b8360405162461bcd60e51b81526004016107cb9190615503565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613dea575050151592915050565b60405180604001604052806002906020820280368337509192915050565b604080516060810182526000808252602082018190529181019190915290565b600060208284031215614e08578081fd5b8135610c1181615afb565b60008060408385031215614e25578081fd5b8235614e3081615afb565b91506020830135614e4081615afb565b809150509250929050565b600080600060608486031215614e5f578081fd5b8335614e6a81615afb565b92506020840135614e7a81615afb565b929592945050506040919091013590565b60008060408385031215614e9d578182fd5b8235614ea881615afb565b91506020830135614e4081615b13565b60008060408385031215614eca578182fd5b8235614ed581615afb565b946020939093013593505050565b60008060008060808587031215614ef8578081fd5b8451614f0381615afb565b602086015160408701519195509350614f1b81615b21565b6060959095015193969295505050565b60008060408385031215614f3d578182fd5b82516001600160401b0380821115614f53578384fd5b818501915085601f830112614f66578384fd5b815181811115614f74578485fd5b60209150818102614f86838201615aa9565b8281528381019085850183870186018b1015614fa0578889fd5b8896505b84871015614fc2578051835260019690960195918501918501614fa4565b5097909301519698969750505050505050565b600060208284031215614fe6578081fd5b8151610c1181615b13565b600060208284031215615002578081fd5b5051919050565b60006020828403121561501a578081fd5b81518060010b8114610c11578182fd5b60006020828403121561503b578081fd5b81356001600160801b0381168114610c11578182fd5b600060208284031215615062578081fd5b5035919050565b6000806040838503121561507b578182fd5b50508035926020909101359150565b60008060006080848603121561509e578081fd5b83519250602080850151925085605f8601126150b8578182fd5b6150c26040615aa9565b8060408701886080890111156150d6578485fd5b845b60028110156150f5578151845292840192908401906001016150d8565b50508093505050509250925092565b600060208284031215615115578081fd5b8135610c1181615b21565b15159052565b6001600160801b03169052565b6001600160401b03169052565b60008251615152818460208701615acf565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038c811682528b811660208301528a811660408301528981166060830152888116608083015287811660a083015286811660c0830152851660e08201528315156101008201526001600160401b038316610120820152610160810161522e610140830184615126565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152901515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156152b157815180516001600160401b039081168652908701511686850152928401929085019060010161527f565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152f6578351835292840192918401916001016152da565b50909695505050505050565b901515815260200190565b921515835263ffffffff918216602084015216604082015260600190565b90815260200190565b9384526001600160a01b0392831660208501529116604083015260010b606082015260800190565b9485526001600160a01b0393841660208601529183166040850152909116606083015260010b608082015260a00190565b600060e0820160018060a01b03808b1684526020818b168186015289604086015288606086015260e060808601528291508754808452610100860192508885528185209350845b818110156153f0578454845260019485019493830193016153d4565b505050809250505061540560a0830185615133565b61541260c0830184615120565b98975050505050505050565b6001600160a01b0395909516855260208501939093526001600160401b039182166040850152166060830152608082015260a00190565b6001600160a01b039390931683526001600160401b03918216602084015216604082015260600190565b602081016005831061548d57fe5b91905290565b60019190910b815260200190565b60019690960b86526001600160801b0394851660208701529290931660408501526001600160a01b0390811660608501529091166080830152151560a082015260c00190565b60019290920b82526001600160401b0316602082015260400190565b6000602082528251806020840152615522816040850160208701615acf565b601f01601f19169190910160400192915050565b6020808252600f908201526e139bdd08195e1c1a5c9959081e595d608a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260099082015268436f6f6c2054696d6560b81b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600a90820152694e6f742061637469766560b01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b6020808252600d908201526c27b7363c90383937bb34b232b960991b604082015260600190565b602080825260099082015268139bc814995dd85c9960ba1b604082015260600190565b6020808252600d908201526c556e7361666520737570706c7960981b604082015260600190565b6020808252600f908201526e496e76616c6964206665656261736560881b604082015260600190565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252600790820152665265766572736560c81b604082015260600190565b6020808252600c908201526b4f7574206f662072616e676560a01b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360408201526532206269747360d01b606082015260800190565b60208082526016908201527513585d1d5c9a5d1e481cda1bdd591b1908195e1a5cdd60521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a4e6f742072756e6e696e6760a81b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600b908201526a139bdd0813585d1d5c995960aa1b604082015260600190565b602080825260079082015266115e1c1a5c995960ca1b604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526001600160401b03918216602084015216604082015260600190565b95865260019490940b602086015263ffffffff9290921660408501526001600160401b039081166060850152166080830152151560a082015260c00190565b918252602082015260400190565b9283526001600160401b039190911660208301521515604082015260600190565b9283526001600160401b0391909116602083015260ff16604082015260600190565b63ffffffff91909116815260200190565b6001600160401b0391909116815260200190565b6001600160401b0392831681529116602082015260400190565b6001600160401b039384168152919092166020820152604081019190915260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ac757600080fd5b604052919050565b60005b83811015615aea578181015183820152602001615ad2565b83811115613b945750506000910152565b6001600160a01b0381168114615b1057600080fd5b50565b8015158114615b1057600080fd5b6001600160401b0381168114615b1057600080fdfe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a264697066735822122002e2720145b831229dc25d43b34aff7140055dd20fc8f575bd19116ae9ed92a464736f6c63430007010033

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

0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d00000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b81700000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000174876e800

-----Decoded View---------------
Arg [0] : _ethOracle (address): 0x6e33f11625b2c8B7270cf8e0319b8B9fFB8F086D
Arg [1] : _pricer (address): 0x965666E465c48DaCc15e001aa7327B707EA2B7D0
Arg [2] : strategy (address): 0x5EE7B5b9845Cae2a8fD2E02e0Bf6cE6F83EbcFd4
Arg [3] : _rewardToken (address): 0xaB37e1358b639Fd877f015027Bb62d3ddAa7557E
Arg [4] : _registrator (address): 0xAAd52946E078Cd22D79050146d81a295bbC2b817
Arg [5] : exchangeAddress (address): 0x23f8477C9F19389069535720e3bA66A2b95d5DD7
Arg [6] : _volOracle (address): 0xc8BBb8d57CEbF834DC429ec4D65DD23eD0d65a87
Arg [7] : _priceUnit (uint64): 1000000000
Arg [8] : _firstRewardRate (uint64): 100000000000

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d
Arg [1] : 000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0
Arg [2] : 0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4
Arg [3] : 000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e
Arg [4] : 000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817
Arg [5] : 00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7
Arg [6] : 000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87
Arg [7] : 000000000000000000000000000000000000000000000000000000003b9aca00
Arg [8] : 000000000000000000000000000000000000000000000000000000174876e800


Deployed Bytecode Sourcemap

122130:4128:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120449:52;;120484:4;;120464:10;;120449:52;;;;120491:9;;120449:52;:::i;:::-;;;;;;;;122130:4128;;;;;95978:557;;;;;;;;;;;;;:::i;:::-;;85343:62;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110957:313;;;;;;;;;;-1:-1:-1;110957:313:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;116632:820::-;;;;;;;;;;-1:-1:-1;116632:820:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;118689:180::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;112827:169::-;;;;;;;;;;;;;:::i;111557:625::-;;;;;;;;;;-1:-1:-1;111557:625:0;;;;;:::i;:::-;;:::i;123554:795::-;;;;;;;;;;;;;:::i;85239:43::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;125866:159::-;;;;;;;;;;;;;:::i;88561:1968::-;;;;;;;;;;;;;:::i;118291:146::-;;;;;;;;;;-1:-1:-1;118291:146:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;126033:99::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;114019:515::-;;;;;;;;;;-1:-1:-1;114019:515:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;119027:149::-;;;;;;;;;;-1:-1:-1;119027:149:0;;;;;:::i;:::-;;:::i;115242:902::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;113004:496::-;;;;;;;;;;-1:-1:-1;113004:496:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;112700:119::-;;;;;;;;;;-1:-1:-1;112700:119:0;;;;;:::i;:::-;;:::i;125339:109::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;119413:308::-;;;;;;;;;;-1:-1:-1;119413:308:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;92980:645::-;;;;;;;;;;-1:-1:-1;92980:645:0;;;;;:::i;:::-;;:::i;85289:47::-;;;;;;;;;;;;;:::i;98886:208::-;;;;;;;;;;;;;:::i;116152:384::-;;;;;;;;;;-1:-1:-1;116152:384:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;126140:115::-;;;;;;;;;;;;;:::i;118570:111::-;;;;;;;;;;;;;:::i;117529:673::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;113508:503::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;111278:169::-;;;;;;;;;;-1:-1:-1;111278:169:0;;;;;:::i;:::-;;:::i;99206:1315::-;;;;;;;;;;;;;:::i;110359:478::-;;;;;;;;;;;;;:::i;119806:140::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;95476:296::-;;;;;;;;;;;;;:::i;96699:2179::-;;;;;;;;;;;;;:::i;119184:221::-;;;;;;;;;;-1:-1:-1;119184:221:0;;;;;:::i;:::-;;:::i;118877:142::-;;;;;;;;;;-1:-1:-1;118877:142:0;;;;;:::i;:::-;;:::i;114877:357::-;;;;;;;;;;-1:-1:-1;114877:357:0;;;;;:::i;:::-;;:::i;118445:117::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;124428:130::-;;;:::i;90758:272::-;;;;;;;;;;-1:-1:-1;90758:272:0;;;;;:::i;:::-;;:::i;114542:327::-;;;;;;;;;;-1:-1:-1;114542:327:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;95978:557::-;86838:11;;86830:40;;;;-1:-1:-1;;;86830:40:0;;;;;;;:::i;:::-;;;;;;;;;96078:16:::1;::::0;96140:11:::1;::::0;-1:-1:-1;;96140:15:0;96051:24:::1;96131:25:::0;;;:8:::1;:25;::::0;;;;:34;-1:-1:-1;;;96078:16:0;;::::1;;;::::0;-1:-1:-1;;;;;96131:34:0::1;::::0;96176:56:::1;;;;-1:-1:-1::0;;;96176:56:0::1;;;;;;;:::i;:::-;96294:41;::::0;-1:-1:-1;;;96294:41:0;;96274:16:::1;::::0;-1:-1:-1;;;;;96294:9:0::1;:22;::::0;::::1;::::0;:41:::1;::::0;96317:17;;96294:41:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;96294:41:0::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;96271:64;;;96366:16;-1:-1:-1::0;;;;;96354:28:0::1;:8;:28;96350:130;;-1:-1:-1::0;;96403:16:0::1;:36:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;96403:36:0::1;-1:-1:-1::0;;;;96403:36:0;;::::1;::::0;;;::::1;::::0;;96458:7:::1;;96350:130;96515:1;96494:22;;;;96243:285;;;;86881:1;;;95978:557::o:0;85343:62::-;;;;;;;;;;;;;;-1:-1:-1;;;85343:62:0;;;;:::o;110957:313::-;111034:4;-1:-1:-1;;111055:6:0;:21;111051:74;;;-1:-1:-1;;;;;111093:20:0;-1:-1:-1;111051:74:0;111169:18;:6;:16;:18::i;:::-;111146:10;111135:22;;;;:10;:22;;;;;;;;-1:-1:-1;;;;;111135:31:0;;;;;;;;;;;:52;;-1:-1:-1;;;;;;111135:52:0;-1:-1:-1;;;;;111135:52:0;;;;;;;;;;;111203:37;;;;;111233:6;;111203:37;:::i;:::-;;;;;;;;-1:-1:-1;111258:4:0;110957:313;;;;;:::o;116632:820::-;-1:-1:-1;;;;;116822:13:0;;116763:23;116822:13;;;:7;:13;;;;;;;;:21;116858:19;:25;;;;;;:31;-1:-1:-1;;;;;116822:21:0;;;;-1:-1:-1;;;116858:31:0;;;;:36;116854:591;;116985:10;116965:31;;;;:19;:31;;;;;:36;116951:11;;116928:4;;-1:-1:-1;;;;;;116965:36:0;;;-1:-1:-1;116947:487:0;;;117243:10;117213:51;117223:31;;;:19;:31;;;;;;;;:36;-1:-1:-1;;;;;117223:36:0;;;;:40;117213:51;;;;:9;:51;;;;;:109;117088:31;;;;;;;117041:377;;117080:292;;-1:-1:-1;;;117213:109:0;;;;;;;117080:64;;117088:37;;;;117131:12;117080:50;:64::i;:::-;:68;;:292::i;:::-;117395:4;117041:16;:377::i;:::-;117022:396;116632:820;;;;:::o;118689:180::-;118813:11;;118752:7;118789:36;;;:23;:36;;;;;;;;;118827:20;:33;;;;;;;-1:-1:-1;;;;;118789:36:0;;;;118827:33;118689:180;;:::o;112827:169::-;112975:11;;112880:7;112954:33;;;:20;:33;;;;;;;;;112915:9;:22;;;;;:33;112907:81;;-1:-1:-1;;;;;112915:33:0;;;;112954;112907:46;:81::i;:::-;112900:88;;112827:169;;:::o;111557:625::-;-1:-1:-1;;;;;111735:18:0;;111691:4;111735:18;;;:10;:18;;;;;;;;111754:10;111735:30;;;;;;;;-1:-1:-1;;;;;111735:30:0;111780:25;;;111776:70;;;111829:5;111822:12;;;;;111776:70;-1:-1:-1;;;;;111897:31:0;;;;111893:196;;-1:-1:-1;;;;;111986:18:0;;;;;;:10;:18;;;;;;;;112005:10;111986:30;;;;;;;;111978:99;;:69;;-1:-1:-1;;;;;111986:30:0;112040:6;111978:61;:69::i;:::-;:97;:99::i;:::-;-1:-1:-1;;;;;111945:18:0;;;;;;:10;:18;;;;;;;;111964:10;111945:30;;;;;;;:132;;-1:-1:-1;;;;;;111945:132:0;-1:-1:-1;;;;;111945:132:0;;;;;;;;;;111893:196;112099:53;112114:6;112122:9;112133:18;:6;:16;:18::i;:::-;112099:14;:53::i;:::-;;112170:4;112163:11;;;111557:625;;;;;;:::o;123554:795::-;123629:56;;-1:-1:-1;;;123629:56:0;;123605:21;;-1:-1:-1;;;;;123629:8:0;:25;;;;:56;;123655:5;;123670:6;;123605:21;;123629:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123605:80;;123725:4;123706:15;:23;;;;:47;;;;;123752:1;123733:15;:20;;;;123706:47;123698:75;;;;-1:-1:-1;;;123698:75:0;;;;;;;:::i;:::-;123808:45;;-1:-1:-1;;;123808:45:0;;123784:21;;-1:-1:-1;;;;;123808:4:0;:24;;;;:45;;123841:4;;123848;;123808:45;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123784:69;;123864:20;123887:4;-1:-1:-1;;;;;123887:24:0;;123920:4;123927:5;123887:46;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123864:69;;123946:18;123967:4;-1:-1:-1;;;;;123967:25:0;;124001:4;124016:9;123967:60;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124040:73;;-1:-1:-1;;;124040:73:0;;123946:81;;-1:-1:-1;;;;;;124040:4:0;:20;;;;:73;;124061:13;;124076:6;;124084:11;;124097:15;;124040:73;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;124126:72:0;;-1:-1:-1;;;124126:72:0;;-1:-1:-1;;;;;124126:4:0;:20;;-1:-1:-1;124126:20:0;;-1:-1:-1;124126:72:0;;124147:12;;124161:6;;124169:11;;124182:15;;124126:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;124245:9:0;;124211:87;;-1:-1:-1;;;124211:87:0;;-1:-1:-1;;;;;124211:4:0;:21;;;-1:-1:-1;124211:21:0;;-1:-1:-1;124211:87:0;;124233:10;;124245:9;;;124256:11;;;;124282:15;;124211:87;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;124309:14:0;:32;;;;;;;;;-1:-1:-1;;;124309:32:0;-1:-1:-1;;;;124309:32:0;;;;;;;;;;-1:-1:-1;;;;;123554:795:0:o;85239:43::-;85281:1;85239:43;:::o;125866:159::-;126004:11;;125927:7;125980:36;;;:23;:36;;;;;;125954:63;;125962:4;125954:21;;-1:-1:-1;;;;;125980:36:0;125954:25;:63::i;88561:1968::-;88711:11;;88613:25;88760:34;;;:20;:34;;;;;;;;;88813:15;:29;;;;;:42;88613:25;;;;88711:11;;-1:-1:-1;;;;;88760:34:0;;-1:-1:-1;;;88813:42:0;;;;;:63;;-1:-1:-1;88859:17:0;;88813:63;88805:91;;;;-1:-1:-1;;;88805:91:0;;;;;;;:::i;:::-;88907:18;88928:23;;;:9;:23;;;;;:34;-1:-1:-1;;;;;88928:34:0;88977:14;;88973:683;;89008:24;89035:21;:19;:21::i;:::-;89008:48;-1:-1:-1;89094:123:0;89129:50;89168:10;89129:34;89008:48;89150:12;89129:20;:34::i;89094:123::-;89295:37;;;;:23;:37;;;;;;89071:146;;-1:-1:-1;89252:181:0;;89071:146;;89287:64;;-1:-1:-1;;;;;89295:37:0;89338:12;89287:50;:64::i;:::-;:108;;;;;;89414:4;89252:16;:181::i;:::-;89232:201;;88973:683;;;;89495:1;89455:37;;;:23;:37;;;;;;-1:-1:-1;;;;;89455:37:0;:41;89451:205;;89550:37;;;;:23;:37;;;;;;89533:61;;-1:-1:-1;;;;;89550:37:0;;89533:16;:61::i;:::-;89513:81;-1:-1:-1;89632:12:0;;-1:-1:-1;89451:205:0;89691:30;;;89786:32;:20;:30;:32::i;:::-;89757:1;89742:16;;89732:27;;;;:9;:27;;;;;:86;;-1:-1:-1;;;;;89732:86:0;;;-1:-1:-1;;;89732:86:0;;;;;;;;;89870:118;:92;89945:16;89870:56;89878:10;89908:17;89870:37;:56::i;:::-;:74;;:92::i;:118::-;89854:1;89839:16;;89829:27;;;;:9;:27;;;;;:159;;-1:-1:-1;;;;;;89829:159:0;-1:-1:-1;;;;;89829:159:0;;;;;;;;90073:49;90019:38;;:103;90001:186;;;90149:19;:26;;-1:-1:-1;;;;90149:26:0;-1:-1:-1;;;90149:26:0;;;90001:186;90203:17;;90199:66;;90237:16;:14;:16::i;:::-;90296:1;90281:12;:16;:40;;;;;90320:1;90301:16;:20;90281:40;90277:108;;;90338:35;90352:20;90338:13;:35::i;:::-;90395:22;:20;:22::i;:::-;90450;:11;;:20;:22::i;:::-;90474:14;;90499:11;;90490:21;;;;90474:14;90490:21;;;;;;;;;:30;90435:86;;-1:-1:-1;;;;;90435:86:0;;;;;;;;-1:-1:-1;;;90474:14:0;;;;;;;90490:30;;90435:86;:::i;:::-;;;;;;;;88561:1968;;;;;;:::o;118291:146::-;-1:-1:-1;;;;;118402:13:0;;118360:6;118402:13;;;:7;:13;;;;;;;;118386:43;;;;;;;;;-1:-1:-1;;;;;118386:43:0;;;;-1:-1:-1;;;;;;;;118386:43:0;;;;;;;;;;;-1:-1:-1;;;118386:43:0;;;;;;;;;118417:11;;118386:43;;;:15;:43::i;:::-;118379:50;;118291:146;;;;:::o;126033:99::-;126122:2;126033:99;:::o;114019:515::-;114141:17;;;114269:9;114265:60;;114302:11;;114295:18;;114265:60;-1:-1:-1;;;114350:21:0;;;;:15;:21;;;;;:34;;-1:-1:-1;;;114350:34:0;;;;114419:43;-1:-1:-1;;;114419:43:0;;;;;114490:36;;114019:515::o;119027:149::-;119102:7;119129:15;;;:9;:15;;;;;:39;-1:-1:-1;;;119129:39:0;;-1:-1:-1;;;;;119129:39:0;;119027:149::o;115242:902::-;115760:9;;115793:8;;115825:4;;115853:11;;115888:6;;115918:12;;115954:16;;115986:5;;116006:14;;116035:15;;116073:51;;115242:902::o;113004:496::-;-1:-1:-1;;;;;113322:25:0;113117:30;113322:25;;;:19;:25;;;;;;;;:30;113413:15;:21;;;;;;:26;-1:-1:-1;;;;;113322:30:0;;;;-1:-1:-1;;;113367:31:0;;;;;;;113413:26;;;;113454:27;;;;;113004:496::o;112700:119::-;-1:-1:-1;;;;;112790:13:0;112763:7;112790:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;112790:21:0;;112700:119::o;125339:109::-;125403:7;125339:109;:::o;119413:308::-;-1:-1:-1;;;;;119643:13:0;119533:14;119643:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;119643:21:0;;;-1:-1:-1;;;;;;;;119666:18:0;;;;;-1:-1:-1;;;119686:26:0;;;;119413:308::o;92980:645::-;93048:12;93076:19;93097:24;93125:15;:13;:15::i;:::-;93174:11;;93216:10;93151:20;93200:27;;;:15;:27;;;;;:33;93073:67;;-1:-1:-1;93073:67:0;;-1:-1:-1;93174:11:0;-1:-1:-1;;;;93200:33:0;;-1:-1:-1;;;;;93200:33:0;93196:127;;93271:10;93255:27;;;;:15;:27;;;;;:56;;-1:-1:-1;;;;;;93255:56:0;-1:-1:-1;;;;;93255:56:0;;;;;93196:127;93349:10;93333:27;;;;:15;:27;;;;;;;;:43;;-1:-1:-1;;;;;;;;93333:43:0;;;;;;;;;;;;;;;;;;;;93387:34;;;:20;:34;;;;;;:44;;;;;;;;;-1:-1:-1;;;;;;93387:44:0;;;;;;;93442:85;;93349:10;93489:11;;93442:85;;93510:16;93442:34;:85::i;:::-;93574:12;93562:10;-1:-1:-1;;;;;93543:52:0;;93588:6;93543:52;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;93613:4:0;;92980:645;-1:-1:-1;;;;92980:645:0:o;85289:47::-;;;;;;;;;;;;;;-1:-1:-1;;;85289:47:0;;;;:::o;98886:208::-;86470:11;;98954:19;86461:21;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86461:30:0;86442:15;:49;;86434:72;;;;-1:-1:-1;;;86434:72:0;;;;;;;:::i;:::-;98986:22:::1;99011:6;-1:-1:-1::0;;;;;99011:18:0::1;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98986:45;;99049:37;99071:14;99049:21;:37::i;:::-;99042:44;;;98886:208:::0;:::o;116152:384::-;116267:15;;;116380:9;116376:60;;116413:11;;116406:18;;116376:60;-1:-1:-1;;;116454:14:0;;;;:8;:14;;;;;;;;:23;;116507:20;;;-1:-1:-1;;;;;116454:23:0;;;;-1:-1:-1;;;116479:26:0;;;;;116152:384::o;126140:115::-;126236:10;126140:115;:::o;118570:111::-;118654:19;;-1:-1:-1;;;118654:19:0;;;;118653:20;;118570:111::o;117529:673::-;117586:15;117618:11;;117633:1;117618:16;117614:540;;;-1:-1:-1;117658:28:0;117651:35;;117614:540;117736:11;;117727:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;117727:30:0;117708:15;:49;117704:450;;117797:15;;-1:-1:-1;;;;;;;;117797:15:0;;;;83732:13;117797:26;117778:15;:45;117774:118;;-1:-1:-1;117851:25:0;117844:32;;117774:118;-1:-1:-1;117913:22:0;117906:29;;117704:450;117998:11;;117989:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;117989:30:0;117971:15;:48;:107;;;;-1:-1:-1;118053:11:0;;118037:28;;;;:15;:28;;;;;:41;-1:-1:-1;;;118037:41:0;;;;118036:42;117971:107;117953:201;;;-1:-1:-1;118112:30:0;118105:37;;117953:201;-1:-1:-1;118171:23:0;117529:673;:::o;113508:503::-;113833:11;;113859:14;;113833:11;;-1:-1:-1;;;113859:14:0;;;;;-1:-1:-1;;;113888:16:0;;;;;-1:-1:-1;;;;;113919:9:0;;;;-1:-1:-1;;;113943:15:0;;;;;;-1:-1:-1;;;113973:19:0;;;;;;113508:503::o;111278:169::-;111358:4;111382:57;111397:10;111409:9;111420:18;:6;:16;:18::i;99206:1315::-;86470:11;;86461:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86461:30:0;86442:15;:49;;86434:72;;;;-1:-1:-1;;;86434:72:0;;;;;;;:::i;:::-;86594:15:::1;::::0;-1:-1:-1;;;;;;;;86594:15:0;;::::1;;83732:13;86594:26;86576:15;:44;86568:66;;;;-1:-1:-1::0;;;86568:66:0::1;;;;;;;:::i;:::-;99280:22:::2;99305:6;-1:-1:-1::0;;;;;99305:18:0::2;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99280:45;;99336:19;99358:37;99380:14;99358:21;:37::i;:::-;99336:59:::0;-1:-1:-1;99410:16:0;99406:100:::2;;99457:37;99479:14;99457:21;:37::i;:::-;99443:51;;99406:100;99519:14;99535:17:::0;99554:30:::2;;:::i;:::-;99769:11;::::0;99748:33:::2;::::0;;;:20:::2;:33;::::0;;;;;;99796:9:::2;::::0;99588:257;;-1:-1:-1;;;99588:257:0;;-1:-1:-1;;;;;99588:8:0::2;:38;::::0;::::2;::::0;:257:::2;::::0;99641:9:::2;::::0;99673:4:::2;::::0;99693:11;;99719:14;;-1:-1:-1;;;;;99796:9:0::2;::::0;99820:14:::2;::::0;99588:257:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99518:327:::0;;-1:-1:-1;99518:327:0;-1:-1:-1;99518:327:0;-1:-1:-1;99862:13:0;;99858:81:::2;;99892:4;-1:-1:-1::0;;;;;99892:15:0::2;;99915:9;99892:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;99858:81;99955:10:::0;;99951:75:::2;;99982:32;99994:11;100007:6;99982:11;:32::i;:::-;100042:15;::::0;::::2;::::0;:19;100038:244:::2;;100194:15:::0;;::::2;100211::::0;::::2;::::0;100155:72:::2;::::0;-1:-1:-1;;;100155:72:0;;:9:::2;-1:-1:-1::0;;;;;100155:38:0::2;::::0;::::2;::::0;:72:::2;::::0;::::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100129:141;;;;-1:-1:-1::0;;;100129:141:0::2;;;;;;;:::i;:::-;100310:26;:15;:24;:26::i;:::-;100292:15;:44:::0;;-1:-1:-1;;;;100292:44:0::2;-1:-1:-1::0;;;;;;;;100292:44:0;;::::2;;;::::0;;100448:15;;::::2;100486::::0;::::2;::::0;100352:161:::2;::::0;;;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;100419:6;;100486:15;100352:161:::2;:::i;:::-;;;;;;;;86645:1;;;;;99206:1315::o:0;110359:478::-;110409:27;;:::i;:::-;-1:-1:-1;110447:10:0;110439:19;;;;:7;:19;;;;;;;;;110409:49;;;;;;;;;-1:-1:-1;;;;;110409:49:0;;;;-1:-1:-1;;;;;;;;110409:49:0;;;;;;;;;;;-1:-1:-1;;;110409:49:0;;;;;;;;;;;;110519:11;;110493:38;;110409:49;;110493:15;:38::i;:::-;-1:-1:-1;;;;;110469:62:0;;;:21;;;:62;;;110565:11;;110542:35;;;:13;;;:35;110588:47;;;;-1:-1:-1;;;110588:47:0;;;;;;;:::i;:::-;110669:21;;;;;;110646:20;110701:25;;;110745:10;110737:19;;;:7;:19;;;;;;;;:30;;;;;;;;;;-1:-1:-1;;;;;;110737:30:0;;;-1:-1:-1;;;;;110737:30:0;;;;-1:-1:-1;;;;110737:30:0;-1:-1:-1;;;;;;;;110737:30:0;;;;;-1:-1:-1;;;;;110737:30:0;-1:-1:-1;;;110737:30:0;;;;;;;;;;;;;;110646:44;;110778:51;;-1:-1:-1;;;;;110778:12:0;:25;;110646:44;110778:25;:51::i;119806:140::-;119926:11;;119905:33;;;;:20;:33;;;;;;;;;119898:40;;;;;;;;;;;;;;;;;119869:16;;119898:40;;;119905:33;119898:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119806:140;:::o;95476:296::-;95527:17;95546:19;95578:24;95658:15;:13;:15::i;:::-;95613:60;;-1:-1:-1;95613:60:0;-1:-1:-1;95613:60:0;-1:-1:-1;95684:80:0;95719:10;95613:60;95744:1;95613:60;95684:34;:80::i;:::-;95476:296;;;:::o;96699:2179::-;86733:11;;86724:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86724:30:0;86706:15;:48;86698:72;;;;-1:-1:-1;;;86698:72:0;;;;;;;:::i;:::-;96789:11:::1;::::0;96766:20:::1;96820:29:::0;;;:15:::1;:29;::::0;;;;:42;-1:-1:-1;;;96820:42:0;::::1;;;96819:43;96811:63;;;;-1:-1:-1::0;;;96811:63:0::1;;;;;;;:::i;:::-;96889:29;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;;96885:167;;97002:38;:9;-1:-1:-1::0;;;;;97002:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36;:38::i;:::-;96955:29;::::0;;;:15:::1;:29;::::0;;;;:85;;-1:-1:-1;;96955:85:0::1;;::::0;;;::::1;::::0;;;::::1;::::0;;96885:167:::1;97109:15;97218:22:::0;;;:8:::1;:22;::::0;;;;;:31;-1:-1:-1;;97295:16:0;;97286:26;;;;;:35;97370:32;;-1:-1:-1;;;97370:32:0;;97109:15;;;;-1:-1:-1;;;;;97218:31:0;;::::1;::::0;97286:35;::::1;::::0;97109:15;;-1:-1:-1;;;;;97370:4:0::1;:17;::::0;::::1;::::0;:32:::1;::::0;97396:4:::1;::::0;97370:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97347:55:::0;-1:-1:-1;97421:16:0;;97417:75:::1;;97458:4;-1:-1:-1::0;;;;;97458:16:0::1;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;97417:75;-1:-1:-1::0;97519:29:0::1;::::0;;;:15:::1;:29;::::0;;;;:51;-1:-1:-1;;;97519:51:0;::::1;;;97515:215;;97605:16;::::0;-1:-1:-1;;;97605:16:0;::::1;;;::::0;-1:-1:-1;97515:215:0::1;;;97667:29;::::0;;;:15:::1;:29;::::0;;;;:51;-1:-1:-1;;;97667:51:0;::::1;;;::::0;-1:-1:-1;97515:215:0::1;97746:29;::::0;;;:15:::1;:29;::::0;;;;:44;97806:2:::1;97746:44;::::0;;::::1;:57:::0;;::::1;:62:::0;;::::1;;97742:286;;;97866:29;::::0;;;:15:::1;:29;::::0;;;;:62;;::::1;97849:2;97836:15:::0;::::1;97866:62:::0;;::::1;-1:-1:-1::0;;;97866:62:0::1;-1:-1:-1::0;;97866:62:0;;::::1;::::0;;;::::1;::::0;;;97836:15;-1:-1:-1;97742:286:0::1;;;97972:29;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;;::::0;-1:-1:-1;97742:286:0::1;98045:22;::::0;::::1;98040:586;98073:8;98069:12;;:1;:12;98040:586;;;98125:154;98163:1;98183:19;98221:8;98248:16;98125:19;:154::i;:::-;98103:176;;98322:1;98300:19;:23;;;98296:319;;;98364:1;98353:8;:12;98348:17;;:1;:17;98344:231;;;98390:29;::::0;;;:15:::1;:29;::::0;;;;:49;;-1:-1:-1;;;;98390:49:0::1;-1:-1:-1::0;;;98390:49:0::1;::::0;;98344:231:::1;;;98488:29;::::0;;;:15:::1;:29;::::0;;;;:67;;-1:-1:-1;;98488:67:0::1;-1:-1:-1::0;;;98553:1:0::1;98549:5:::0;::::1;98488:67;;;;::::0;;98344:231:::1;98593:7;;;;;;;;;98296:319;98083:3;;98040:586;;;-1:-1:-1::0;98654:29:0::1;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;98642:56:::0;;::::1;98654:44:::0;::::1;98642:56;98638:233;;;98715:29;::::0;;;:15:::1;:29;::::0;;;;:49;;-1:-1:-1;;;;98715:49:0::1;-1:-1:-1::0;;;98715:49:0::1;::::0;;98638:233:::1;;;98797:29;::::0;;;:15:::1;:29;::::0;;;;:62;;-1:-1:-1;;98797:62:0::1;-1:-1:-1::0;;;98797:62:0::1;::::0;::::1;;;::::0;;98638:233:::1;86781:1;;;;;;96699:2179::o:0;119184:221::-;119324:7;119356:28;;;:22;:28;;;;;;;;:41;;;;;;;;;;119184:221::o;118877:142::-;-1:-1:-1;;;;;118985:17:0;;;118958:7;118985:17;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;-1:-1:-1;;;;;118985:26:0;;118877:142::o;114877:357::-;115088:9;;115057:44;;-1:-1:-1;;;115057:44:0;;115012:19;;-1:-1:-1;;;;;115057:8:0;:23;;;;:44;;115081:5;;-1:-1:-1;;;;;115088:9:0;;;;115057:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115049:52;-1:-1:-1;115118:9:0;115114:60;;115151:11;;115144:18;;115114:60;-1:-1:-1;115191:28:0;;;;:22;:28;;;;;;;;:35;;;;;;;;;;114877:357::o;118445:117::-;118502:20;118542:12;118535:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;118535:19:0;;;;;-1:-1:-1;;;118535:19:0;;;;;;;;;;;;;;;;;;;;;;;;;118445:117;:::o;124428:130::-;87041:19;;124491:12;;-1:-1:-1;;;87041:19:0;;;;87040:20;87032:46;;;;-1:-1:-1;;;87032:46:0;;;;;;;:::i;:::-;124526:24:::1;124540:9;124526:13;:24::i;90758:272::-:0;87154:10;-1:-1:-1;;;;;87168:5:0;87154:19;;87146:45;;;;-1:-1:-1;;;87146:45:0;;;;;;;:::i;:::-;86838:11:::1;::::0;86830:40:::1;;;;-1:-1:-1::0;;;86830:40:0::1;;;;;;;:::i;:::-;90872:12:::0;-1:-1:-1;;;;;90858:26:0;::::2;;::::0;::::2;::::0;:66:::2;;-1:-1:-1::0;90902:22:0;-1:-1:-1;;;;;90888:36:0;::::2;;;90858:66;90850:91;;;;-1:-1:-1::0;;;90850:91:0::2;;;;;;;:::i;:::-;90952:12;90970:51;;;;;;;;90982:22;:11;;:20;:22::i;:::-;91007:1;90982:26:::0;;::::2;-1:-1:-1::0;;;;;90970:51:0;;::::2;::::0;;;;::::2;;::::0;;::::2;::::0;90952:70;;;;::::2;::::0;;-1:-1:-1;90952:70:0;;;;;;;;;;::::2;::::0;;;;;::::2;::::0;-1:-1:-1;;90952:70:0;;::::2;::::0;;::::2;::::0;;;::::2;-1:-1:-1::0;;;;90952:70:0::2;-1:-1:-1::0;;;90952:70:0;;;::::2;;::::0;;;::::2;::::0;;90758:272::o;114542:327::-;114646:18;;114719:9;114715:60;;114752:11;;114745:18;;114715:60;-1:-1:-1;;114793:15:0;;;;:9;:15;;;;;:26;-1:-1:-1;;;;;114793:26:0;;;;-1:-1:-1;;;114821:39:0;;;;;114542:327::o;45582:184::-;45639:7;-1:-1:-1;;;45667:5:0;:14;45659:67;;;;-1:-1:-1;;;45659:67:0;;;;;;;:::i;:::-;-1:-1:-1;45752:5:0;45582:184::o;18937:471::-;18995:7;19240:6;19236:47;;-1:-1:-1;19270:1:0;19263:8;;19236:47;19307:5;;;19311:1;19307;:5;:1;19331:5;;;;;:10;19323:56;;;;-1:-1:-1;;;19323:56:0;;;;;;;:::i;19884:132::-;19942:7;19969:39;19973:1;19976;19969:39;;;;;;;;;;;;;;;;;:3;:39::i;125533:246::-;125619:7;125643:5;125639:133;;;-1:-1:-1;125681:15:0;125672:24;;125665:31;;125639:133;-1:-1:-1;125745:15:0;125736:24;;125729:31;;18047:136;18105:7;18132:43;18136:1;18139;18132:43;;;;;;;;;;;;;;;;;:3;:43::i;112297:395::-;-1:-1:-1;;;;;112436:13:0;;112415:4;112436:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;112436:30:0;;;:21;;:30;112432:75;;;-1:-1:-1;112490:5:0;112483:12;;112432:75;112517:45;112536:4;112554:6;-1:-1:-1;;;;;112547:14:0;-1:-1:-1;;112542:19:0;112517:18;:45::i;:::-;112573:38;112592:2;112603:6;-1:-1:-1;;;;;112596:14:0;112573:18;:38::i;:::-;112642:2;-1:-1:-1;;;;;112627:35:0;112636:4;-1:-1:-1;;;;;112627:35:0;;112654:6;-1:-1:-1;;;;;112646:15:0;112627:35;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;112680:4:0;112297:395;;;;;:::o;17583:181::-;17641:7;17673:5;;;17697:6;;;;17689:46;;;;-1:-1:-1;;;17689:46:0;;;;;;;:::i;105557:355::-;105649:14;;105688:11;;105678:22;;;;:9;:22;;;;;;:46;105649:14;105749:15;;;105739:26;;;;;;:50;105603:276;;-1:-1:-1;;;105603:276:0;;-1:-1:-1;;;;;105603:8:0;:31;;;;:276;;-1:-1:-1;;;105649:14:0;;;;;;-1:-1:-1;;;;;;;;105678:46:0;;;;;;;105739:50;;;;;;105804:5;;105832:6;;105854:14;;105603:276;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105890:14;:12;:14::i;124705:307::-;124864:11;;124787:14;124843:33;;;:20;:33;;;;;;124804:148;;124835:86;;124908:12;;124835:68;;-1:-1:-1;;;;;124843:33:0;124882:20;124835:46;:68::i;:86::-;124936:5;124804:16;:148::i;:::-;124787:165;;124963:41;124984:10;124997:6;124963:12;:41::i;91038:1015::-;91090:21;91114:8;-1:-1:-1;;;;;91114:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91090:51;;91152:22;91177:6;-1:-1:-1;;;;;91177:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91311:9;;91237:123;;-1:-1:-1;;;91237:123:0;;91152:45;;-1:-1:-1;91208:26:0;;-1:-1:-1;;;;;91237:8:0;:30;;;;:123;;91152:45;;-1:-1:-1;;;;;91311:9:0;;;;91335:14;;91237:123;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91208:152;;91373:32;91390:14;91373:16;:32::i;:::-;91457:13;91473:16;-1:-1:-1;;;;;91473:28:0;;91516:9;91540:29;:18;:27;:29::i;:::-;91584:24;:13;:22;:24::i;:::-;91473:146;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91457:162;;91631:18;91659:9;-1:-1:-1;;;;;91659:17:0;;91677:5;91659:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;91694:51:0;;-1:-1:-1;;;91694:51:0;;91630:53;;-1:-1:-1;;;;;;;91694:26:0;;;;;:51;;91729:4;;-1:-1:-1;;83694:2:0;91694:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;91758:11:0;:16;;91773:1;91758:16;;;91785:27;;:::i;:::-;91815:122;;;;;;;;91838:24;:13;:22;:24::i;:::-;-1:-1:-1;;;;;91815:122:0;;;;;91877:29;:18;:27;:29::i;:::-;-1:-1:-1;;;;;91815:122:0;;;;;;;;;;;;91957:11;;-1:-1:-1;91948:21:0;;;:8;:21;;;;;;;;:35;;;;;;;;-1:-1:-1;;91948:35:0;;;;;;;-1:-1:-1;;;;91948:35:0;-1:-1:-1;;;91948:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;91994:51;-1:-1:-1;;;91994:51:0;;91948:35;;-1:-1:-1;91994:11:0;-1:-1:-1;;;;;91994:36:0;;;;:51;;92031:13;;91994:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91038:1015;;;;;;:::o;46065:179::-;46121:6;-1:-1:-1;;;46148:5:0;:13;46140:65;;;;-1:-1:-1;;;46140:65:0;;;;;;;:::i;109014:1224::-;109187:24;;;;109226:19;;-1:-1:-1;;;;;109226:23:0;;;;;:50;;;109272:4;109253:11;:16;;;-1:-1:-1;;;;;109253:23:0;;109226:50;109222:1009;;;109315:12;:19;;-1:-1:-1;;109315:23:0;;;109293:12;;-1:-1:-1;;;;;109377:19:0;;;;;;;;;;;;;;;;;:24;109437:12;:19;;-1:-1:-1;;;;;109377:24:0;;;;-1:-1:-1;109437:12:0;;:19;;;;;;;;;;;;;;;;;;:25;-1:-1:-1;;;109437:25:0;;-1:-1:-1;;;;;109437:25:0;;-1:-1:-1;109496:4:0;109479:741;109506:11;:16;;;-1:-1:-1;;;;;109502:20:0;:1;:20;109479:741;;;109556:13;-1:-1:-1;;;;;109552:17:0;:1;:17;109548:323;;;109725:1;109716:10;;;;109763:12;109776:5;-1:-1:-1;;;;;109763:19:0;;;;;;;;;;;;;;;;:25;;;;;;;;;;-1:-1:-1;;;;;109763:25:0;109749:39;;109827:12;109840:5;-1:-1:-1;;;;;109827:19:0;;;;;;;;;;;;;;;;;;:24;-1:-1:-1;;;;;109827:24:0;;-1:-1:-1;109548:323:0;110128:12;;;;:9;:12;;;;;:23;110102:19;;110006:198;;:165;;110076:76;;-1:-1:-1;;;;;110128:23:0;;;;110077:45;;-1:-1:-1;;;;;110077:20:0;;;:45;:24;:45::i;110076:76::-;-1:-1:-1;;;;;110006:21:0;;;:47;:165::i;:::-;:196;:198::i;:::-;109991:213;-1:-1:-1;;;109524:3:0;109479:741;;;;109222:1009;;;109014:1224;;;;:::o;93633:1697::-;93849:11;;93921:10;93708:17;93905:27;;;:15;:27;;;;;;;;:32;94058:19;:31;;;;;:36;93708:17;;;;;;-1:-1:-1;;;;;93905:32:0;;;;-1:-1:-1;;;93983:33:0;;;;;;;94058:36;;;;94137:37;;;94189:17;94185:66;;94231:1;94234;94237;94223:16;;;;;;;;;;;;;94185:66;-1:-1:-1;;;;;94267:29:0;;;;;;:71;;;94315:23;-1:-1:-1;;;;;94300:38:0;:12;:38;94267:71;94263:513;;;-1:-1:-1;;;;;94506:1:0;94480:27;;94472:36;;94462:47;;;;:9;:47;;;;;:71;94367:246;;94402:172;;94561:12;;94402:132;;:33;;;;-1:-1:-1;;;94462:71:0;;;;94402:59;:132::i;94367:246::-;94355:258;-1:-1:-1;94632:13:0;;94628:88;;94666:34;94678:10;94690:9;94666:11;:34::i;:::-;94753:10;94737:27;;;;:15;:27;;;;;94730:34;94263:513;-1:-1:-1;;;;;94792:26:0;;;;;;:65;;;94837:20;-1:-1:-1;;;;;94822:35:0;:12;:35;94792:65;94788:454;;;-1:-1:-1;;;;;95039:1:0;95016:24;;95006:35;;;;;;:9;:35;;;;;:59;94888:235;;94923:162;;-1:-1:-1;;;95006:59:0;;;;;94923:48;;:30;;94958:12;94923:34;:48::i;94888:235::-;95219:10;95199:31;;;;:19;:31;;;;;95192:38;94874:249;-1:-1:-1;;;;;;95138:39:0;;;-1:-1:-1;94788:454:0;95285:12;95273:10;-1:-1:-1;;;;;95257:65:0;;95299:9;95310:11;95257:65;;;;;;;:::i;:::-;;;;;;;;93633:1697;;;;;;;;;:::o;107791:1014::-;107968:30;;:::i;:::-;-1:-1:-1;;;;;;108001:14:0;;;;;;:7;:14;;;;;;;;;107968:47;;;;;;;;;-1:-1:-1;;;;;107968:47:0;;;;-1:-1:-1;;;;;;;;107968:47:0;;;;;;;;;;;-1:-1:-1;;;107968:47:0;;;;;;;;;;;;108083:14;;108079:313;;108141:34;108157:11;108170:4;108141:15;:34::i;:::-;-1:-1:-1;;;;;108114:61:0;;;:24;;;:61;108190:31;;:16;;;:31;108288:19;;108280:100;;:70;;-1:-1:-1;;;;;108280:28:0;108339:9;108280:50;:70::i;:100::-;-1:-1:-1;;;;;108258:122:0;;;108079:313;108481:41;108497:11;108510;;108481:15;:41::i;:::-;-1:-1:-1;;;;;108454:68:0;;;:24;;;:68;108559:11;;108533:38;:16;;;:38;108633:17;;108629:130;;108697:19;;108689:58;;:46;;-1:-1:-1;;;;;108689:28:0;108722:12;108689:32;:46::i;:58::-;-1:-1:-1;;;;;108667:80:0;;;108629:130;-1:-1:-1;;;;;108769:14:0;;;;;;;;:7;:14;;;;;;;;;:28;;;;;;;;;;;;;-1:-1:-1;;;;;;108769:28:0;;;-1:-1:-1;;;;;108769:28:0;;;;;;;-1:-1:-1;;;;108769:28:0;-1:-1:-1;;;;;;;;108769:28:0;;;;;-1:-1:-1;;;;;108769:28:0;-1:-1:-1;;;108769:28:0;;;;;;;;;;;;-1:-1:-1;;;107791:1014:0:o;103077:995::-;103280:9;;103208:121;;-1:-1:-1;;;103208:121:0;;103150:19;;;;-1:-1:-1;;;;;103208:8:0;:28;;;;:121;;103251:14;;-1:-1:-1;;;;;103280:9:0;;;;103304:14;;103208:121;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103363:11;;103182:147;;-1:-1:-1;103385:20:0;;:::i;:::-;-1:-1:-1;103408:22:0;;;;:8;:22;;;;;;;;;103385:45;;;;;;;;;-1:-1:-1;;;;;103385:45:0;;;;;-1:-1:-1;;;103385:45:0;;;;;;;;;;;;;;;;;;;;;103459:47;;103490:15;103459:12;:47::i;:::-;103634:16;;;;103665:13;;103693:10;;;;;103531:183;;-1:-1:-1;;;103531:183:0;;103441:65;;-1:-1:-1;;;;;;103531:16:0;:34;;;;:183;;103580:9;;103441:65;;103531:183;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103517:197;;103807:14;103803:262;;;103945:9;;103900:62;;-1:-1:-1;;;103900:62:0;;103838:139;;103870:11;;-1:-1:-1;;;;;103900:8:0;:28;;;;:62;;103929:14;;-1:-1:-1;;;;;103945:9:0;;;;;;103900:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103838:13;:139::i;:::-;103803:262;;;104010:43;104024:11;104037:15;104010:13;:43::i;:::-;103077:995;;;;;;:::o;102187:882::-;102348:9;;102308:53;;-1:-1:-1;;;102308:53:0;;102265:7;;;;-1:-1:-1;;;;;102308:8:0;:23;;;;:53;;102332:14;;-1:-1:-1;;;;;102348:9:0;;;;;;102308:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102470:11;;102380:54;102447:35;;;:22;:35;;;;;;;;102497:32;;;;;;;;;;;102285:76;;-1:-1:-1;102447:35:0;102497:37;102493:109;;102558:32;;;;;;;;;;;-1:-1:-1;102551:39:0;;102493:109;102706:1;102689:373;102714:1;102709;:6;102689:373;;102775:9;;-1:-1:-1;;;;;102775:9:0;:13;;102760:28;;102741:48;;;;;;;;;;;;:53;102737:149;;102856:9;;-1:-1:-1;;;;;102856:9:0;:13;102841:28;;;102822:48;;;;;;;;;;;;;;-1:-1:-1;102815:55:0;;102737:149;102940:9;;-1:-1:-1;;;;;102940:9:0;:13;;102925:28;;102906:48;;;;;;;;;;;;:53;102902:149;;103021:9;;-1:-1:-1;;;;;103021:9:0;:13;103006:28;;;;102987:48;;;;;;;;;;;;;;-1:-1:-1;102980:55:0;;102902:149;102717:3;;102689:373;;125020:311;125206:9;-1:-1:-1;;;;;125238:16:0;;;125262:47;125304:4;125262:37;125294:4;125262:27;:6;125273:15;125262:10;:27::i;:::-;:31;;:37::i;:47::-;125311:11;125238:85;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;125020:311;;;:::o;79643:177::-;79726:86;79746:5;79776:23;;;79801:2;79805:5;79753:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;79753:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;79753:58:0;-1:-1:-1;;;;;;79753:58:0;;;;;;;;;;79726:19;:86::i;:::-;79643:177;;;:::o;46543:179::-;46599:6;-1:-1:-1;;;46626:5:0;:13;46618:65;;;;-1:-1:-1;;;46618:65:0;;;;;;;:::i;101328:851::-;101509:6;101529:24;101555:17;101576:9;-1:-1:-1;;;;;101576:22:0;;101599:11;101576:35;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;101576:35:0;;;;;;;;;;;;:::i;:::-;101528:83;;;;101638:8;-1:-1:-1;;;;;101626:20:0;:9;:20;:79;;;;101663:16;-1:-1:-1;;;;;101651:28:0;:9;:28;:53;;;;-1:-1:-1;;;;;;101683:21:0;;;;101651:53;101622:138;;;101729:19;101722:26;;;;;;101622:138;101770:17;;101798:337;101822:7;:14;101818:1;:18;101798:337;;;101859:19;101888:9;-1:-1:-1;;;;;101888:17:0;;101906:7;101914:1;101906:10;;;;;;;;;;;;;;101888:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101858:59;;;;;101970:153;101998:11;102028;102058:19;102096:12;101970:9;:153::i;:::-;101932:191;;-1:-1:-1;101932:191:0;-1:-1:-1;;101838:3:0;;101798:337;;;;102152:19;102145:26;;;;;101328:851;;;;;;;:::o;92061:665::-;92118:12;92146:19;92167:24;92195:15;:13;:15::i;:::-;92143:67;;;;;92221:80;92256:10;92268:11;92281:1;92284:16;92221:34;:80::i;:::-;92335:11;;92381:10;92312:20;92361:31;;;:19;:31;;;;;:37;-1:-1:-1;;;92361:37:0;;-1:-1:-1;;;;;92361:37:0;92357:135;;92440:10;92420:31;;;;:19;:31;;;;;:60;;-1:-1:-1;;;;;;92420:60:0;-1:-1:-1;;;;;92420:60:0;;;;;92357:135;92543:18;:6;:16;:18::i;:::-;92522:10;92502:31;;;;:19;:31;;;;;:59;;-1:-1:-1;;;;;;;;92502:59:0;;;;;;;;;;;;;;;;;;;;;92613:18;:6;:16;:18::i;:::-;92572:37;;;;:23;:37;;;;;;;:59;;-1:-1:-1;;;;;;92572:59:0;;-1:-1:-1;;;;;92572:59:0;;;;;;;;;;;;;;;92647:49;92572:37;;92663:10;;92647:49;;;;92689:6;;92647:49;:::i;20512:278::-;20598:7;20633:12;20626:5;20618:28;;;;-1:-1:-1;;;20618:28:0;;;;;;;;:::i;:::-;;20657:9;20673:1;20669;:5;;;;;;;20512:278;-1:-1:-1;;;;;20512:278:0:o;18486:192::-;18572:7;18608:12;18600:6;;;;18592:29;;;;-1:-1:-1;;;18592:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;18644:5:0;;;18486:192::o;107190:593::-;107268:30;;:::i;:::-;-1:-1:-1;;;;;;107301:14:0;;;;;;:7;:14;;;;;;;;;107268:47;;;;;;;;;-1:-1:-1;;;;;107268:47:0;;;;-1:-1:-1;;;;;;;;107268:47:0;;;;;;;;;;;-1:-1:-1;;;107268:47:0;;;;;;;;;;;;107382:11;;107353:41;;107268:47;;107353:15;:41::i;:::-;-1:-1:-1;;;;;107326:68:0;;;:24;;;:68;107431:11;;107405:38;:16;;;:38;-1:-1:-1;107458:10:0;;107454:283;;;107515:19;;107507:102;;:72;;-1:-1:-1;;;;;107507:28:0;107566:11;;;;107507:50;:72::i;:102::-;-1:-1:-1;;;;;107485:124:0;;;107454:283;;;107672:19;;107664:61;;:49;;-1:-1:-1;;;;;107664:28:0;107705:6;107664:32;:49::i;:61::-;-1:-1:-1;;;;;107642:83:0;;;107454:283;-1:-1:-1;;;;;107747:14:0;;;;;;;;:7;:14;;;;;;;;;:28;;;;;;;;;;;;;-1:-1:-1;;;;;;107747:28:0;;;-1:-1:-1;;;;;107747:28:0;;;;;;;-1:-1:-1;;;;107747:28:0;-1:-1:-1;;;;;;;;107747:28:0;;;;;-1:-1:-1;;;;;107747:28:0;-1:-1:-1;;;107747:28:0;;;;;;;;;;;;-1:-1:-1;107190:593:0:o;121252:172::-;121337:79;121350:9;121361:6;121337:79;;;;;;;;;;;;;;;;;:12;:79::i;105227:322::-;105297:18;105318:40;:14;-1:-1:-1;;;;;105337:2:0;105342:15;105337:20;105318:40;:18;:40::i;:::-;105297:61;-1:-1:-1;105373:15:0;105369:173;;105405:9;:27;;-1:-1:-1;;105405:27:0;105417:15;-1:-1:-1;;;;;105405:27:0;;;;105369:173;;;105477:53;105516:2;-1:-1:-1;;;;;105497:15:0;105479:33;;;:2;:33;105478:40;105477:51;:53::i;:::-;105465:9;:65;;-1:-1:-1;;105465:65:0;-1:-1:-1;;;;;105465:65:0;;;;;;;;;;-1:-1:-1;;105227:322:0:o;124566:131::-;124646:43;;-1:-1:-1;;;124646:43:0;;-1:-1:-1;;;;;124646:10:0;:20;;;;:43;;124675:4;;124682:6;;124646:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106112:220;106232:7;106264:60;106322:1;106284:35;:15;-1:-1:-1;;;;;106284:35:0;;:19;:35::i;:::-;:39;;;;;106264:15;;106284:39;;106264:19;:60::i;104080:1139::-;104235:11;;;104214:33;;;;:20;:33;;;;;;;;:51;;;;;;;;;;;;;;;;;104299:11;;104276:35;;:22;:35;;;;;:60;;;;;;;;:74;;;104394:35;-1:-1:-1;;;104394:35:0;;104364:24;;-1:-1:-1;;;;;104394:9:0;:22;;;;:35;;104253:11;;104394:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;104394:35:0;;;;;;;;;;;;:::i;:::-;104363:66;;;104441:24;104475:9;-1:-1:-1;;;;;104475:17:0;;104493:7;104501:1;104493:10;;;;;;;;;;;;;;104475:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;104565:64:0;;-1:-1:-1;;;104565:64:0;;104440;;-1:-1:-1;;;;;;;104565:34:0;;;;;:64;;104608:4;;104623;;104565:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104561:159;;104651:57;;-1:-1:-1;;;104651:57:0;;-1:-1:-1;;;;;104651:32:0;;;;;:57;;104692:4;;-1:-1:-1;;83694:2:0;104651:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104561:159;104733:24;104767:9;-1:-1:-1;;;;;104767:17:0;;104785:7;104793:1;104785:10;;;;;;;;;;;;;;104767:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;104813:64:0;;-1:-1:-1;;;104813:64:0;;104732;;-1:-1:-1;;;;;;;104813:34:0;;;;;:64;;104856:4;;104871;;104813:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104809:159;;104899:57;;-1:-1:-1;;;104899:57:0;;-1:-1:-1;;;;;104899:32:0;;;;;:57;;104940:4;;-1:-1:-1;;83694:2:0;104899:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104809:159;104979:24;105013:9;-1:-1:-1;;;;;105013:17:0;;105031:7;105039:1;105031:10;;;;;;;;;;;;;;105013:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;105057:64:0;;-1:-1:-1;;;105057:64:0;;104978;;-1:-1:-1;;;;;;;105057:34:0;;;;;:64;;105100:4;;105115;;105057:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105053:159;;105143:57;;-1:-1:-1;;;105143:57:0;;-1:-1:-1;;;;;105143:32:0;;;;;:57;;105184:4;;-1:-1:-1;;83694:2:0;105143:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104080:1139;;;;;;:::o;81948:761::-;82372:23;82398:69;82426:4;82398:69;;;;;;;;;;;;;;;;;82406:5;-1:-1:-1;;;;;82398:27:0;;;:69;;;;;:::i;:::-;82482:17;;82372:95;;-1:-1:-1;82482:21:0;82478:224;;82624:10;82613:30;;;;;;;;;;;;:::i;:::-;82605:85;;;;-1:-1:-1;;;82605:85:0;;;;;;;:::i;100529:791::-;100795:29;;-1:-1:-1;;;100795:29:0;;100698:6;;;;100768:11;;100698:6;;-1:-1:-1;;;;;100795:14:0;;;;;:29;;100818:4;;100795:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:33;100791:469;;;100850:12;100845:336;;101088:39;;-1:-1:-1;;;101088:39:0;;-1:-1:-1;;;;;101088:9:0;:23;;;;:39;;101112:11;;101125:1;;101088:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101161:4;101146:19;;100845:336;101195:4;-1:-1:-1;;;;;101195:12:0;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101247:1;101224:24;;;;100791:469;-1:-1:-1;101278:19:0;;101299:12;;-1:-1:-1;100529:791:0;;-1:-1:-1;;;100529:791:0:o;120808:436::-;120963:29;120985:6;120963:21;:29::i;:::-;120994:12;120955:52;;;;;-1:-1:-1;;;120955:52:0;;;;;;;;:::i;:::-;;121019:12;121037:9;-1:-1:-1;;;;;121037:14:0;121059:6;121037:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121018:52;;;121135:7;121127:45;;;;-1:-1:-1;;;121127:45:0;;;;;;;:::i;:::-;121218:9;-1:-1:-1;;;;;121188:48:0;121211:4;-1:-1:-1;;;;;121188:48:0;;121229:6;121188:48;;;;;;:::i;:::-;;;;;;;;120808:436;;;;:::o;25924:196::-;26027:12;26059:53;26082:6;26090:4;26096:1;26099:12;26059:22;:53::i;120517:182::-;120638:4;120671:20;-1:-1:-1;120661:30:0;;120517:182::o;27301:979::-;27431:12;27464:18;27475:6;27464:10;:18::i;:::-;27456:60;;;;-1:-1:-1;;;27456:60:0;;;;;;;:::i;:::-;27590:12;27604:23;27631:6;-1:-1:-1;;;;;27631:11:0;27651:8;27662:4;27631:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27589:78;;;;27682:7;27678:595;;;27713:10;-1:-1:-1;27706:17:0;;-1:-1:-1;27706:17:0;27678:595;27827:17;;:21;27823:439;;28090:10;28084:17;28151:15;28138:10;28134:2;28130:19;28123:44;28038:148;28233:12;28226:20;;-1:-1:-1;;;28226:20:0;;;;;;;;:::i;22809:619::-;22869:4;23337:20;;23180:66;23377:23;;;;;;:42;;-1:-1:-1;;23404:15:0;;;23369:51;-1:-1:-1;;22809:619:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2929:241::-;;3033:2;3021:9;3012:7;3008:23;3004:32;3001:2;;;-1:-1;;3039:12;3001:2;85:6;72:20;97:33;124:5;97:33;:::i;3177:366::-;;;3298:2;3286:9;3277:7;3273:23;3269:32;3266:2;;;-1:-1;;3304:12;3266:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3356:63;-1:-1;3456:2;3495:22;;72:20;97:33;72:20;97:33;:::i;:::-;3464:63;;;;3260:283;;;;;:::o;3550:491::-;;;;3688:2;3676:9;3667:7;3663:23;3659:32;3656:2;;;-1:-1;;3694:12;3656:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3746:63;-1:-1;3846:2;3885:22;;72:20;97:33;72:20;97:33;:::i;:::-;3650:391;;3854:63;;-1:-1;;;3954:2;3993:22;;;;2444:20;;3650:391::o;4048:360::-;;;4166:2;4154:9;4145:7;4141:23;4137:32;4134:2;;;-1:-1;;4172:12;4134:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4224:63;-1:-1;4324:2;4360:22;;1760:20;1785:30;1760:20;1785:30;:::i;4415:366::-;;;4536:2;4524:9;4515:7;4511:23;4507:32;4504:2;;;-1:-1;;4542:12;4504:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4594:63;4694:2;4733:22;;;;2444:20;;-1:-1;;;4498:283::o;4788:670::-;;;;;4953:3;4941:9;4932:7;4928:23;4924:33;4921:2;;;-1:-1;;4960:12;4921:2;226:6;220:13;238:33;265:5;238:33;:::i;:::-;5123:2;5173:22;;2592:13;5242:2;5291:22;;2867:13;5012:74;;-1:-1;2592:13;-1:-1;2885:32;2867:13;2885:32;:::i;:::-;5360:2;5410:22;;;;2040:13;4915:543;;;;-1:-1;;;4915:543::o;5465:528::-;;;5622:2;5610:9;5601:7;5597:23;5593:32;5590:2;;;-1:-1;;5628:12;5590:2;5679:17;5673:24;-1:-1;;;;;5717:18;5709:6;5706:30;5703:2;;;-1:-1;;5739:12;5703:2;5841:6;5830:9;5826:22;;;429:3;422:4;414:6;410:17;406:27;396:2;;-1:-1;;437:12;396:2;477:6;471:13;5717:18;50377:6;50374:30;50371:2;;;-1:-1;;50407:12;50371:2;50452:4;;;;50444:6;50440:17;499:80;50452:4;50440:17;50505:15;499:80;:::i;:::-;607:21;;;664:14;;;;639:17;;;744:27;;;;;741:36;-1:-1;738:2;;;-1:-1;;780:12;738:2;-1:-1;806:10;;800:217;825:6;822:1;819:13;800:217;;;2040:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;5945:22;;;;2592:13;5759:99;;2592:13;;-1:-1;;;;;;;5584:409::o;6000:257::-;;6112:2;6100:9;6091:7;6087:23;6083:32;6080:2;;;-1:-1;;6118:12;6080:2;1908:6;1902:13;1920:30;1944:5;1920:30;:::i;6264:263::-;;6379:2;6367:9;6358:7;6354:23;6350:32;6347:2;;;-1:-1;;6385:12;6347:2;-1:-1;2040:13;;6341:186;-1:-1;6341:186::o;6534:259::-;;6647:2;6635:9;6626:7;6622:23;6618:32;6615:2;;;-1:-1;;6653:12;6615:2;2185:6;2179:13;58198:5;53819:1;53808:20;58175:5;58172:33;58162:2;;-1:-1;;58209:12;6800:241;;6904:2;6892:9;6883:7;6879:23;6875:32;6872:2;;;-1:-1;;6910:12;6872:2;2320:6;2307:20;-1:-1;;;;;58322:5;53902:46;58297:5;58294:35;58284:2;;-1:-1;;58333:12;7048:241;;7152:2;7140:9;7131:7;7127:23;7123:32;7120:2;;;-1:-1;;7158:12;7120:2;-1:-1;2444:20;;7114:175;-1:-1;7114:175::o;7566:366::-;;;7687:2;7675:9;7666:7;7662:23;7658:32;7655:2;;;-1:-1;;7693:12;7655:2;-1:-1;;2444:20;;;7845:2;7884:22;;;2444:20;;-1:-1;7649:283::o;7939:582::-;;;;8111:3;8099:9;8090:7;8086:23;8082:33;8079:2;;;-1:-1;;8118:12;8079:2;2598:6;2592:13;8170:74;;8281:2;;8335:9;8331:22;2592:13;8289:74;;1176:3;1157:17;8477:9;1157:17;1153:27;1143:2;;-1:-1;;1184:12;1143:2;1237:78;8400:2;1237:78;:::i;:::-;1321:16;8400:2;8477:9;8473:22;1438:3;8111;8477:9;1409:27;1406:36;1403:2;;;-1:-1;;1445:12;1403:2;-1:-1;1465:217;1218:4;1487:1;1484:13;1465:217;;;2592:13;;1558:61;;1633:14;;;;1661;;;;1512:1;1505:9;1465:217;;;1469:14;;8408:97;;;;;;8073:448;;;;;:::o;8528:239::-;;8631:2;8619:9;8610:7;8606:23;8602:32;8599:2;;;-1:-1;;8637:12;8599:2;2734:6;2721:20;2746:32;2772:5;2746:32;:::i;12167:104::-;53492:13;53485:21;12232:34;;12226:45::o;22465:113::-;-1:-1;;;;;53902:46;22536:37;;22530:48::o;23196:100::-;-1:-1;;;;;54323:30;23255:36;;23249:47::o;23534:271::-;;12558:5;51443:12;12669:52;12714:6;12709:3;12702:4;12695:5;12691:16;12669:52;:::i;:::-;12733:16;;;;;23668:137;-1:-1;;23668:137::o;24198:222::-;-1:-1;;;;;54022:54;;;;9486:45;;24325:2;24310:18;;24296:124::o;24427:349::-;-1:-1;;;;;54022:54;;;9329:58;;54022:54;;24762:2;24747:18;;9486:45;24590:2;24575:18;;24561:215::o;24783:337::-;-1:-1;;;;;54022:54;;;;9329:58;;53492:13;53485:21;25106:2;25091:18;;12232:34;24940:2;24925:18;;24911:209::o;25127:365::-;-1:-1;;;;;54022:54;;;;9486:45;;25478:2;25463:18;;12349:37;25298:2;25283:18;;25269:223::o;25839:1326::-;-1:-1;;;;;54022:54;;;9486:45;;54022:54;;;26404:2;26389:18;;9486:45;54022:54;;;26487:2;26472:18;;9486:45;54022:54;;;26570:2;26555:18;;9486:45;54022:54;;;26653:3;26638:19;;9486:45;54022:54;;;54033:42;26722:19;;9486:45;54022:54;;;26821:3;26806:19;;9486:45;54022:54;;26905:3;26890:19;;9486:45;53492:13;;53485:21;26983:3;26968:19;;12232:34;-1:-1;;;;;54323:30;;27065:3;27050:19;;23255:36;26239:3;26224:19;;27081:74;27150:3;27135:19;;27125:7;27081:74;:::i;:::-;26210:955;;;;;;;;;;;;;;:::o;27172:432::-;-1:-1;;;;;54022:54;;;9486:45;;54022:54;;;;27513:2;27498:18;;9486:45;53492:13;;53485:21;27590:2;27575:18;;12232:34;27349:2;27334:18;;27320:284::o;27951:482::-;28184:2;28198:47;;;51443:12;;28169:18;;;52550:19;;;27951:482;;28184:2;52590:14;;;;;;50931;;;27951:482;10316:344;10341:6;10338:1;10335:13;10316:344;;;10402:13;;22194:23;;-1:-1;;;;;54323:30;;;23255:36;;22353:16;;;22347:23;54323:30;22422:14;;;23255:36;9040:14;;;;52150;;;;10363:1;10356:9;10316:344;;;-1:-1;28251:172;;28155:278;-1:-1;;;;;;;28155:278::o;28440:370::-;28617:2;28631:47;;;51443:12;;28602:18;;;52550:19;;;28440:370;;28617:2;50931:14;;;;52590;;;;28440:370;11129:260;11154:6;11151:1;11148:13;11129:260;;;11215:13;;12349:37;;52150:14;;;;9222;;;;11176:1;11169:9;11129:260;;;-1:-1;28684:116;;28588:222;-1:-1;;;;;;28588:222::o;28817:210::-;53492:13;;53485:21;12232:34;;28938:2;28923:18;;28909:118::o;29034:424::-;53492:13;;53485:21;12232:34;;54239:10;54228:22;;;29363:2;29348:18;;23148:36;54228:22;29444:2;29429:18;;23148:36;29207:2;29192:18;;29178:280::o;29465:222::-;12349:37;;;29592:2;29577:18;;29563:124::o;29694:698::-;12349:37;;;-1:-1;;;;;54022:54;;;30175:2;30160:18;;12858:76;54022:54;;30299:2;30284:18;;12858:76;5717:18;53808:20;30378:2;30363:18;;13795:35;29976:3;29961:19;;29947:445::o;30399:890::-;12349:37;;;-1:-1;;;;;54022:54;;;30947:2;30932:18;;12858:76;54022:54;;;31071:2;31056:18;;12858:76;54022:54;;;31195:2;31180:18;;12858:76;5717:18;53808:20;31274:3;31259:19;;13795:35;30749:3;30734:19;;30720:569::o;31296:1070::-;;31656:3;31645:9;31641:19;5717:18;;54033:42;;;;53302:5;54022:54;12865:3;12858:76;31847:2;54033:42;53302:5;54022:54;31847:2;31836:9;31832:18;9486:45;12379:5;31930:2;31919:9;31915:18;12349:37;12379:5;32013:2;32002:9;31998:18;12349:37;31656:3;32050;32039:9;32035:19;32028:49;32091:105;;;11637:5;51734:12;52562:6;52557:3;52550:19;52590:14;31645:9;52590:14;11649:93;;51252:3;-1:-1;51242:14;31847:2;-1:-1;51271:18;11822:21;;-1:-1;11849:288;11874:6;11871:1;11868:13;11849:288;;;57393:11;;12349:37;;11896:1;52377:14;;;;9222;;;;11889:9;11849:288;;;11853:14;;;32083:113;;;;;32207:71;32273:3;32262:9;32258:19;32249:6;32207:71;:::i;:::-;32289:67;32351:3;32340:9;32336:19;32327:6;32289:67;:::i;:::-;31627:739;;;;;;;;;;:::o;32373:712::-;-1:-1;;;;;54022:54;;;;12858:76;;32825:2;32810:18;;12349:37;;;;-1:-1;;;;;54323:30;;;32906:2;32891:18;;23255:36;54323:30;32987:2;32972:18;;23255:36;33070:3;33055:19;;12349:37;32634:3;32619:19;;32605:480::o;33092:488::-;-1:-1;;;;;54022:54;;;;12858:76;;-1:-1;;;;;54323:30;;;33485:2;33470:18;;23255:36;54323:30;33566:2;33551:18;;23255:36;33297:2;33282:18;;33268:312::o;33587:256::-;33731:2;33716:18;;57720:1;57710:12;;57700:2;;57726:9;57700:2;13649:67;;;33702:141;:::o;33850:214::-;53819:1;53808:20;;;;13795:35;;33973:2;33958:18;;33944:120::o;34071:760::-;53819:1;53808:20;;;;13795:35;;-1:-1;;;;;53902:46;;;34489:2;34474:18;;22656:50;53902:46;;;;34572:2;34557:18;;22656:50;-1:-1;;;;;54022:54;;;34655:2;34640:18;;9486:45;54022:54;;;34738:3;34723:19;;9486:45;53492:13;53485:21;54033:42;34801:19;;12232:34;34328:3;34313:19;;34299:532::o;34838:321::-;53819:1;53808:20;;;;13795:35;;-1:-1;;;;;54323:30;35145:2;35130:18;;23255:36;34987:2;34972:18;;34958:201::o;35166:310::-;;35313:2;35334:17;35327:47;14281:5;51443:12;52562:6;35313:2;35302:9;35298:18;52550:19;14375:52;14420:6;52590:14;35302:9;52590:14;35313:2;14401:5;14397:16;14375:52;:::i;:::-;57501:7;57485:14;-1:-1;;57481:28;14439:39;;;;52590:14;14439:39;;35284:192;-1:-1;;35284:192::o;35483:416::-;35683:2;35697:47;;;14715:2;35668:18;;;52550:19;-1:-1;;;52590:14;;;14731:38;14788:12;;;35654:245::o;35906:416::-;36106:2;36120:47;;;15039:2;36091:18;;;52550:19;15075:29;52590:14;;;15055:50;15124:12;;;36077:245::o;36329:416::-;36529:2;36543:47;;;15375:1;36514:18;;;52550:19;-1:-1;;;52590:14;;;15390:32;15441:12;;;36500:245::o;36752:416::-;36952:2;36966:47;;;15692:2;36937:18;;;52550:19;15728:34;52590:14;;;15708:55;-1:-1;;;15783:12;;;15776:31;15826:12;;;36923:245::o;37175:416::-;37375:2;37389:47;;;16077:2;37360:18;;;52550:19;-1:-1;;;52590:14;;;16093:33;16145:12;;;37346:245::o;37598:416::-;37798:2;37812:47;;;16396:2;37783:18;;;52550:19;16432:34;52590:14;;;16412:55;-1:-1;;;16487:12;;;16480:25;16524:12;;;37769:245::o;38021:416::-;38221:2;38235:47;;;16775:2;38206:18;;;52550:19;16811:34;52590:14;;;16791:55;-1:-1;;;16866:12;;;16859:30;16908:12;;;38192:245::o;38444:416::-;38644:2;38658:47;;;17159:2;38629:18;;;52550:19;-1:-1;;;52590:14;;;17175:36;17230:12;;;38615:245::o;38867:416::-;39067:2;39081:47;;;17481:1;39052:18;;;52550:19;-1:-1;;;52590:14;;;17496:32;17547:12;;;39038:245::o;39290:416::-;39490:2;39504:47;;;17798:2;39475:18;;;52550:19;-1:-1;;;52590:14;;;17814:36;17869:12;;;39461:245::o;39713:416::-;39913:2;39927:47;;;18120:2;39898:18;;;52550:19;-1:-1;;;52590:14;;;18136:38;18193:12;;;39884:245::o;40136:416::-;40336:2;40350:47;;;18444:2;40321:18;;;52550:19;18480:27;52590:14;;;18460:48;18527:12;;;40307:245::o;40559:416::-;40759:2;40773:47;;;18778:1;40744:18;;;52550:19;-1:-1;;;52590:14;;;18793:30;18842:12;;;40730:245::o;40982:416::-;41182:2;41196:47;;;19398:2;41167:18;;;52550:19;-1:-1;;;52590:14;;;19414:35;19468:12;;;41153:245::o;41405:416::-;41605:2;41619:47;;;19719:2;41590:18;;;52550:19;19755:34;52590:14;;;19735:55;-1:-1;;;19810:12;;;19803:30;19852:12;;;41576:245::o;41828:416::-;42028:2;42042:47;;;20103:2;42013:18;;;52550:19;-1:-1;;;52590:14;;;20119:45;20183:12;;;41999:245::o;42251:416::-;42451:2;42465:47;;;20434:2;42436:18;;;52550:19;20470:31;52590:14;;;20450:52;20521:12;;;42422:245::o;42674:416::-;42874:2;42888:47;;;20772:2;42859:18;;;52550:19;-1:-1;;;52590:14;;;20788:34;20841:12;;;42845:245::o;43097:416::-;43297:2;43311:47;;;21092:2;43282:18;;;52550:19;21128:34;52590:14;;;21108:55;-1:-1;;;21183:12;;;21176:34;21229:12;;;43268:245::o;43520:416::-;43720:2;43734:47;;;21480:2;43705:18;;;52550:19;-1:-1;;;52590:14;;;21496:34;21549:12;;;43691:245::o;43943:416::-;44143:2;44157:47;;;21800:1;44128:18;;;52550:19;-1:-1;;;52590:14;;;21815:30;21864:12;;;44114:245::o;44366:222::-;-1:-1;;;;;53902:46;;;;22656:50;;44493:2;44478:18;;44464:124::o;44595:333::-;-1:-1;;;;;53902:46;;;22536:37;;53902:46;;44914:2;44899:18;;22536:37;44750:2;44735:18;;44721:207::o;44935:556::-;-1:-1;;;;;53902:46;;;22536:37;;53902:46;;;45311:2;45296:18;;22536:37;53902:46;;;45394:2;45379:18;;22536:37;53902:46;;;45477:2;45462:18;;22536:37;45146:3;45131:19;;45117:374::o;45498:436::-;-1:-1;;;;;53902:46;;;;22536:37;;-1:-1;;;;;54323:30;;;45839:2;45824:18;;23255:36;54323:30;45920:2;45905:18;;23255:36;45677:2;45662:18;;45648:286::o;46170:748::-;12349:37;;;53819:1;53808:20;;;;46582:2;46567:18;;13795:35;54239:10;54228:22;;;;46663:2;46648:18;;23148:36;-1:-1;;;;;54323:30;;;46744:2;46729:18;;23255:36;54323:30;46825:3;46810:19;;23255:36;53492:13;53485:21;46903:3;46888:19;;12232:34;46421:3;46406:19;;46392:526::o;46925:349::-;12349:37;;;47260:2;47245:18;;13921:58;47088:2;47073:18;;47059:215::o;47621:428::-;12349:37;;;-1:-1;;;;;54323:30;;;;47958:2;47943:18;;23255:36;53492:13;53485:21;48035:2;48020:18;;12232:34;47796:2;47781:18;;47767:282::o;48056:452::-;12349:37;;;-1:-1;;;;;54323:30;;;;48405:2;48390:18;;23255:36;54436:4;54425:16;48494:2;48479:18;;14068:56;48243:2;48228:18;;48214:294::o;48515:220::-;54239:10;54228:22;;;;23018:49;;48641:2;48626:18;;48612:123::o;48742:218::-;-1:-1;;;;;54323:30;;;;23255:36;;48867:2;48852:18;;48838:122::o;48967:325::-;-1:-1;;;;;54323:30;;;23255:36;;54323:30;;49278:2;49263:18;;23255:36;49118:2;49103:18;;49089:203::o;49299:436::-;-1:-1;;;;;54323:30;;;23255:36;;54323:30;;;;49638:2;49623:18;;23255:36;49721:2;49706:18;;12349:37;;;;49478:2;49463:18;;49449:286::o;49742:214::-;54436:4;54425:16;;;;23487:35;;49865:2;49850:18;;49836:120::o;49963:256::-;50025:2;50019:9;50051:17;;;-1:-1;;;;;50111:34;;50147:22;;;50108:62;50105:2;;;50183:1;;50173:12;50105:2;50025;50192:22;50003:216;;-1:-1;50003:216::o;56828:268::-;56893:1;56900:101;56914:6;56911:1;56908:13;56900:101;;;56981:11;;;56975:18;56962:11;;;56955:39;56936:2;56929:10;56900:101;;;57016:6;57013:1;57010:13;57007:2;;;-1:-1;;56893:1;57063:16;;57056:27;56877:219::o;57749:117::-;-1:-1;;;;;54022:54;;57808:35;;57798:2;;57857:1;;57847:12;57798:2;57792:74;:::o;57873:111::-;57954:5;53492:13;53485:21;57932:5;57929:32;57919:2;;57975:1;;57965:12;58483:115;-1:-1;;;;;58568:5;54323:30;58544:5;58541:34;58531:2;;58589:1;;58579:12

Swarm Source

ipfs://4f0a0f8dfa8207815122cdcd7e302a058c41e7aa8d8ee8daf858e9b12287afea

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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