ETH Price: $3,119.85 (+0.99%)
 

Overview

ETH Balance

0.007740682037394805 ETH

Eth Value

$24.15 (@ $3,119.85/ETH)

Token Holdings

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw ETH241578202026-01-04 0:50:597 days ago1767487859IN
0x8E0aE525...F787C7d5d
0 ETH0.000001150.04058567
Execute Unexecut...241578192026-01-04 0:50:477 days ago1767487847IN
0x8E0aE525...F787C7d5d
0 ETH0.000004960.03654043
Order Token To E...241578092026-01-04 0:48:477 days ago1767487727IN
0x8E0aE525...F787C7d5d
0 ETH0.00000730.03150788
Withdraw ETH241578082026-01-04 0:48:357 days ago1767487715IN
0x8E0aE525...F787C7d5d
0 ETH0.000000810.02843078
Execute Unexecut...241578072026-01-04 0:48:237 days ago1767487703IN
0x8E0aE525...F787C7d5d
0 ETH0.000003560.02625821
Order Token To E...241577962026-01-04 0:46:117 days ago1767487571IN
0x8E0aE525...F787C7d5d
0 ETH0.000006360.02748237
Withdraw ETH241577942026-01-04 0:45:477 days ago1767487547IN
0x8E0aE525...F787C7d5d
0 ETH0.000000860.03050085
Execute Unexecut...241577922026-01-04 0:45:237 days ago1767487523IN
0x8E0aE525...F787C7d5d
0 ETH0.000004190.03087428
Order Token To E...241577812026-01-04 0:43:117 days ago1767487391IN
0x8E0aE525...F787C7d5d
0 ETH0.000007510.0324149
Withdraw ETH241577802026-01-04 0:42:597 days ago1767487379IN
0x8E0aE525...F787C7d5d
0 ETH0.000000950.0335891
Execute Unexecut...241577792026-01-04 0:42:477 days ago1767487367IN
0x8E0aE525...F787C7d5d
0 ETH0.000004790.03528064
Order Token To E...241577692026-01-04 0:40:477 days ago1767487247IN
0x8E0aE525...F787C7d5d
0 ETH0.000008010.03459705
Withdraw ETH241577682026-01-04 0:40:357 days ago1767487235IN
0x8E0aE525...F787C7d5d
0 ETH0.000000870.03078042
Execute Unexecut...241577672026-01-04 0:40:237 days ago1767487223IN
0x8E0aE525...F787C7d5d
0 ETH0.000004390.03233374
Order Token To E...241577592026-01-04 0:38:477 days ago1767487127IN
0x8E0aE525...F787C7d5d
0 ETH0.000007390.03191173
Withdraw ETH241577562026-01-04 0:37:597 days ago1767487079IN
0x8E0aE525...F787C7d5d
0 ETH0.000000970.03408828
Execute Unexecut...241577552026-01-04 0:37:477 days ago1767487067IN
0x8E0aE525...F787C7d5d
0 ETH0.000004840.03562904
Order Token To E...241577452026-01-04 0:35:477 days ago1767486947IN
0x8E0aE525...F787C7d5d
0 ETH0.000009070.0391776
Withdraw ETH241577442026-01-04 0:35:357 days ago1767486935IN
0x8E0aE525...F787C7d5d
0 ETH0.000001170.04128653
Execute Unexecut...241577432026-01-04 0:35:237 days ago1767486923IN
0x8E0aE525...F787C7d5d
0 ETH0.000005630.04144374
Order Token To E...241577332026-01-04 0:33:237 days ago1767486803IN
0x8E0aE525...F787C7d5d
0 ETH0.000011820.05102181
Withdraw ETH241577322026-01-04 0:33:117 days ago1767486791IN
0x8E0aE525...F787C7d5d
0 ETH0.00000150.05262198
Execute Unexecut...241577312026-01-04 0:32:597 days ago1767486779IN
0x8E0aE525...F787C7d5d
0 ETH0.000007450.05486991
Order Token To E...241577192026-01-04 0:30:357 days ago1767486635IN
0x8E0aE525...F787C7d5d
0 ETH0.00001510.06518948
Withdraw ETH241577182026-01-04 0:30:237 days ago1767486623IN
0x8E0aE525...F787C7d5d
0 ETH0.000001810.06370599
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer241578202026-01-04 0:50:597 days ago1767487859
0x8E0aE525...F787C7d5d
0.00003139 ETH
Transfer241578082026-01-04 0:48:357 days ago1767487715
0x8E0aE525...F787C7d5d
0.00003165 ETH
Transfer241577942026-01-04 0:45:477 days ago1767487547
0x8E0aE525...F787C7d5d
0.00003191 ETH
Transfer241577802026-01-04 0:42:597 days ago1767487379
0x8E0aE525...F787C7d5d
0.00003217 ETH
Transfer241577682026-01-04 0:40:357 days ago1767487235
0x8E0aE525...F787C7d5d
0.00003244 ETH
Transfer241577562026-01-04 0:37:597 days ago1767487079
0x8E0aE525...F787C7d5d
0.0000327 ETH
Transfer241577442026-01-04 0:35:357 days ago1767486935
0x8E0aE525...F787C7d5d
0.00003298 ETH
Transfer241577322026-01-04 0:33:117 days ago1767486791
0x8E0aE525...F787C7d5d
0.00003325 ETH
Transfer241577182026-01-04 0:30:237 days ago1767486623
0x8E0aE525...F787C7d5d
0.00003353 ETH
Transfer241577052026-01-04 0:27:477 days ago1767486467
0x8E0aE525...F787C7d5d
0.00003381 ETH
Transfer241576932026-01-04 0:25:237 days ago1767486323
0x8E0aE525...F787C7d5d
0.0000341 ETH
Transfer241576782026-01-04 0:22:237 days ago1767486143
0x8E0aE525...F787C7d5d
0.00003439 ETH
Transfer241576652026-01-04 0:19:477 days ago1767485987
0x8E0aE525...F787C7d5d
0.00003468 ETH
Transfer241576522026-01-04 0:17:117 days ago1767485831
0x8E0aE525...F787C7d5d
0.00003498 ETH
Transfer241576382026-01-04 0:14:237 days ago1767485663
0x8E0aE525...F787C7d5d
0.00003528 ETH
Transfer241576242026-01-04 0:11:357 days ago1767485495
0x8E0aE525...F787C7d5d
0.00003559 ETH
Transfer241576002026-01-04 0:06:477 days ago1767485207
0x8E0aE525...F787C7d5d
0.0000359 ETH
Transfer241575832026-01-04 0:03:237 days ago1767485003
0x8E0aE525...F787C7d5d
0.00003621 ETH
Transfer241575672026-01-04 0:00:117 days ago1767484811
0x8E0aE525...F787C7d5d
0.00003653 ETH
Transfer241575542026-01-03 23:57:357 days ago1767484655
0x8E0aE525...F787C7d5d
0.00003685 ETH
Transfer241575412026-01-03 23:54:597 days ago1767484499
0x8E0aE525...F787C7d5d
0.00003718 ETH
Transfer241575292026-01-03 23:52:357 days ago1767484355
0x8E0aE525...F787C7d5d
0.00003751 ETH
Transfer241575152026-01-03 23:49:477 days ago1767484187
0x8E0aE525...F787C7d5d
0.00003784 ETH
Transfer241575002026-01-03 23:46:477 days ago1767484007
0x8E0aE525...F787C7d5d
0.00003818 ETH
Transfer241574872026-01-03 23:44:117 days ago1767483851
0x8E0aE525...F787C7d5d
0.00003852 ETH
View All Internal Transactions
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
IDOLvsETHBoxExchange

Compiler Version
v0.6.6+commit.6c089d02

Optimization Enabled:
Yes with 200 runs

Other Settings:
constantinople EvmVersion, None license
/**
 *Submitted for verification at Etherscan.io on 2020-08-12
*/

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.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/token/ERC20/IERC20.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.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: @openzeppelin/contracts/math/SafeMath.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.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

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.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) public {
        _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 is 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: @openzeppelin/contracts/utils/SafeCast.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.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/Interfaces/PriceCalculatorInterface.sol

pragma solidity >=0.6.6;

interface PriceCalculatorInterface {
    function calculatePrice(
        uint256 buyAmount,
        uint256 buyAmountLimit,
        uint256 sellAmount,
        uint256 sellAmountLimit,
        uint256 baseTokenPool,
        uint256 settlementTokenPool
    ) external view returns (uint256[5] memory);
}

// File: contracts/Libraries/Enums.sol

pragma solidity >=0.6.6;

enum Token {TOKEN0, TOKEN1}

// FLEX_0_1 => Swap TOKEN0 to TOKEN1, slippage is tolerate to 5%
// FLEX_1_0 => Swap TOKEN1 to TOKEN0, slippage is tolerate to 5%
// STRICT_0_1 => Swap TOKEN0 to TOKEN1, slippage is limited in 0.1%
// STRICT_1_0 => Swap TOKEN1 to TOKEN0, slippage is limited in 0.1%
enum OrderType {FLEX_0_1, FLEX_1_0, STRICT_0_1, STRICT_1_0}

library TokenLibrary {
    function another(Token self) internal pure returns (Token) {
        if (self == Token.TOKEN0) {
            return Token.TOKEN1;
        } else {
            return Token.TOKEN0;
        }
    }
}

library OrderTypeLibrary {
    function inToken(OrderType self) internal pure returns (Token) {
        if (self == OrderType.FLEX_0_1 || self == OrderType.STRICT_0_1) {
            return Token.TOKEN0;
        } else {
            return Token.TOKEN1;
        }
    }

    function isFlex(OrderType self) internal pure returns (bool) {
        return self == OrderType.FLEX_0_1 || self == OrderType.FLEX_1_0;
    }

    function isStrict(OrderType self) internal pure returns (bool) {
        return !isFlex(self);
    }

    function next(OrderType self) internal pure returns (OrderType) {
        return OrderType((uint256(self) + 1) % 4);
    }

    function isBuy(OrderType self) internal pure returns (bool) {
        return (self == OrderType.FLEX_0_1 || self == OrderType.STRICT_0_1);
    }
}

// File: contracts/Libraries/RateMath.sol

pragma solidity >=0.6.6;


library RateMath {
    using SafeMath for uint256;
    uint256 public constant RATE_POINT_MULTIPLIER = 1000000000000000000; // 10^18

    function getRate(uint256 a, uint256 b) internal pure returns (uint256) {
        return a.mul(RATE_POINT_MULTIPLIER).div(b);
    }

    function divByRate(uint256 self, uint256 rate)
        internal
        pure
        returns (uint256)
    {
        return self.mul(RATE_POINT_MULTIPLIER).div(rate);
    }

    function mulByRate(uint256 self, uint256 rate)
        internal
        pure
        returns (uint256)
    {
        return self.mul(rate).div(RATE_POINT_MULTIPLIER);
    }
}

// File: contracts/Libraries/ExecutionStatus.sol

pragma solidity >=0.6.6;



struct BoxExecutionStatus {
    OrderType partiallyRefundOrderType;
    uint64 partiallyRefundRate; // refundAmount/inAmount
    uint128 rate; // Token0/Token1
    uint32 boxNumber;
    bool onGoing;
}

struct BookExecutionStatus {
    OrderType executingOrderType;
    uint256 nextIndex;
}

library BoxExecutionStatusLibrary {
    using OrderTypeLibrary for OrderType;

    function refundRate(BoxExecutionStatus memory self, OrderType orderType)
        internal
        pure
        returns (uint256)
    {
        // inToken is different from refundOrderType
        if (self.partiallyRefundOrderType.inToken() != orderType.inToken()) {
            return 0;
        }

        // inToken is the same as refundOrderType
        // refund all of strict order and some of flex order
        if (self.partiallyRefundOrderType.isFlex()) {
            // orderType is flex
            if (orderType.isFlex()) {
                return self.partiallyRefundRate;
            }
            // orderType is strict
            return RateMath.RATE_POINT_MULTIPLIER;
        }

        // refund some of strict order
        if (orderType.isStrict()) {
            return self.partiallyRefundRate;
        }
        return 0;
    }
}

// File: contracts/Libraries/OrderBox.sol

pragma solidity >=0.6.6;




struct OrderBox {
    mapping(OrderType => OrderBook) orderBooks;
    uint128 spreadRate;
    uint128 expireAt;
}

struct OrderBook {
    mapping(address => uint256) inAmounts;
    address[] recipients;
    uint256 totalInAmount;
}

library OrderBoxLibrary {
    using RateMath for uint256;
    using SafeMath for uint256;
    using TokenLibrary for Token;

    function newOrderBox(uint128 spreadRate, uint128 expireAt)
        internal
        pure
        returns (OrderBox memory)
    {
        return OrderBox({spreadRate: spreadRate, expireAt: expireAt});
    }

    function addOrder(
        OrderBox storage self,
        OrderType orderType,
        uint256 inAmount,
        address recipient
    ) internal {
        OrderBook storage orderBook = self.orderBooks[orderType];
        if (orderBook.inAmounts[recipient] == 0) {
            orderBook.recipients.push(recipient);
        }
        orderBook.inAmounts[recipient] = orderBook.inAmounts[recipient].add(
            inAmount
        );
        orderBook.totalInAmount = orderBook.totalInAmount.add(inAmount);
    }
}

library OrderBookLibrary {
    function numOfOrder(OrderBook memory self) internal pure returns (uint256) {
        return self.recipients.length;
    }
}

// File: contracts/BoxExchange/BoxExchange.sol

pragma solidity ^0.6.6;



abstract contract BoxExchange is ERC20 {
    using BoxExecutionStatusLibrary for BoxExecutionStatus;
    using OrderBoxLibrary for OrderBox;
    using OrderBookLibrary for OrderBook;
    using OrderTypeLibrary for OrderType;
    using TokenLibrary for Token;
    using RateMath for uint256;
    using SafeMath for uint256;
    using SafeCast for uint256;

    uint256 internal constant MARKET_FEE_RATE = 200000000000000000; // market fee taker takes 20% of spread

    address internal immutable factory;

    address internal immutable marketFeeTaker; // Address that receives market fee (i.e. Lien Token)
    uint128 public marketFeePool0; // Total market fee in TOKEN0
    uint128 public marketFeePool1; // Total market fee in TOKEN1

    uint128 internal reserve0; // Total Liquidity of TOKEN0
    uint128 internal reserve1; // Total Liquidity of TOKEN1
    OrderBox[] internal orderBoxes; // Array of OrderBox
    PriceCalculatorInterface internal immutable priceCalc; // Price Calculator
    BoxExecutionStatus internal boxExecutionStatus; // Struct that has information about execution of current executing OrderBox
    BookExecutionStatus internal bookExecutionStatus; // Struct that has information about execution of current executing OrderBook

    event AcceptOrders(
        address indexed recipient,
        bool indexed isBuy, // if true, this order is exchange from TOKEN0 to TOKEN1
        uint32 indexed boxNumber,
        bool isLimit, // if true, this order is STRICT order
        uint256 tokenIn
    );

    event MoveLiquidity(
        address indexed liquidityProvider,
        bool indexed isAdd, // if true, this order is addtion of liquidity
        uint256 movedToken0Amount,
        uint256 movedToken1Amount,
        uint256 sharesMoved // Amount of share that is minted or burned
    );

    event Execution(
        bool indexed isBuy, // if true, this order is exchange from TOKEN0 to TOKEN1
        uint32 indexed boxNumber,
        address indexed recipient,
        uint256 orderAmount, // Amount of token that is transferred when this order is added
        uint256 refundAmount, // In the same token as orderAmount
        uint256 outAmount // In the other token than orderAmount
    );

    event UpdateReserve(uint128 reserve0, uint128 reserve1, uint256 totalShare);

    event PayMarketFee(uint256 amount0, uint256 amount1);

    event ExecutionSummary(
        uint32 indexed boxNumber,
        uint8 partiallyRefundOrderType,
        uint256 rate,
        uint256 partiallyRefundRate,
        uint256 totalInAmountFLEX_0_1,
        uint256 totalInAmountFLEX_1_0,
        uint256 totalInAmountSTRICT_0_1,
        uint256 totalInAmountSTRICT_1_0
    );

    modifier isAmountSafe(uint256 amount) {
        require(amount != 0, "Amount should be bigger than 0");
        _;
    }

    modifier isInTime(uint256 timeout) {
        require(timeout > _currentOpenBoxId(), "Time out");
        _;
    }

    constructor(
        PriceCalculatorInterface _priceCalc,
        address _marketFeeTaker,
        string memory _name
    ) public ERC20(_name, "share") {
        factory = msg.sender;
        priceCalc = _priceCalc;
        marketFeeTaker = _marketFeeTaker;
        _setupDecimals(8); // Decimal of share token is the same as iDOL, LBT, and Lien Token
    }

    /**
     * @notice Shows how many boxes and orders exist before the specific order
     * @dev If this order does not exist, return (false, 0, 0)
     * @dev If this order is already executed, return (true, 0, 0)
     * @param recipient Recipient of this order
     * @param boxNumber Box ID where the order exists
     * @param isExecuted If true, the order is already executed
     * @param boxCount Counter of boxes before this order. If current executing box number is the same as boxNumber, return 1 (i.e. indexing starts from 1)
     * @param orderCount Counter of orders before this order. If this order is on n-th top of the queue, return n (i.e. indexing starts from 1)
     **/
    function whenToExecute(
        address recipient,
        uint256 boxNumber,
        bool isBuy,
        bool isLimit
    )
        external
        view
        returns (
            bool isExecuted,
            uint256 boxCount,
            uint256 orderCount
        )
    {
        return
            _whenToExecute(recipient, _getOrderType(isBuy, isLimit), boxNumber);
    }

    /**
     * @notice Returns summary of current exchange status
     * @param boxNumber Current open box ID
     * @param _reserve0 Current reserve of TOKEN0
     * @param _reserve1 Current reserve of TOKEN1
     * @param totalShare Total Supply of share token
     * @param latestSpreadRate Spread Rate in latest OrderBox
     * @param token0PerShareE18 Amount of TOKEN0 per 1 share token and has 18 decimal
     * @param token1PerShareE18 Amount of TOKEN1 per 1 share token and has 18 decimal
     **/
    function getExchangeData()
        external
        virtual
        view
        returns (
            uint256 boxNumber,
            uint256 _reserve0,
            uint256 _reserve1,
            uint256 totalShare,
            uint256 latestSpreadRate,
            uint256 token0PerShareE18,
            uint256 token1PerShareE18
        )
    {
        boxNumber = _currentOpenBoxId();
        (_reserve0, _reserve1) = _getReserves();
        latestSpreadRate = orderBoxes[boxNumber].spreadRate;
        totalShare = totalSupply();
        token0PerShareE18 = RateMath.getRate(_reserve0, totalShare);
        token1PerShareE18 = RateMath.getRate(_reserve1, totalShare);
    }

    /**
     * @notice Gets summary of Current box information (Total order amount of each OrderTypes)
     * @param executionStatusNumber Status of execution of this box
     * @param boxNumber ID of target box.
     **/
    function getBoxSummary(uint256 boxNumber)
        public
        view
        returns (
            uint256 executionStatusNumber,
            uint256 flexToken0InAmount,
            uint256 strictToken0InAmount,
            uint256 flexToken1InAmount,
            uint256 strictToken1InAmount
        )
    {
        // `executionStatusNumber`
        // 0 => This box has not been executed
        // 1 => This box is currently executing. (Reserves and market fee pools have already been updated)
        // 2 => This box has already been executed
        uint256 nextExecutingBoxId = boxExecutionStatus.boxNumber;
        flexToken0InAmount = orderBoxes[boxNumber].orderBooks[OrderType
            .FLEX_0_1]
            .totalInAmount;
        strictToken0InAmount = orderBoxes[boxNumber].orderBooks[OrderType
            .STRICT_0_1]
            .totalInAmount;
        flexToken1InAmount = orderBoxes[boxNumber].orderBooks[OrderType
            .FLEX_1_0]
            .totalInAmount;
        strictToken1InAmount = orderBoxes[boxNumber].orderBooks[OrderType
            .STRICT_1_0]
            .totalInAmount;
        if (boxNumber < nextExecutingBoxId) {
            executionStatusNumber = 2;
        } else if (
            boxNumber == nextExecutingBoxId && boxExecutionStatus.onGoing
        ) {
            executionStatusNumber = 1;
        }
    }

    /**
     * @notice Gets amount of order in current open box
     * @param account Target Address
     * @param orderType OrderType of target order
     * @return Amount of target order
     **/
    function getOrderAmount(address account, OrderType orderType)
        public
        view
        returns (uint256)
    {
        return
            orderBoxes[_currentOpenBoxId()].orderBooks[orderType]
                .inAmounts[account];
    }

    // abstract functions
    function _feeRate() internal virtual returns (uint128);

    function _receiveTokens(
        Token token,
        address from,
        uint256 amount
    ) internal virtual;

    function _sendTokens(
        Token token,
        address to,
        uint256 amount
    ) internal virtual;

    function _payForOrderExecution(
        Token token,
        address to,
        uint256 amount
    ) internal virtual;

    function _payMarketFee(
        address _marketFeeTaker,
        uint256 amount0,
        uint256 amount1
    ) internal virtual;

    function _isCurrentOpenBoxExpired() internal virtual view returns (bool) {}

    /**
     * @notice User can determine the amount of share token to mint.
     * @dev This function can be executed only by factory
     * @param amount0 The amount of TOKEN0 to invest
     * @param amount1 The amount of TOKEN1 to invest
     * @param initialShare The amount of share token to mint. This defines approximate value of share token.
     **/
    function _init(
        uint128 amount0,
        uint128 amount1,
        uint256 initialShare
    ) internal virtual {
        require(totalSupply() == 0, "Already initialized");
        require(msg.sender == factory);
        _updateReserve(amount0, amount1);
        _mint(msg.sender, initialShare);
        _receiveTokens(Token.TOKEN0, msg.sender, amount0);
        _receiveTokens(Token.TOKEN1, msg.sender, amount1);
        _openNewBox();
    }

    /**
     * @dev Amount of share to mint is determined by `amount`
     * @param tokenType Type of token which the amount of share the LP get is calculated based on `amount`
     * @param amount The amount of token type of `tokenType`
     **/
    function _addLiquidity(
        uint256 _reserve0,
        uint256 _reserve1,
        uint256 amount,
        uint256 minShare,
        Token tokenType
    ) internal virtual {
        (uint256 amount0, uint256 amount1, uint256 share) = _calculateAmounts(
            amount,
            _reserve0,
            _reserve1,
            tokenType
        );
        require(share >= minShare, "You can't receive enough shares");
        _receiveTokens(Token.TOKEN0, msg.sender, amount0);
        _receiveTokens(Token.TOKEN1, msg.sender, amount1);
        _updateReserve(
            _reserve0.add(amount0).toUint128(),
            _reserve1.add(amount1).toUint128()
        );
        _mint(msg.sender, share);
        emit MoveLiquidity(msg.sender, true, amount0, amount1, share);
    }

    /**
     * @dev Amount of TOKEN0 and TOKEN1 is determined by amount of share to be burned
     * @param minAmount0 Minimum amount of TOKEN0 to return. If returned TOKEN0 is less than this value, revert transaction
     * @param minAmount1 Minimum amount of TOKEN1 to return. If returned TOKEN1 is less than this value, revert transaction
     * @param share Amount of share token to be burned
     **/
    function _removeLiquidity(
        uint256 minAmount0,
        uint256 minAmount1,
        uint256 share
    ) internal virtual {
        (uint256 _reserve0, uint256 _reserve1) = _getReserves(); // gas savings
        uint256 _totalSupply = totalSupply();
        uint256 amount0 = _reserve0.mul(share).div(_totalSupply);
        uint256 amount1 = _reserve1.mul(share).div(_totalSupply);
        require(
            amount0 >= minAmount0 && amount1 >= minAmount1,
            "You can't receive enough tokens"
        );
        _updateReserve(
            _reserve0.sub(amount0).toUint128(),
            _reserve1.sub(amount1).toUint128()
        );
        _burn(msg.sender, share);
        _sendTokens(Token.TOKEN0, msg.sender, amount0);
        _sendTokens(Token.TOKEN1, msg.sender, amount1);
        emit MoveLiquidity(msg.sender, false, amount0, amount1, share);
    }

    /**
     * @dev If there is some OrderBox to be executed, try execute 5 orders
     * @dev If currentBox has expired, open new box
     * @param orderType Type of order
     * @param inAmount Amount of token to be exchanged
     * @param recipient Recipient of swapped token. If this value is address(0), msg.sender is the recipient
     **/
    function _addOrder(
        OrderType orderType,
        uint256 inAmount,
        address recipient
    ) internal virtual {
        _rotateBox();
        uint256 _currentOpenBoxId = _currentOpenBoxId();
        _executeOrders(5, _currentOpenBoxId);
        if (recipient == address(0)) {
            recipient = msg.sender;
        }
        _receiveTokens(orderType.inToken(), msg.sender, inAmount);
        orderBoxes[_currentOpenBoxId].addOrder(orderType, inAmount, recipient);
        emit AcceptOrders(
            recipient,
            orderType.isBuy(),
            uint32(_currentOpenBoxId),
            orderType.isStrict(),
            inAmount
        );
    }

    /**
     * @dev Triggers executeOrders()
     * @param maxOrderNum Number of orders to execute (if no order is left, stop execution)
     **/
    function _triggerExecuteOrders(uint8 maxOrderNum) internal virtual {
        _executeOrders(maxOrderNum, _currentOpenBoxId());
    }

    /**
     * @dev Triggers PayMarketFee() and update marketFeePool to 0
     **/
    function _triggerPayMarketFee() internal virtual {
        (
            uint256 _marketFeePool0,
            uint256 _marketFeePool1
        ) = _getMarketFeePools();
        _updateMarketFeePool(0, 0);

        emit PayMarketFee(_marketFeePool0, _marketFeePool1);
        _payMarketFee(marketFeeTaker, _marketFeePool0, _marketFeePool1);
    }

    // When open new box, creates new OrderBox with spreadRate and block number of expiretion, then pushes it to orderBoxes
    function _openNewBox() internal virtual {
        orderBoxes.push(
            OrderBoxLibrary.newOrderBox(
                _feeRate(),
                (block.number + 2).toUint32()
            )
        );
    }

    function _rotateBox() private {
        // if current open box has expired
        if (_isCurrentOpenBoxExpired()) {
            _openNewBox();
        }
    }

    /**
     * @param maxOrderNum Number of orders to execute (if no order is left, stoppes execution)
     * @param _currentOpenBoxId Current box ID (_currentOpenBoxID() is already run in _addOrder() or _triggerExecuteOrders()
     **/
    function _executeOrders(uint256 maxOrderNum, uint256 _currentOpenBoxId)
        private
    {
        BoxExecutionStatus memory _boxExecutionStatus = boxExecutionStatus;
        BookExecutionStatus memory _bookExecutionStatus = bookExecutionStatus;
        // if _boxExecutionStatus.boxNumber is current open and not expired box, won't execute.
        // if _boxExecutionStatus.boxNumber is more than currentOpenBoxId, the newest box is already executed.
        if (
            _boxExecutionStatus.boxNumber >= _currentOpenBoxId &&
            (!_isCurrentOpenBoxExpired() ||
                _boxExecutionStatus.boxNumber > _currentOpenBoxId)
        ) {
            return;
        }
        if (!_boxExecutionStatus.onGoing) {
            // get rates and start new box execution
            // before start new box execution, updates reserves.
            {
                (
                    OrderType partiallyRefundOrderType,
                    uint256 partiallyRefundRate,
                    uint256 rate
                ) = _getExecutionRatesAndUpdateReserve(
                    _boxExecutionStatus.boxNumber
                );
                _boxExecutionStatus
                    .partiallyRefundOrderType = partiallyRefundOrderType;
                _boxExecutionStatus.partiallyRefundRate = partiallyRefundRate
                    .toUint64();
                _boxExecutionStatus.rate = rate.toUint128();
                _boxExecutionStatus.onGoing = true;
                _bookExecutionStatus.executingOrderType = OrderType(0);
                _bookExecutionStatus.nextIndex = 0;
            }
        }
        // execute orders in one book
        // reducing maxOrderNum to avoid stack to deep
        while (maxOrderNum != 0) {
            OrderBook storage executionBook = orderBoxes[_boxExecutionStatus
                .boxNumber]
                .orderBooks[_bookExecutionStatus.executingOrderType];
            (
                bool isBookFinished,
                uint256 nextIndex,
                uint256 executedOrderNum
            ) = _executeOrdersInBook(
                executionBook,
                _bookExecutionStatus.executingOrderType.inToken(),
                _bookExecutionStatus.nextIndex,
                _boxExecutionStatus.refundRate(
                    _bookExecutionStatus.executingOrderType
                ),
                _boxExecutionStatus.rate,
                orderBoxes[_boxExecutionStatus.boxNumber].spreadRate,
                maxOrderNum
            );
            if (isBookFinished) {
                bool isBoxFinished = _isBoxFinished(
                    orderBoxes[_boxExecutionStatus.boxNumber],
                    _bookExecutionStatus.executingOrderType
                );
                delete orderBoxes[_boxExecutionStatus.boxNumber]
                    .orderBooks[_bookExecutionStatus.executingOrderType];

                // update book execution status and box execution status
                if (isBoxFinished) {
                    _boxExecutionStatus.boxNumber += 1;
                    _boxExecutionStatus.onGoing = false;
                    boxExecutionStatus = _boxExecutionStatus;

                    return; // no need to update bookExecutionStatus;
                }
                _bookExecutionStatus.executingOrderType = _bookExecutionStatus
                    .executingOrderType
                    .next();
            }
            _bookExecutionStatus.nextIndex = nextIndex.toUint32();
            maxOrderNum -= executedOrderNum;
        }
        boxExecutionStatus = _boxExecutionStatus;
        bookExecutionStatus = _bookExecutionStatus;
    }

    /**
     * @notice Executes each OrderBook
     * @param orderBook Target OrderBook
     * @param rate Rate of swap
     * @param refundRate Refund rate in this OrderType
     * @param maxOrderNum Max number of orders to execute in this book
     * @return If execution is finished, return true
     * @return Next index to execute. If execution is finished, return 0
     * @return Number of orders executed
     **/
    function _executeOrdersInBook(
        OrderBook storage orderBook,
        Token inToken,
        uint256 initialIndex,
        uint256 refundRate,
        uint256 rate,
        uint256 spreadRate,
        uint256 maxOrderNum
    )
        private
        returns (
            bool,
            uint256,
            uint256
        )
    {
        uint256 index;
        uint256 numOfOrder = orderBook.numOfOrder();
        for (
            index = initialIndex;
            index - initialIndex < maxOrderNum;
            index++
        ) {
            if (index >= numOfOrder) {
                return (true, 0, index - initialIndex);
            }
            address recipient = orderBook.recipients[index];
            _executeOrder(
                inToken,
                recipient,
                orderBook.inAmounts[recipient],
                refundRate,
                rate,
                spreadRate
            );
        }
        if (index >= numOfOrder) {
            return (true, 0, index - initialIndex);
        }
        return (false, index, index - initialIndex);
    }

    /**
     * @dev Executes each order
     * @param inToken type of token
     * @param recipient Recipient of Token
     * @param inAmount Amount of token
     * @param refundRate Refund rate in this OrderType
     * @param rate Rate of swap
     * @param spreadRate Spread rate in this box
     **/
    function _executeOrder(
        Token inToken,
        address recipient,
        uint256 inAmount,
        uint256 refundRate,
        uint256 rate,
        uint256 spreadRate
    ) internal {
        Token outToken = inToken.another();
        // refundAmount = inAmount * refundRate
        uint256 refundAmount = inAmount.mulByRate(refundRate);
        // executingInAmountWithoutSpread = (inAmount - refundAmount) / (1+spreadRate)
        uint256 executingInAmountWithoutSpread = inAmount
            .sub(refundAmount)
            .divByRate(RateMath.RATE_POINT_MULTIPLIER.add(spreadRate));
        // spread = executingInAmountWithoutSpread * spreadRate
        // = (inAmount - refundAmount ) * ( 1 - 1 /( 1 + spreadRate))
        uint256 outAmount = _otherAmountBasedOnRate(
            inToken,
            executingInAmountWithoutSpread,
            rate
        );
        _payForOrderExecution(inToken, recipient, refundAmount);
        _payForOrderExecution(outToken, recipient, outAmount);
        emit Execution(
            (inToken == Token.TOKEN0),
            uint32(_currentOpenBoxId()),
            recipient,
            inAmount,
            refundAmount,
            outAmount
        );
    }

    /**
     * @notice Updates reserves and market fee pools
     * @param spreadRate Spread rate in the box
     * @param executingAmount0WithoutSpread Executed amount of TOKEN0 in this box
     * @param executingAmount1WithoutSpread Executed amount of TOKEN1 in this box
     * @param rate Rate of swap
     **/
    function _updateReservesAndMarketFeePoolByExecution(
        uint256 spreadRate,
        uint256 executingAmount0WithoutSpread,
        uint256 executingAmount1WithoutSpread,
        uint256 rate
    ) internal virtual {
        uint256 newReserve0;
        uint256 newReserve1;
        uint256 newMarketFeePool0;
        uint256 newMarketFeePool1;
        {
            (
                uint256 differenceOfReserve,
                uint256 differenceOfMarketFee
            ) = _calculateNewReserveAndMarketFeePool(
                spreadRate,
                executingAmount0WithoutSpread,
                executingAmount1WithoutSpread,
                rate,
                Token.TOKEN0
            );
            newReserve0 = reserve0 + differenceOfReserve;
            newMarketFeePool0 = marketFeePool0 + differenceOfMarketFee;
        }
        {
            (
                uint256 differenceOfReserve,
                uint256 differenceOfMarketFee
            ) = _calculateNewReserveAndMarketFeePool(
                spreadRate,
                executingAmount1WithoutSpread,
                executingAmount0WithoutSpread,
                rate,
                Token.TOKEN1
            );
            newReserve1 = reserve1 + differenceOfReserve;
            newMarketFeePool1 = marketFeePool1 + differenceOfMarketFee;
        }
        _updateReserve(newReserve0.toUint128(), newReserve1.toUint128());
        _updateMarketFeePool(
            newMarketFeePool0.toUint128(),
            newMarketFeePool1.toUint128()
        );
    }

    function _whenToExecute(
        address recipient,
        uint256 orderTypeCount,
        uint256 boxNumber
    )
        internal
        view
        returns (
            bool isExecuted,
            uint256 boxCount,
            uint256 orderCount
        )
    {
        if (boxNumber > _currentOpenBoxId()) {
            return (false, 0, 0);
        }
        OrderBox storage yourOrderBox = orderBoxes[boxNumber];
        address[] memory recipients = yourOrderBox.orderBooks[OrderType(
            orderTypeCount
        )]
            .recipients;
        uint256 nextExecutingBoxId = boxExecutionStatus.boxNumber;
        uint256 nextIndex = bookExecutionStatus.nextIndex;
        uint256 nextType = uint256(bookExecutionStatus.executingOrderType);
        bool onGoing = boxExecutionStatus.onGoing;
        bool isExist;
        uint256 place;
        for (uint256 j = 0; j != recipients.length; j++) {
            if (recipients[j] == recipient) {
                isExist = true;
                place = j;
                break;
            }
        }

        // If current box number exceeds boxNumber, the target box has already been executed
        // If current box number is equal to boxNumber, and OrderType or index exceeds that of the target order, the target box has already been executed
        if (
            (boxNumber < nextExecutingBoxId) ||
            ((onGoing && (boxNumber == nextExecutingBoxId)) &&
                ((orderTypeCount < nextType) ||
                    ((orderTypeCount == nextType) && (place < nextIndex))))
        ) {
            return (true, 0, 0);
        }

        if (!isExist) {
            return (false, 0, 0);
        }

        // Total number of orders before the target OrderType
        uint256 counts;
        if (boxNumber == nextExecutingBoxId && onGoing) {
            for (uint256 i = nextType; i < orderTypeCount; i++) {
                counts += yourOrderBox.orderBooks[OrderType(i)].numOfOrder();
            }
            boxCount = 1;
            orderCount = counts.add(place).sub(nextIndex) + 1;
        } else {
            for (uint256 i = 0; i != orderTypeCount; i++) {
                counts += yourOrderBox.orderBooks[OrderType(i)].numOfOrder();
            }
            boxCount = boxNumber.sub(nextExecutingBoxId) + 1;
            orderCount = counts.add(place) + 1;
        }
    }

    function _getReserves()
        internal
        view
        returns (uint256 _reserve0, uint256 _reserve1)
    {
        _reserve0 = reserve0;
        _reserve1 = reserve1;
    }

    function _getMarketFeePools()
        internal
        view
        returns (uint256 _marketFeePool0, uint256 _marketFeePool1)
    {
        _marketFeePool0 = marketFeePool0;
        _marketFeePool1 = marketFeePool1;
    }

    function _updateReserve(uint128 newReserve0, uint128 newReserve1) internal {
        reserve0 = newReserve0;
        reserve1 = newReserve1;
        emit UpdateReserve(newReserve0, newReserve1, totalSupply());
    }

    function _calculatePriceWrapper(
        uint256 flexToken0InWithoutSpread,
        uint256 strictToken0InWithoutSpread,
        uint256 flexToken1InWithoutSpread,
        uint256 strictToken1InWithoutSpread,
        uint256 _reserve0,
        uint256 _reserve1
    )
        internal
        view
        returns (
            uint256 rate,
            uint256 refundStatus,
            uint256 partiallyRefundRate,
            uint256 executingAmount0,
            uint256 executingAmount1
        )
    {
        uint256[5] memory data = priceCalc.calculatePrice(
            flexToken0InWithoutSpread,
            strictToken0InWithoutSpread,
            flexToken1InWithoutSpread,
            strictToken1InWithoutSpread,
            _reserve0,
            _reserve1
        );
        return (data[0], data[1], data[2], data[3], data[4]);
    }

    /**
     * @param rate0Per1 Token0 / Token1 * RATE_POINT_MULTIPLIER
     */
    function _otherAmountBasedOnRate(
        Token token,
        uint256 amount,
        uint256 rate0Per1
    ) internal pure returns (uint256) {
        if (token == Token.TOKEN0) {
            return amount.mulByRate(rate0Per1);
        } else {
            return amount.divByRate(rate0Per1);
        }
    }

    function _currentOpenBoxId() internal view returns (uint256) {
        return orderBoxes.length - 1;
    }

    /**
     * @notice Gets OrderType in uint
     **/
    function _getOrderType(bool isBuy, bool isLimit)
        internal
        pure
        returns (uint256 orderTypeCount)
    {
        if (isBuy && isLimit) {
            orderTypeCount = 2;
        } else if (!isBuy) {
            if (isLimit) {
                orderTypeCount = 3;
            } else {
                orderTypeCount = 1;
            }
        }
    }

    function _updateMarketFeePool(
        uint128 newMarketFeePool0,
        uint128 newMarketFeePool1
    ) private {
        marketFeePool0 = newMarketFeePool0;
        marketFeePool1 = newMarketFeePool1;
    }

    function _calculateAmounts(
        uint256 amount,
        uint256 _reserve0,
        uint256 _reserve1,
        Token tokenType
    )
        private
        view
        returns (
            uint256,
            uint256,
            uint256
        )
    {
        if (tokenType == Token.TOKEN0) {
            return (
                amount,
                amount.mul(_reserve1).div(_reserve0),
                amount.mul(totalSupply()).div(_reserve0)
            );
        } else {
            return (
                amount.mul(_reserve0).div(_reserve1),
                amount,
                amount.mul(totalSupply()).div(_reserve1)
            );
        }
    }

    function _priceCalculateRates(
        OrderBox storage orderBox,
        uint256 totalInAmountFLEX_0_1,
        uint256 totalInAmountFLEX_1_0,
        uint256 totalInAmountSTRICT_0_1,
        uint256 totalInAmountSTRICT_1_0
    )
        private
        view
        returns (
            uint256 rate,
            uint256 refundStatus,
            uint256 partiallyRefundRate,
            uint256 executingAmount0,
            uint256 executingAmount1
        )
    {
        uint256 withoutSpreadRate = RateMath.RATE_POINT_MULTIPLIER +
            orderBox.spreadRate;
        return
            _calculatePriceWrapper(
                totalInAmountFLEX_0_1.divByRate(withoutSpreadRate),
                totalInAmountSTRICT_0_1.divByRate(withoutSpreadRate),
                totalInAmountFLEX_1_0.divByRate(withoutSpreadRate),
                totalInAmountSTRICT_1_0.divByRate(withoutSpreadRate),
                reserve0,
                reserve1
            );
    }

    function _getExecutionRatesAndUpdateReserve(uint32 boxNumber)
        private
        returns (
            OrderType partiallyRefundOrderType,
            uint256 partiallyRefundRate,
            uint256 rate
        )
    {
        OrderBox storage orderBox = orderBoxes[boxNumber];
        // `refundStatus`
        // 0 => no_refund
        // 1 => refund some of strictToken0
        // 2 => refund all strictToken0 and some of flexToken0
        // 3 => refund some of strictToken1
        // 4 => refund all strictToken1 and some of flexToken1
        uint256 refundStatus;
        uint256 executingAmount0WithoutSpread;
        uint256 executingAmount1WithoutSpread;
        uint256 totalInAmountFLEX_0_1 = orderBox.orderBooks[OrderType.FLEX_0_1]
            .totalInAmount;
        uint256 totalInAmountFLEX_1_0 = orderBox.orderBooks[OrderType.FLEX_1_0]
            .totalInAmount;
        uint256 totalInAmountSTRICT_0_1 = orderBox.orderBooks[OrderType
            .STRICT_0_1]
            .totalInAmount;
        uint256 totalInAmountSTRICT_1_0 = orderBox.orderBooks[OrderType
            .STRICT_1_0]
            .totalInAmount;
        (
            rate,
            refundStatus,
            partiallyRefundRate,
            executingAmount0WithoutSpread,
            executingAmount1WithoutSpread
        ) = _priceCalculateRates(
            orderBox,
            totalInAmountFLEX_0_1,
            totalInAmountFLEX_1_0,
            totalInAmountSTRICT_0_1,
            totalInAmountSTRICT_1_0
        );

        {
            if (refundStatus == 0) {
                partiallyRefundOrderType = OrderType.STRICT_0_1;
                //refundRate = 0;
            } else if (refundStatus == 1) {
                partiallyRefundOrderType = OrderType.STRICT_0_1;
            } else if (refundStatus == 2) {
                partiallyRefundOrderType = OrderType.FLEX_0_1;
            } else if (refundStatus == 3) {
                partiallyRefundOrderType = OrderType.STRICT_1_0;
            } else if (refundStatus == 4) {
                partiallyRefundOrderType = OrderType.FLEX_1_0;
            }
        }
        emit ExecutionSummary(
            boxNumber,
            uint8(partiallyRefundOrderType),
            rate,
            partiallyRefundRate,
            totalInAmountFLEX_0_1,
            totalInAmountFLEX_1_0,
            totalInAmountSTRICT_0_1,
            totalInAmountSTRICT_1_0
        );
        _updateReservesAndMarketFeePoolByExecution(
            orderBox.spreadRate,
            executingAmount0WithoutSpread,
            executingAmount1WithoutSpread,
            rate
        );
    }

    /**
     * @notice Detects if this OrderBox is finished
     * @param orders Target OrderBox
     * @param lastFinishedOrderType Latest OrderType which is executed
     **/
    function _isBoxFinished(
        OrderBox storage orders,
        OrderType lastFinishedOrderType
    ) private view returns (bool) {
        // If orderType is STRICT_1_0, no book is left
        if (lastFinishedOrderType == OrderType.STRICT_1_0) {
            return true;
        }
        for (uint256 i = uint256(lastFinishedOrderType.next()); i != 4; i++) {
            OrderBook memory book = orders.orderBooks[OrderType(i)];
            // If OrderBook has some order return false
            if (book.numOfOrder() != 0) {
                return false;
            }
        }
        return true;
    }

    function _calculateNewReserveAndMarketFeePool(
        uint256 spreadRate,
        uint256 executingAmountWithoutSpread,
        uint256 anotherExecutingAmountWithoutSpread,
        uint256 rate,
        Token tokenType
    ) internal returns (uint256, uint256) {
        uint256 totalSpread = executingAmountWithoutSpread.mulByRate(
            spreadRate
        );
        uint256 marketFee = totalSpread.mulByRate(MARKET_FEE_RATE);
        uint256 newReserve = executingAmountWithoutSpread +
            (totalSpread - marketFee) -
            _otherAmountBasedOnRate(
                tokenType.another(),
                anotherExecutingAmountWithoutSpread,
                rate
            );
        return (newReserve, marketFee);
    }

    function _getTokenType(bool isBuy, bool isStrict)
        internal
        pure
        returns (OrderType)
    {
        if (isBuy) {
            if (isStrict) {
                return OrderType.STRICT_0_1;
            } else {
                return OrderType.FLEX_0_1;
            }
        } else {
            if (isStrict) {
                return OrderType.STRICT_1_0;
            } else {
                return OrderType.FLEX_1_0;
            }
        }
    }
}

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.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/Interfaces/ERC20Interface.sol

pragma solidity >=0.6.6;


interface ERC20Interface is IERC20 {
    function name() external view returns (string memory);
}

// File: contracts/Interfaces/OracleInterface.sol

pragma solidity >=0.6.6;

interface OracleInterface {
    function latestPrice() external returns (uint256);

    function getVolatility() external returns (uint256);

    function latestId() external returns (uint256);
}

// File: contracts/Interfaces/SpreadCalculatorInterface.sol

pragma solidity >=0.6.6;


interface SpreadCalculatorInterface {
    function calculateCurrentSpread(
        uint256 _maturity,
        uint256 _strikePrice,
        OracleInterface oracle
    ) external returns (uint128);

    function calculateSpreadByAssetVolatility(OracleInterface oracle)
        external
        returns (uint128);
}

// File: contracts/BoxExchange/ETHBoxExchange/ETHBoxExchange.sol

pragma solidity >=0.6.6;






abstract contract ETHBoxExchange is BoxExchange {
    using SafeERC20 for ERC20Interface;

    ERC20Interface public immutable token; // token0
    // ETH is token1
    SpreadCalculatorInterface internal immutable spreadCalc;
    OracleInterface internal immutable oracle;

    mapping(address => uint256) internal ethBalances; // This balance increased by execution or refund

    event SpreadRate(uint128 indexed boxNumber, uint128 spreadRate);

    /**
     * @param _token ERC20 contract
     * @param _priceCalc Price Calculator contract
     * @param _marketFeeTaker Address of market fee taker (i.e. Lien Token)
     * @param _spreadCalc Spread Calculator contract
     * @param _oracle Oracle contract of token/ETH
     * @param _name Name of share token
     **/

    constructor(
        ERC20Interface _token,
        PriceCalculatorInterface _priceCalc,
        address _marketFeeTaker,
        SpreadCalculatorInterface _spreadCalc,
        OracleInterface _oracle,
        string memory _name
    ) public BoxExchange(_priceCalc, _marketFeeTaker, _name) {
        token = _token;
        spreadCalc = _spreadCalc;
        oracle = _oracle;
    }

    /**
     * @notice User can decide first supply of Share token
     **/
    function initializeExchange(uint256 tokenAmount, uint256 initialShare)
        external
        payable
    {
        _init(uint128(tokenAmount), uint128(msg.value), initialShare);
    }

    /**
     * @param timeout Revert if nextBoxNumber exceeds `timeout`
     * @param recipient Recipient of swapped token. If recipient == address(0), recipient is msg.sender
     * @param isLimit Whether the order restricts a large slippage.
     * @dev if isLimit is true and reserve0/reserve1 * 0.999 < rate, the order will be executed, otherwise ETH will be refunded
     * @dev if isLimit is false and reserve0/reserve1 * 0.95 < rate, the order will be executed, otherwise ETH will be refunded
     **/
    function orderEthToToken(
        uint256 timeout,
        address recipient,
        bool isLimit
    ) external payable isAmountSafe(msg.value) isInTime(timeout) {
        OrderType orderType = _getTokenType(false, isLimit);
        _addOrder(orderType, msg.value, recipient);
    }

    /**
     * @param timeout Revert if nextBoxNumber exceeds timeout
     * @param recipient Recipient of swapped token. If recipient == address(0), recipient is msg.sender
     * @param tokenAmount Amount of token that should be approved before executing this function
     * @param isLimit Whether the order restricts a large slippage.
     * @dev if isLimit is true and reserve0/reserve1 * 1.001 >  `rate`, the order will be executed, otherwise token will be refunded
     * @dev if isLimit is false and reserve0/reserve1 * 1.05 > `rate`, the order will be executed, otherwise token will be refunded
     **/
    function orderTokenToEth(
        uint256 timeout,
        address recipient,
        uint256 tokenAmount,
        bool isLimit
    ) external isAmountSafe(tokenAmount) isInTime(timeout) {
        OrderType orderType = _getTokenType(true, isLimit);
        _addOrder(orderType, tokenAmount, recipient);
    }

    /**
     * @notice LP provides liquidity and receives share token.
     * @notice iDOL required is calculated based on msg.value
     * @param timeout Revert if nextBoxNumber exceeds `timeout`
     * @param _minShares Minimum amount of share token LP will receive. If amount of share token is less than  `_minShares`, revert the transaction
     **/
    function addLiquidity(uint256 timeout, uint256 _minShares)
        external
        payable
        isAmountSafe(msg.value)
        isInTime(timeout)
    {
        (uint256 _reserve0, uint256 _reserve1) = _getReserves(); // gas savings
        _addLiquidity(
            _reserve0,
            _reserve1,
            msg.value,
            _minShares,
            Token.TOKEN1
        );
    }

    /**
     * @notice LP burns share token and receives ERC20 token and ETH.
     * @param timeout Revert if nextBoxNumber exceeds `timeout`
     * @param minEth Minimum amount of ETH LP will receive. If amount of ERC20 token is less than `minEth`, revert the transaction
     * @param minTokens Minimum amount of ERC20 token  LP will receive. If amount of LBT is less than `minTokens`, revert the transaction
     * @param sharesBurned Amount of share token to be burned
     **/
    function removeLiquidity(
        uint256 timeout,
        uint256 minEth,
        uint256 minTokens,
        uint256 sharesBurned
    ) external isInTime(timeout) {
        _removeLiquidity(minTokens, minEth, sharesBurned);
    }

    /**
     * @notice Executes orders that are unexecuted
     * @param maxOrderNum Max number of orders to be executed
     **/
    function executeUnexecutedBox(uint8 maxOrderNum) external {
        _triggerExecuteOrders(maxOrderNum);
    }

    /**
     * @notice Sends market fee to Lien Token
     **/
    function sendMarketFeeToLien() external {
        _triggerPayMarketFee();
    }

    // definitions of unique functions
    /**
     * @notice Withdraws ETH in ethBalances and set ethBalance of msg.sender to 0
     **/
    function withdrawETH() external {
        uint256 ethBalance = ethBalances[msg.sender];
        ethBalances[msg.sender] = 0;
        _transferEth(msg.sender, ethBalance);
    }

    /**
     * @notice Gets ethBalance of `recipient`
     * @param recipient Target address
     **/
    function getETHBalance(address recipient) external view returns (uint256) {
        return ethBalances[recipient];
    }

    // definition of abstract functions
    function _feeRate() internal override returns (uint128) {
        return spreadCalc.calculateSpreadByAssetVolatility(oracle);
    }

    function _receiveTokens(
        Token tokenType,
        address from,
        uint256 amount
    ) internal override {
        if (tokenType == Token.TOKEN0) {
            token.safeTransferFrom(from, address(this), amount);
        } else {
            require(msg.value == amount, "Incorrect ETH amount");
        }
    }

    function _sendTokens(
        Token tokenType,
        address to,
        uint256 amount
    ) internal override {
        if (tokenType == Token.TOKEN0) {
            token.safeTransfer(to, amount);
        } else {
            _transferEth(to, amount);
        }
    }

    function _payMarketFee(
        address _marketFeeTaker,
        uint256 amount0,
        uint256 amount1
    ) internal override {
        if (amount0 != 0) {
            token.safeTransfer(_marketFeeTaker, amount0);
        }
        if (amount1 != 0) {
            _transferEth(_marketFeeTaker, amount1);
        }
    }

    function _payForOrderExecution(
        Token tokenType,
        address to,
        uint256 amount
    ) internal override {
        if (tokenType == Token.TOKEN0) {
            token.safeTransfer(to, amount);
        } else {
            ethBalances[to] += amount;
        }
    }

    function _isCurrentOpenBoxExpired() internal override view returns (bool) {
        return block.number >= orderBoxes[_currentOpenBoxId()].expireAt;
    }

    function _openNewBox() internal override {
        super._openNewBox();
        uint256 _boxNumber = _currentOpenBoxId();
        emit SpreadRate(
            _boxNumber.toUint128(),
            orderBoxes[_boxNumber].spreadRate
        );
    }

    function _transferEth(address to, uint256 amount) internal {
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, ) = to.call{value: amount}("");
        require(success, "Transfer failed.");
    }
}

// File: contracts/BoxExchange/ETHBoxExchange/IDOLvsETH/IDOLvsETHBoxExchange.sol

pragma solidity >=0.6.6;


contract IDOLvsETHBoxExchange is ETHBoxExchange {
    /**
     * @param _token ERC20 token contract
     * @param _priceCalc Price Calculator contract
     * @param _marketFeeTaker Address of market fee taker (i.e. Lien Token)
     * @param _spreadCalc Spread Calculator contract
     * @param _oracle Oracle contract of ETH/USD
     * @param _name Name of share token
     **/
    constructor(
        ERC20Interface _token,
        PriceCalculatorInterface _priceCalc,
        address _marketFeeTaker,
        SpreadCalculatorInterface _spreadCalc,
        OracleInterface _oracle,
        string memory _name
    )
        public
        ETHBoxExchange(
            _token,
            _priceCalc,
            _marketFeeTaker,
            _spreadCalc,
            _oracle,
            _name
        )
    {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract ERC20Interface","name":"_token","type":"address"},{"internalType":"contract PriceCalculatorInterface","name":"_priceCalc","type":"address"},{"internalType":"address","name":"_marketFeeTaker","type":"address"},{"internalType":"contract SpreadCalculatorInterface","name":"_spreadCalc","type":"address"},{"internalType":"contract OracleInterface","name":"_oracle","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"bool","name":"isBuy","type":"bool"},{"indexed":true,"internalType":"uint32","name":"boxNumber","type":"uint32"},{"indexed":false,"internalType":"bool","name":"isLimit","type":"bool"},{"indexed":false,"internalType":"uint256","name":"tokenIn","type":"uint256"}],"name":"AcceptOrders","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":"bool","name":"isBuy","type":"bool"},{"indexed":true,"internalType":"uint32","name":"boxNumber","type":"uint32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refundAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outAmount","type":"uint256"}],"name":"Execution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"boxNumber","type":"uint32"},{"indexed":false,"internalType":"uint8","name":"partiallyRefundOrderType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"partiallyRefundRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalInAmountFLEX_0_1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalInAmountFLEX_1_0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalInAmountSTRICT_0_1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalInAmountSTRICT_1_0","type":"uint256"}],"name":"ExecutionSummary","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"},{"indexed":true,"internalType":"bool","name":"isAdd","type":"bool"},{"indexed":false,"internalType":"uint256","name":"movedToken0Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"movedToken1Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesMoved","type":"uint256"}],"name":"MoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"PayMarketFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint128","name":"boxNumber","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"spreadRate","type":"uint128"}],"name":"SpreadRate","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":false,"internalType":"uint128","name":"reserve0","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"reserve1","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"totalShare","type":"uint256"}],"name":"UpdateReserve","type":"event"},{"inputs":[{"internalType":"uint256","name":"timeout","type":"uint256"},{"internalType":"uint256","name":"_minShares","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"maxOrderNum","type":"uint8"}],"name":"executeUnexecutedBox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"boxNumber","type":"uint256"}],"name":"getBoxSummary","outputs":[{"internalType":"uint256","name":"executionStatusNumber","type":"uint256"},{"internalType":"uint256","name":"flexToken0InAmount","type":"uint256"},{"internalType":"uint256","name":"strictToken0InAmount","type":"uint256"},{"internalType":"uint256","name":"flexToken1InAmount","type":"uint256"},{"internalType":"uint256","name":"strictToken1InAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"getETHBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExchangeData","outputs":[{"internalType":"uint256","name":"boxNumber","type":"uint256"},{"internalType":"uint256","name":"_reserve0","type":"uint256"},{"internalType":"uint256","name":"_reserve1","type":"uint256"},{"internalType":"uint256","name":"totalShare","type":"uint256"},{"internalType":"uint256","name":"latestSpreadRate","type":"uint256"},{"internalType":"uint256","name":"token0PerShareE18","type":"uint256"},{"internalType":"uint256","name":"token1PerShareE18","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"}],"name":"getOrderAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"initialShare","type":"uint256"}],"name":"initializeExchange","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"marketFeePool0","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketFeePool1","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeout","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"isLimit","type":"bool"}],"name":"orderEthToToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeout","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"bool","name":"isLimit","type":"bool"}],"name":"orderTokenToEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeout","type":"uint256"},{"internalType":"uint256","name":"minEth","type":"uint256"},{"internalType":"uint256","name":"minTokens","type":"uint256"},{"internalType":"uint256","name":"sharesBurned","type":"uint256"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sendMarketFeeToLien","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract ERC20Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"boxNumber","type":"uint256"},{"internalType":"bool","name":"isBuy","type":"bool"},{"internalType":"bool","name":"isLimit","type":"bool"}],"name":"whenToExecute","outputs":[{"internalType":"bool","name":"isExecuted","type":"bool"},{"internalType":"uint256","name":"boxCount","type":"uint256"},{"internalType":"uint256","name":"orderCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101406040523480156200001257600080fd5b5060405162003e7b38038062003e7b833981810160405260c08110156200003857600080fd5b815160208301516040808501516060860151608087015160a0880180519451969895979396929591949293820192846401000000008211156200007a57600080fd5b9083019060208201858111156200009057600080fd5b8251640100000000811182820188101715620000ab57600080fd5b82525081516020918201929091019080838360005b83811015620000da578181015183820152602001620000c0565b50505050905090810190601f168015620001085780820380516001836020036101000a031916815260200191505b50604052505050858585858585848482806040518060400160405280600581526020017f736861726500000000000000000000000000000000000000000000000000000081525081600390805190602001906200016792919062000213565b5080516200017d90600490602084019062000213565b50506005805460ff191660121790555033606090811b6080526001600160601b031984821b811660c0529083901b1660a052620001c460086001600160e01b03620001fd16565b5050506001600160601b0319606096871b811660e05292861b8316610100525090931b9092166101205250620002b89650505050505050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025657805160ff191683800117855562000286565b8280016001018555821562000286579182015b828111156200028657825182559160200191906001019062000269565b506200029492915062000298565b5090565b620002b591905b808211156200029457600081556001016200029f565b90565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c613b536200032860003980613378525080613349525080610f9252806121d8528061263552806128f5528061365752508061348e5250806118cd5250806117fe5250613b536000f3fe60806040526004361061019c5760003560e01c80639c558c4b116100ec578063d5855e7a1161008a578063e086e5ec11610064578063e086e5ec146106cc578063f88bf15a146106e1578063fbb747a81461071d578063fc0c546a146107515761019c565b8063d5855e7a1461062f578063da84fb0b14610644578063dd62ed3e146106915761019c565b8063a457c2d7116100c6578063a457c2d71461055f578063a9059cbb14610598578063b196a352146105d1578063c9a01af9146106025761019c565b80639c558c4b146104d25780639cd441da146104e7578063a3fee0721461050a5761019c565b806339509351116101595780636f0fe850116101335780636f0fe8501461042b57806370a082311461044e57806384c76abc1461048157806395d89b41146104bd5761019c565b806339509351146103565780633bb66a7b1461038f57806359e71314146103c25761019c565b806306fdde03146101a1578063095ea7b31461022b57806318160ddd146102785780631dfc8fb91461029f57806323b872dd146102e8578063313ce5671461032b575b600080fd5b3480156101ad57600080fd5b506101b6610782565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f05781810151838201526020016101d8565b50505050905090810190601f16801561021d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023757600080fd5b506102646004803603604081101561024e57600080fd5b506001600160a01b038135169060200135610819565b604080519115158252519081900360200190f35b34801561028457600080fd5b5061028d610837565b60408051918252519081900360200190f35b3480156102ab57600080fd5b506102e6600480360360808110156102c257600080fd5b508035906001600160a01b036020820135169060408101359060600135151561083d565b005b3480156102f457600080fd5b506102646004803603606081101561030b57600080fd5b506001600160a01b038135811691602081013590911690604001356108fa565b34801561033757600080fd5b50610340610988565b6040805160ff9092168252519081900360200190f35b34801561036257600080fd5b506102646004803603604081101561037957600080fd5b506001600160a01b038135169060200135610991565b34801561039b57600080fd5b5061028d600480360360208110156103b257600080fd5b50356001600160a01b03166109e5565b3480156103ce57600080fd5b5061040b600480360360808110156103e557600080fd5b506001600160a01b03813516906020810135906040810135151590606001351515610a04565b604080519315158452602084019290925282820152519081900360600190f35b6102e66004803603604081101561044157600080fd5b5080359060200135610a2e565b34801561045a57600080fd5b5061028d6004803603602081101561047157600080fd5b50356001600160a01b0316610a3d565b34801561048d57600080fd5b5061028d600480360360408110156104a457600080fd5b5080356001600160a01b0316906020013560ff16610a58565b3480156104c957600080fd5b506101b6610ac7565b3480156104de57600080fd5b506102e6610b28565b6102e6600480360360408110156104fd57600080fd5b5080359060200135610b32565b34801561051657600080fd5b506105346004803603602081101561052d57600080fd5b5035610bf1565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561056b57600080fd5b506102646004803603604081101561058257600080fd5b506001600160a01b038135169060200135610d0c565b3480156105a457600080fd5b50610264600480360360408110156105bb57600080fd5b506001600160a01b038135169060200135610d7a565b3480156105dd57600080fd5b506105e6610d8e565b604080516001600160801b039092168252519081900360200190f35b34801561060e57600080fd5b506102e66004803603602081101561062557600080fd5b503560ff16610d9d565b34801561063b57600080fd5b506105e6610da9565b34801561065057600080fd5b50610659610dbd565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561069d57600080fd5b5061028d600480360360408110156106b457600080fd5b506001600160a01b0381358116916020013516610e39565b3480156106d857600080fd5b506102e6610e64565b3480156106ed57600080fd5b506102e66004803603608081101561070457600080fd5b5080359060208101359060408101359060600135610e83565b6102e66004803603606081101561073357600080fd5b508035906001600160a01b0360208201351690604001351515610edc565b34801561075d57600080fd5b50610766610f90565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b820191906000526020600020905b8154815290600101906020018083116107f157829003601f168201915b505050505090505b90565b600061082d610826610fb4565b8484610fb8565b5060015b92915050565b60025490565b8180610890576040805162461bcd60e51b815260206004820152601e60248201527f416d6f756e742073686f756c6420626520626967676572207468616e20300000604482015290519081900360640190fd5b846108996110a4565b81116108d7576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b60006108e46001856110ae565b90506108f18186886110e2565b50505050505050565b60006109078484846111dd565b61097d84610913610fb4565b61097885604051806060016040528060288152602001613a17602891396001600160a01b038a16600090815260016020526040812090610951610fb4565b6001600160a01b03168152602081019190915260400160002054919063ffffffff61134416565b610fb8565b5060015b9392505050565b60055460ff1690565b600061082d61099e610fb4565b8461097885600160006109af610fb4565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6113db16565b6001600160a01b0381166000908152600c60205260409020545b919050565b6000806000610a1d87610a178787611435565b88611461565b9250925092505b9450945094915050565b610a398234836117a3565b5050565b6001600160a01b031660009081526020819052604090205490565b60006008610a646110a4565b81548110610a6e57fe5b90600052602060002090600202016000016000836003811115610a8d57fe5b6003811115610a9857fe5b8152602080820192909252604090810160009081206001600160a01b0387168252909252902054905092915050565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b610b30611873565b565b3480610b85576040805162461bcd60e51b815260206004820152601e60248201527f416d6f756e742073686f756c6420626520626967676572207468616e20300000604482015290519081900360640190fd5b82610b8e6110a4565b8111610bcc576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b600080610bd76118f3565b91509150610be9828234886001611911565b505050505050565b600080600080600080600960000160199054906101000a900463ffffffff1663ffffffff16905060088781548110610c2557fe5b60009182526020808320838052600292830201905260409091200154600880549196509088908110610c5357fe5b60009182526020808320600280855292830201905260409091200154600880549195509088908110610c8157fe5b6000918252602080832060018452600292830201905260409091200154600880549194509088908110610cb057fe5b6000918252602080832060038452600292830201905260409091200154915080871015610ce05760029550610d02565b8087148015610cf85750600954600160e81b900460ff165b15610d0257600195505b5091939590929450565b600061082d610d19610fb4565b8461097885604051806060016040528060258152602001613af96025913960016000610d43610fb4565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61134416565b600061082d610d87610fb4565b84846111dd565b6006546001600160801b031681565b610da681611a21565b50565b60055461010090046001600160801b031681565b6000806000806000806000610dd06110a4565b9650610dda6118f3565b809650819750505060088781548110610def57fe5b60009182526020909120600160029092020101546001600160801b03169250610e16610837565b9350610e228685611a35565b9150610e2e8585611a35565b905090919293949596565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336000818152600c60205260408120805491905590610da69082611a5f565b83610e8c6110a4565b8111610eca576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b610ed5838584611af8565b5050505050565b3480610f2f576040805162461bcd60e51b815260206004820152601e60248201527f416d6f756e742073686f756c6420626520626967676572207468616e20300000604482015290519081900360640190fd5b83610f386110a4565b8111610f76576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000610f836000856110ae565b9050610be98134876110e2565b7f000000000000000000000000000000000000000000000000000000000000000081565b3390565b6001600160a01b038316610ffd5760405162461bcd60e51b8152600401808060200182810382526024815260200180613aab6024913960400191505060405180910390fd5b6001600160a01b0382166110425760405162461bcd60e51b81526004018080602001828103825260228152602001806139616022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6008546000190190565b600082156110cc5781156110c457506002610831565b506000610831565b81156110da57506003610831565b506001610831565b6110ea611c3e565b60006110f46110a4565b9050611101600582611c53565b6001600160a01b038216611113573391505b61113161112a85600381111561112557fe5b61217c565b33856121b7565b6111628484846008858154811061114457fe5b9060005260206000209060020201612256909392919063ffffffff16565b8063ffffffff1661117d85600381111561117857fe5b612332565b1515836001600160a01b03167fd54c711b2fd79474dc74606062c8605c0dac9e6089a74320ccf470dc2e33e19a6111be8860038111156111b957fe5b61235e565b604080519115158252602082018990528051918290030190a450505050565b6001600160a01b0383166112225760405162461bcd60e51b8152600401808060200182810382526025815260200180613a606025913960400191505060405180910390fd5b6001600160a01b0382166112675760405162461bcd60e51b815260040180806020018281038252602381526020018061391c6023913960400191505060405180910390fd5b61127283838361186e565b6112b581604051806060016040528060268152602001613983602691396001600160a01b038616600090815260208190526040902054919063ffffffff61134416565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546112ea908263ffffffff6113db16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156113d35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611398578181015183820152602001611380565b50505050905090810190601f1680156113c55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610981576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008280156114415750815b1561144e57506002610831565b8261083157811561082d57506003610831565b600080600061146e6110a4565b8411156114835750600091508190508061179a565b60006008858154811061149257fe5b9060005260206000209060020201905060608160000160008860038111156114b657fe5b60038111156114c157fe5b60038111156114cc57fe5b815260200190815260200160002060010180548060200260200160405190810160405280929190818152602001828054801561153157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611513575b5050600954600b54600a54959650600160c81b90910463ffffffff16949093506000925060ff169050600381111561156557fe5b600954909150600160e81b900460ff16600080805b875181146115c3578e6001600160a01b031688828151811061159857fe5b60200260200101516001600160a01b031614156115bb57600192508091506115c3565b60010161157a565b50858c10806115f757508280156115d95750858c145b80156115f75750838d10806115f75750838d1480156115f757508481105b156116155750600199506000985088975061179a9650505050505050565b8161163257506000995089985088975061179a9650505050505050565b6000868d1480156116405750835b1561173c57845b8e81101561170d576117018a600083600381111561166157fe5b600381111561166c57fe5b600381111561167757fe5b8152602001908152602001600020604051806040016040529081600182018054806020026020016040519081016040528092919081815260200182805480156116e957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116116cb575b50505050508152602001600282015481525050612370565b90910190600101611647565b5060019a5061173286611726838563ffffffff6113db16565b9063ffffffff61237516565b6001019950611790565b60005b8e8114611764576117588a600083600381111561166157fe5b9091019060010161173f565b506117758d8863ffffffff61237516565b6001019a5061178a818363ffffffff6113db16565b60010199505b5050505050505050505b93509350939050565b6117ab610837565b156117f3576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461182857600080fd5b61183283836123b7565b61183c3382612442565b611851600033856001600160801b03166121b7565b611866600133846001600160801b03166121b7565b61186e61253e565b505050565b60008061187e6125c5565b9150915061188d6000806125e1565b604080518381526020810183905281517f72715c0cf03be5e4479cb972219945b83aee28f65875993b1de62bda86892d1e929181900390910190a1610a397f00000000000000000000000000000000000000000000000000000000000000008383612622565b6006546007546001600160801b03600160801b909204821692911690565b600080600061192286898987612672565b9250925092508481101561197d576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f7567682073686172657300604482015290519081900360640190fd5b611989600033856121b7565b611995600133846121b7565b6119c86119b06119ab8a8663ffffffff6113db16565b6126e9565b6119c36119ab8a8663ffffffff6113db16565b6123b7565b6119d23382612442565b6040805184815260208101849052808201839052905160019133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b610da68160ff16611a306110a4565b611c53565b600061098182611a5385670de0b6b3a764000063ffffffff61273116565b9063ffffffff61278a16565b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114611aaa576040519150601f19603f3d011682016040523d82523d6000602084013e611aaf565b606091505b505090508061186e576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b600080611b036118f3565b915091506000611b11610837565b90506000611b2982611a53868863ffffffff61273116565b90506000611b4183611a53868963ffffffff61273116565b9050878210158015611b535750868110155b611ba4576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f75676820746f6b656e7300604482015290519081900360640190fd5b611bcd611bba6119ab878563ffffffff61237516565b6119c36119ab878563ffffffff61237516565b611bd733876127cc565b611be3600033846128d4565b611bef600133836128d4565b6040805183815260208101839052808201889052905160009133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b611c4661292c565b15610b3057610b3061253e565b611c5b613864565b6040805160a0810190915260098054829060ff166003811115611c7a57fe5b6003811115611c8557fe5b81529054610100810467ffffffffffffffff166020830152600160481b81046001600160801b03166040830152600160c81b810463ffffffff166060830152600160e81b900460ff1615156080909101529050611ce0613894565b60408051808201909152600a8054829060ff166003811115611cfe57fe5b6003811115611d0957fe5b8152602001600182015481525050905082826060015163ffffffff1610158015611d4b5750611d3661292c565b1580611d4b575082826060015163ffffffff16115b15611d57575050610a39565b8160800151611dda576000806000611d72856060015161296e565b9194509250905084836003811115611d8657fe5b90816003811115611d9357fe5b905250611d9f82612ad7565b67ffffffffffffffff166020860152611db7816126e9565b6001600160801b0316604086015250506001608084015250600080825260208201525b83156120935760006008836060015163ffffffff1681548110611df957fe5b600091825260208220845160029092020191906003811115611e1757fe5b6003811115611e2257fe5b815260200190815260200160002090506000806000611eae84611e4e8760000151600381111561112557fe5b60208801518851611e66908b9063ffffffff612b2016565b8a604001516001600160801b031660088c6060015163ffffffff1681548110611e8b57fe5b60009182526020909120600160029092020101546001600160801b03168e612bea565b9250925092508215612072576000611eee6008886060015163ffffffff1681548110611ed657fe5b90600052602060002090600202018760000151612d21565b90506008876060015163ffffffff1681548110611f0757fe5b600091825260208220885160029092020191906003811115611f2557fe5b6003811115611f3057fe5b81526020019081526020016000206000600182016000611f5091906138ab565b60028201600090555050801561203d5760608701805163ffffffff600191820116909152600060808901528751600980548a93919291839160ff191690836003811115611f9957fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff001990951694909417949094169290921716919091179290921691909117905550610a3995505050505050565b855161205390600381111561204e57fe5b612e3c565b8690600381111561206057fe5b9081600381111561206d57fe5b905250505b61207b82612e62565b63ffffffff1660208601529096039550611dda915050565b815160098054849290829060ff191660018360038111156120b057fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff00199095169490941794909416929092171691909117929092169190911790558051600a8054839290829060ff1916600183600381111561216457fe5b02179055506020820151816001015590505050505050565b60008082600381111561218b57fe5b14806121a2575060028260038111156121a057fe5b145b156121af575060006109ff565b5060016109ff565b60008360018111156121c557fe5b141561220b576122066001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683308463ffffffff612ea716565b61186e565b80341461186e576040805162461bcd60e51b8152602060048201526014602482015273125b98dbdc9c9958dd0811551208185b5bdd5b9d60621b604482015290519081900360640190fd5b6000848185600381111561226657fe5b600381111561227157fe5b8152602080820192909252604090810160009081206001600160a01b03861682529283905220549091506122cf576001818101805491820181556000908152602090200180546001600160a01b0319166001600160a01b0384161790555b6001600160a01b0382166000908152602082905260409020546122f8908463ffffffff6113db16565b6001600160a01b0383166000908152602083905260409020556002810154612326908463ffffffff6113db16565b60029091015550505050565b60008082600381111561234157fe5b1480610831575060025b82600381111561235757fe5b1492915050565b600061236982612f07565b1592915050565b515190565b600061098183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611344565b600680546001600160801b03908116600160801b8583160217909155600780546001600160801b0319169183169190911790557f17226eb45b590dffadbc03fba4681aa4c198e7e838ab8a6fb7e32a51634b3e808282612415610837565b604080516001600160801b0394851681529290931660208301528183015290519081900360600190a15050565b6001600160a01b03821661249d576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6124a96000838361186e565b6002546124bc908263ffffffff6113db16565b6002556001600160a01b0382166000908152602081905260409020546124e8908263ffffffff6113db16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b612546612f24565b60006125506110a4565b905061255b816126e9565b6001600160801b03167f5ab5824685efa3ca4a723a2f94da7d225628bfae130cc14663932a3bf11140a86008838154811061259257fe5b600091825260209182902060016002909202010154604080516001600160801b039092168252519081900390910190a250565b6005546006546001600160801b03610100909204821692911690565b6005805470ffffffffffffffffffffffffffffffff0019166101006001600160801b0394851602179055600680546001600160801b03191691909216179055565b8115612662576126626001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016848463ffffffff612f9516565b801561186e5761186e8382611a5f565b600080808084600181111561268357fe5b14156126c5578661269e87611a53838963ffffffff61273116565b6126ba88611a536126ad610837565b8c9063ffffffff61273116565b925092509250610a24565b6126d985611a53898963ffffffff61273116565b876126ba87611a536126ad610837565b6000600160801b821061272d5760405162461bcd60e51b81526004018080602001828103825260278152602001806139a96027913960400191505060405180910390fd5b5090565b60008261274057506000610831565b8282028284828161274d57fe5b04146109815760405162461bcd60e51b81526004018080602001828103825260218152602001806139d06021913960400191505060405180910390fd5b600061098183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612fe7565b6001600160a01b0382166128115760405162461bcd60e51b8152600401808060200182810382526021815260200180613a3f6021913960400191505060405180910390fd5b61281d8260008361186e565b6128608160405180606001604052806022815260200161393f602291396001600160a01b038516600090815260208190526040902054919063ffffffff61134416565b6001600160a01b03831660009081526020819052604090205560025461288c908263ffffffff61237516565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60008360018111156128e257fe5b1415612922576122066001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838363ffffffff612f9516565b61186e8282611a5f565b600060086129386110a4565b8154811061294257fe5b6000918252602090912060029091020160010154600160801b90046001600160801b0316431015919050565b60008060008060088563ffffffff168154811061298757fe5b6000918252602080832083805260029283020190819052604080842083015460018552818520840154848652828620850154600387529286209094015492955084938493919290916129dc888585858561304c565b919d50929b509098509096509450866129f85760029a50612a3c565b8660011415612a0a5760029a50612a3c565b8660021415612a1c5760009a50612a3c565b8660031415612a2e5760039a50612a3c565b8660041415612a3c5760019a505b8b63ffffffff167f24f971a36bb1ccca6d5a24e46c30c46b44dc72fdf6b667edd669dee3585552a58c6003811115612a7057fe5b6040805160ff9092168252602082018d90528181018e9052606082018890526080820187905260a0820186905260c08201859052519081900360e00190a26001880154612ac8906001600160801b031687878c6130e2565b50505050505050509193909250565b600068010000000000000000821061272d5760405162461bcd60e51b81526004018080602001828103825260268152602001806139f16026913960400191505060405180910390fd5b6000612b3182600381111561112557fe5b6001811115612b3c57fe5b8351612b4d90600381111561112557fe5b6001811115612b5857fe5b14612b6557506000610831565b8251612b7b906003811115612b7657fe5b612f07565b15612bb857612b8f826003811115612b7657fe5b15612ba95750602082015167ffffffffffffffff16610831565b50670de0b6b3a7640000610831565b612bc78260038111156111b957fe5b15612be15750602082015167ffffffffffffffff16610831565b50600092915050565b6000806000806000612c708c604051806040016040529081600182018054806020026020016040519081016040528092919081815260200182805480156116e9576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116116cb5750505050508152602001600282015481525050612370565b90508991505b858a83031015612cee57808210612c9a575060019350600092508890039050612d14565b60008c6001018381548110612cab57fe5b60009182526020808320909101546001600160a01b0316808352908f9052604090912054909150612ce2908d9083908d8d8d613191565b50600190910190612c76565b808210612d08575060019350600092508890039050612d14565b50600093509150508681035b9750975097945050505050565b60006003826003811115612d3157fe5b1415612d3f57506001610831565b6000612d5083600381111561204e57fe5b6003811115612d5b57fe5b90505b8060041461097d57612d6e6138c9565b846000836003811115612d7d57fe5b6003811115612d8857fe5b6003811115612d9357fe5b815260200190815260200160002060405180604001604052908160018201805480602002602001604051908101604052809291908181526020018280548015612e0557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612de7575b505050505081526020016002820154815250509050612e2381612370565b15612e3357600092505050610831565b50600101612d5e565b60006004826003811115612e4c57fe5b60010181612e5657fe5b06600381111561083157fe5b6000640100000000821061272d5760405162461bcd60e51b8152600401808060200182810382526026815260200180613a856026913960400191505060405180910390fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612f01908590613294565b50505050565b600080826003811115612f1657fe5b14806108315750600161234b565b6008612f48612f31613345565b612f3d43600201612e62565b63ffffffff16613410565b8154600180820184556000938452602093849020835160029093020101805492909301516001600160801b03199092166001600160801b03918216178116600160801b9190921602179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261186e908490613294565b600081836130365760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611398578181015183820152602001611380565b50600083858161304257fe5b0495945050505050565b600185015460009081908190819081906001600160801b0316670de0b6b3a7640000016130cb61307c8b83611a35565b61308c8a8463ffffffff611a3516565b61309c8c8563ffffffff611a3516565b6130ac8b8663ffffffff611a3516565b6006546007546001600160801b03600160801b9092048216911661343a565b939f929e50909c509a509098509650505050505050565b6000806000806000806130f98a8a8a8a6000613551565b6006546005546001600160801b03600160801b90920482169093019850610100909204909116019350600091508190506131378a898b8a6001613551565b6007546006546001600160801b0391821690930197509190911601925061316d91506131649050856126e9565b6119c3856126e9565b613187613179836126e9565b613182836126e9565b6125e1565b5050505050505050565b60006131a78760018111156131a257fe5b6135b7565b905060006131bb868663ffffffff6135dc16565b905060006131f66131da670de0b6b3a76400008663ffffffff6113db16565b6131ea898563ffffffff61237516565b9063ffffffff611a3516565b905060006132058a83886135fa565b90506132128a8a85613636565b61321d848a83613636565b886001600160a01b031661322f6110a4565b63ffffffff1660008c600181111561324357fe5b604080518d815260208101899052808201879052905192909114917fb8221d4e9feabcc28c5e0878f3196eecf38320725898780b22a503239b6bc9969181900360600190a450505050505050505050565b60606132e9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136a79092919063ffffffff16565b80519091501561186e5780806020019051602081101561330857600080fd5b505161186e5760405162461bcd60e51b815260040180806020018281038252602a815260200180613acf602a913960400191505060405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e66ed1a7f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b1580156133df57600080fd5b505af11580156133f3573d6000803e3d6000fd5b505050506040513d602081101561340957600080fd5b5051905090565b613418613894565b50604080518082019091526001600160801b0392831681529116602082015290565b600080600080600061344a6138e3565b6040805163f5eeb35760e01b8152600481018e9052602481018d9052604481018c9052606481018b9052608481018a905260a4810189905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163f5eeb3579160c48083019260a0929190829003018186803b1580156134d457600080fd5b505afa1580156134e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525060a081101561350d57600080fd5b509050806000602002015181600160200201518260026020020151836003602002015184600460200201519550955095509550955050965096509650965096915050565b60008080613565878963ffffffff6135dc16565b90506000613581826702c68af0bb14000063ffffffff6135dc16565b9050600061359e6135978760018111156131a257fe5b89896135fa565b9282900389019290920393509150509550959350505050565b6000808260018111156135c657fe5b14156135d4575060016109ff565b5060006109ff565b6000610981670de0b6b3a7640000611a53858563ffffffff61273116565b60008084600181111561360957fe5b14156136265761361f838363ffffffff6135dc16565b9050610981565b61361f838363ffffffff611a3516565b600083600181111561364457fe5b1415613684576122066001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838363ffffffff612f9516565b6001600160a01b0382166000908152600c60205260409020805482019055505050565b60606136b684846000856136be565b949350505050565b60606136c98561382b565b61371a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106137595780518252601f19909201916020918201910161373a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146137bb576040519150601f19603f3d011682016040523d82523d6000602084013e6137c0565b606091505b509150915081156137d45791506136b69050565b8051156137e45780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315611398578181015183820152602001611380565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906136b6575050151592915050565b6040805160a081019091528060008152600060208201819052604082018190526060820181905260809091015290565b604080518082019091526000808252602082015290565b5080546000825590600052602060002090810190610da69190613901565b604051806040016040528060608152602001600081525090565b6040518060a001604052806005906020820280368337509192915050565b61081691905b8082111561272d576000815560010161390756fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636553616665436173743a2076616c756520646f65736e27742066697420696e203132382062697473536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e203634206269747345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e203332206269747345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220fc8042f134361df36258d94edf8f6d257bae11b393a73d0aa7846d4648c458b864736f6c63430006060033000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad782000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac8200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000e53484152452d49444f4c2d455448000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061019c5760003560e01c80639c558c4b116100ec578063d5855e7a1161008a578063e086e5ec11610064578063e086e5ec146106cc578063f88bf15a146106e1578063fbb747a81461071d578063fc0c546a146107515761019c565b8063d5855e7a1461062f578063da84fb0b14610644578063dd62ed3e146106915761019c565b8063a457c2d7116100c6578063a457c2d71461055f578063a9059cbb14610598578063b196a352146105d1578063c9a01af9146106025761019c565b80639c558c4b146104d25780639cd441da146104e7578063a3fee0721461050a5761019c565b806339509351116101595780636f0fe850116101335780636f0fe8501461042b57806370a082311461044e57806384c76abc1461048157806395d89b41146104bd5761019c565b806339509351146103565780633bb66a7b1461038f57806359e71314146103c25761019c565b806306fdde03146101a1578063095ea7b31461022b57806318160ddd146102785780631dfc8fb91461029f57806323b872dd146102e8578063313ce5671461032b575b600080fd5b3480156101ad57600080fd5b506101b6610782565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f05781810151838201526020016101d8565b50505050905090810190601f16801561021d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023757600080fd5b506102646004803603604081101561024e57600080fd5b506001600160a01b038135169060200135610819565b604080519115158252519081900360200190f35b34801561028457600080fd5b5061028d610837565b60408051918252519081900360200190f35b3480156102ab57600080fd5b506102e6600480360360808110156102c257600080fd5b508035906001600160a01b036020820135169060408101359060600135151561083d565b005b3480156102f457600080fd5b506102646004803603606081101561030b57600080fd5b506001600160a01b038135811691602081013590911690604001356108fa565b34801561033757600080fd5b50610340610988565b6040805160ff9092168252519081900360200190f35b34801561036257600080fd5b506102646004803603604081101561037957600080fd5b506001600160a01b038135169060200135610991565b34801561039b57600080fd5b5061028d600480360360208110156103b257600080fd5b50356001600160a01b03166109e5565b3480156103ce57600080fd5b5061040b600480360360808110156103e557600080fd5b506001600160a01b03813516906020810135906040810135151590606001351515610a04565b604080519315158452602084019290925282820152519081900360600190f35b6102e66004803603604081101561044157600080fd5b5080359060200135610a2e565b34801561045a57600080fd5b5061028d6004803603602081101561047157600080fd5b50356001600160a01b0316610a3d565b34801561048d57600080fd5b5061028d600480360360408110156104a457600080fd5b5080356001600160a01b0316906020013560ff16610a58565b3480156104c957600080fd5b506101b6610ac7565b3480156104de57600080fd5b506102e6610b28565b6102e6600480360360408110156104fd57600080fd5b5080359060200135610b32565b34801561051657600080fd5b506105346004803603602081101561052d57600080fd5b5035610bf1565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561056b57600080fd5b506102646004803603604081101561058257600080fd5b506001600160a01b038135169060200135610d0c565b3480156105a457600080fd5b50610264600480360360408110156105bb57600080fd5b506001600160a01b038135169060200135610d7a565b3480156105dd57600080fd5b506105e6610d8e565b604080516001600160801b039092168252519081900360200190f35b34801561060e57600080fd5b506102e66004803603602081101561062557600080fd5b503560ff16610d9d565b34801561063b57600080fd5b506105e6610da9565b34801561065057600080fd5b50610659610dbd565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561069d57600080fd5b5061028d600480360360408110156106b457600080fd5b506001600160a01b0381358116916020013516610e39565b3480156106d857600080fd5b506102e6610e64565b3480156106ed57600080fd5b506102e66004803603608081101561070457600080fd5b5080359060208101359060408101359060600135610e83565b6102e66004803603606081101561073357600080fd5b508035906001600160a01b0360208201351690604001351515610edc565b34801561075d57600080fd5b50610766610f90565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b820191906000526020600020905b8154815290600101906020018083116107f157829003601f168201915b505050505090505b90565b600061082d610826610fb4565b8484610fb8565b5060015b92915050565b60025490565b8180610890576040805162461bcd60e51b815260206004820152601e60248201527f416d6f756e742073686f756c6420626520626967676572207468616e20300000604482015290519081900360640190fd5b846108996110a4565b81116108d7576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b60006108e46001856110ae565b90506108f18186886110e2565b50505050505050565b60006109078484846111dd565b61097d84610913610fb4565b61097885604051806060016040528060288152602001613a17602891396001600160a01b038a16600090815260016020526040812090610951610fb4565b6001600160a01b03168152602081019190915260400160002054919063ffffffff61134416565b610fb8565b5060015b9392505050565b60055460ff1690565b600061082d61099e610fb4565b8461097885600160006109af610fb4565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6113db16565b6001600160a01b0381166000908152600c60205260409020545b919050565b6000806000610a1d87610a178787611435565b88611461565b9250925092505b9450945094915050565b610a398234836117a3565b5050565b6001600160a01b031660009081526020819052604090205490565b60006008610a646110a4565b81548110610a6e57fe5b90600052602060002090600202016000016000836003811115610a8d57fe5b6003811115610a9857fe5b8152602080820192909252604090810160009081206001600160a01b0387168252909252902054905092915050565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b610b30611873565b565b3480610b85576040805162461bcd60e51b815260206004820152601e60248201527f416d6f756e742073686f756c6420626520626967676572207468616e20300000604482015290519081900360640190fd5b82610b8e6110a4565b8111610bcc576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b600080610bd76118f3565b91509150610be9828234886001611911565b505050505050565b600080600080600080600960000160199054906101000a900463ffffffff1663ffffffff16905060088781548110610c2557fe5b60009182526020808320838052600292830201905260409091200154600880549196509088908110610c5357fe5b60009182526020808320600280855292830201905260409091200154600880549195509088908110610c8157fe5b6000918252602080832060018452600292830201905260409091200154600880549194509088908110610cb057fe5b6000918252602080832060038452600292830201905260409091200154915080871015610ce05760029550610d02565b8087148015610cf85750600954600160e81b900460ff165b15610d0257600195505b5091939590929450565b600061082d610d19610fb4565b8461097885604051806060016040528060258152602001613af96025913960016000610d43610fb4565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61134416565b600061082d610d87610fb4565b84846111dd565b6006546001600160801b031681565b610da681611a21565b50565b60055461010090046001600160801b031681565b6000806000806000806000610dd06110a4565b9650610dda6118f3565b809650819750505060088781548110610def57fe5b60009182526020909120600160029092020101546001600160801b03169250610e16610837565b9350610e228685611a35565b9150610e2e8585611a35565b905090919293949596565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336000818152600c60205260408120805491905590610da69082611a5f565b83610e8c6110a4565b8111610eca576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b610ed5838584611af8565b5050505050565b3480610f2f576040805162461bcd60e51b815260206004820152601e60248201527f416d6f756e742073686f756c6420626520626967676572207468616e20300000604482015290519081900360640190fd5b83610f386110a4565b8111610f76576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000610f836000856110ae565b9050610be98134876110e2565b7f000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad78281565b3390565b6001600160a01b038316610ffd5760405162461bcd60e51b8152600401808060200182810382526024815260200180613aab6024913960400191505060405180910390fd5b6001600160a01b0382166110425760405162461bcd60e51b81526004018080602001828103825260228152602001806139616022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6008546000190190565b600082156110cc5781156110c457506002610831565b506000610831565b81156110da57506003610831565b506001610831565b6110ea611c3e565b60006110f46110a4565b9050611101600582611c53565b6001600160a01b038216611113573391505b61113161112a85600381111561112557fe5b61217c565b33856121b7565b6111628484846008858154811061114457fe5b9060005260206000209060020201612256909392919063ffffffff16565b8063ffffffff1661117d85600381111561117857fe5b612332565b1515836001600160a01b03167fd54c711b2fd79474dc74606062c8605c0dac9e6089a74320ccf470dc2e33e19a6111be8860038111156111b957fe5b61235e565b604080519115158252602082018990528051918290030190a450505050565b6001600160a01b0383166112225760405162461bcd60e51b8152600401808060200182810382526025815260200180613a606025913960400191505060405180910390fd5b6001600160a01b0382166112675760405162461bcd60e51b815260040180806020018281038252602381526020018061391c6023913960400191505060405180910390fd5b61127283838361186e565b6112b581604051806060016040528060268152602001613983602691396001600160a01b038616600090815260208190526040902054919063ffffffff61134416565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546112ea908263ffffffff6113db16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156113d35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611398578181015183820152602001611380565b50505050905090810190601f1680156113c55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610981576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008280156114415750815b1561144e57506002610831565b8261083157811561082d57506003610831565b600080600061146e6110a4565b8411156114835750600091508190508061179a565b60006008858154811061149257fe5b9060005260206000209060020201905060608160000160008860038111156114b657fe5b60038111156114c157fe5b60038111156114cc57fe5b815260200190815260200160002060010180548060200260200160405190810160405280929190818152602001828054801561153157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611513575b5050600954600b54600a54959650600160c81b90910463ffffffff16949093506000925060ff169050600381111561156557fe5b600954909150600160e81b900460ff16600080805b875181146115c3578e6001600160a01b031688828151811061159857fe5b60200260200101516001600160a01b031614156115bb57600192508091506115c3565b60010161157a565b50858c10806115f757508280156115d95750858c145b80156115f75750838d10806115f75750838d1480156115f757508481105b156116155750600199506000985088975061179a9650505050505050565b8161163257506000995089985088975061179a9650505050505050565b6000868d1480156116405750835b1561173c57845b8e81101561170d576117018a600083600381111561166157fe5b600381111561166c57fe5b600381111561167757fe5b8152602001908152602001600020604051806040016040529081600182018054806020026020016040519081016040528092919081815260200182805480156116e957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116116cb575b50505050508152602001600282015481525050612370565b90910190600101611647565b5060019a5061173286611726838563ffffffff6113db16565b9063ffffffff61237516565b6001019950611790565b60005b8e8114611764576117588a600083600381111561166157fe5b9091019060010161173f565b506117758d8863ffffffff61237516565b6001019a5061178a818363ffffffff6113db16565b60010199505b5050505050505050505b93509350939050565b6117ab610837565b156117f3576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b336001600160a01b037f0000000000000000000000008cb13a8271efa096b407ec8a20aa14c01e74c427161461182857600080fd5b61183283836123b7565b61183c3382612442565b611851600033856001600160801b03166121b7565b611866600133846001600160801b03166121b7565b61186e61253e565b505050565b60008061187e6125c5565b9150915061188d6000806125e1565b604080518381526020810183905281517f72715c0cf03be5e4479cb972219945b83aee28f65875993b1de62bda86892d1e929181900390910190a1610a397f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e8383612622565b6006546007546001600160801b03600160801b909204821692911690565b600080600061192286898987612672565b9250925092508481101561197d576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f7567682073686172657300604482015290519081900360640190fd5b611989600033856121b7565b611995600133846121b7565b6119c86119b06119ab8a8663ffffffff6113db16565b6126e9565b6119c36119ab8a8663ffffffff6113db16565b6123b7565b6119d23382612442565b6040805184815260208101849052808201839052905160019133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b610da68160ff16611a306110a4565b611c53565b600061098182611a5385670de0b6b3a764000063ffffffff61273116565b9063ffffffff61278a16565b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114611aaa576040519150601f19603f3d011682016040523d82523d6000602084013e611aaf565b606091505b505090508061186e576040805162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015290519081900360640190fd5b600080611b036118f3565b915091506000611b11610837565b90506000611b2982611a53868863ffffffff61273116565b90506000611b4183611a53868963ffffffff61273116565b9050878210158015611b535750868110155b611ba4576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f75676820746f6b656e7300604482015290519081900360640190fd5b611bcd611bba6119ab878563ffffffff61237516565b6119c36119ab878563ffffffff61237516565b611bd733876127cc565b611be3600033846128d4565b611bef600133836128d4565b6040805183815260208101839052808201889052905160009133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b611c4661292c565b15610b3057610b3061253e565b611c5b613864565b6040805160a0810190915260098054829060ff166003811115611c7a57fe5b6003811115611c8557fe5b81529054610100810467ffffffffffffffff166020830152600160481b81046001600160801b03166040830152600160c81b810463ffffffff166060830152600160e81b900460ff1615156080909101529050611ce0613894565b60408051808201909152600a8054829060ff166003811115611cfe57fe5b6003811115611d0957fe5b8152602001600182015481525050905082826060015163ffffffff1610158015611d4b5750611d3661292c565b1580611d4b575082826060015163ffffffff16115b15611d57575050610a39565b8160800151611dda576000806000611d72856060015161296e565b9194509250905084836003811115611d8657fe5b90816003811115611d9357fe5b905250611d9f82612ad7565b67ffffffffffffffff166020860152611db7816126e9565b6001600160801b0316604086015250506001608084015250600080825260208201525b83156120935760006008836060015163ffffffff1681548110611df957fe5b600091825260208220845160029092020191906003811115611e1757fe5b6003811115611e2257fe5b815260200190815260200160002090506000806000611eae84611e4e8760000151600381111561112557fe5b60208801518851611e66908b9063ffffffff612b2016565b8a604001516001600160801b031660088c6060015163ffffffff1681548110611e8b57fe5b60009182526020909120600160029092020101546001600160801b03168e612bea565b9250925092508215612072576000611eee6008886060015163ffffffff1681548110611ed657fe5b90600052602060002090600202018760000151612d21565b90506008876060015163ffffffff1681548110611f0757fe5b600091825260208220885160029092020191906003811115611f2557fe5b6003811115611f3057fe5b81526020019081526020016000206000600182016000611f5091906138ab565b60028201600090555050801561203d5760608701805163ffffffff600191820116909152600060808901528751600980548a93919291839160ff191690836003811115611f9957fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff001990951694909417949094169290921716919091179290921691909117905550610a3995505050505050565b855161205390600381111561204e57fe5b612e3c565b8690600381111561206057fe5b9081600381111561206d57fe5b905250505b61207b82612e62565b63ffffffff1660208601529096039550611dda915050565b815160098054849290829060ff191660018360038111156120b057fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff00199095169490941794909416929092171691909117929092169190911790558051600a8054839290829060ff1916600183600381111561216457fe5b02179055506020820151816001015590505050505050565b60008082600381111561218b57fe5b14806121a2575060028260038111156121a057fe5b145b156121af575060006109ff565b5060016109ff565b60008360018111156121c557fe5b141561220b576122066001600160a01b037f000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad7821683308463ffffffff612ea716565b61186e565b80341461186e576040805162461bcd60e51b8152602060048201526014602482015273125b98dbdc9c9958dd0811551208185b5bdd5b9d60621b604482015290519081900360640190fd5b6000848185600381111561226657fe5b600381111561227157fe5b8152602080820192909252604090810160009081206001600160a01b03861682529283905220549091506122cf576001818101805491820181556000908152602090200180546001600160a01b0319166001600160a01b0384161790555b6001600160a01b0382166000908152602082905260409020546122f8908463ffffffff6113db16565b6001600160a01b0383166000908152602083905260409020556002810154612326908463ffffffff6113db16565b60029091015550505050565b60008082600381111561234157fe5b1480610831575060025b82600381111561235757fe5b1492915050565b600061236982612f07565b1592915050565b515190565b600061098183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611344565b600680546001600160801b03908116600160801b8583160217909155600780546001600160801b0319169183169190911790557f17226eb45b590dffadbc03fba4681aa4c198e7e838ab8a6fb7e32a51634b3e808282612415610837565b604080516001600160801b0394851681529290931660208301528183015290519081900360600190a15050565b6001600160a01b03821661249d576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6124a96000838361186e565b6002546124bc908263ffffffff6113db16565b6002556001600160a01b0382166000908152602081905260409020546124e8908263ffffffff6113db16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b612546612f24565b60006125506110a4565b905061255b816126e9565b6001600160801b03167f5ab5824685efa3ca4a723a2f94da7d225628bfae130cc14663932a3bf11140a86008838154811061259257fe5b600091825260209182902060016002909202010154604080516001600160801b039092168252519081900390910190a250565b6005546006546001600160801b03610100909204821692911690565b6005805470ffffffffffffffffffffffffffffffff0019166101006001600160801b0394851602179055600680546001600160801b03191691909216179055565b8115612662576126626001600160a01b037f000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad78216848463ffffffff612f9516565b801561186e5761186e8382611a5f565b600080808084600181111561268357fe5b14156126c5578661269e87611a53838963ffffffff61273116565b6126ba88611a536126ad610837565b8c9063ffffffff61273116565b925092509250610a24565b6126d985611a53898963ffffffff61273116565b876126ba87611a536126ad610837565b6000600160801b821061272d5760405162461bcd60e51b81526004018080602001828103825260278152602001806139a96027913960400191505060405180910390fd5b5090565b60008261274057506000610831565b8282028284828161274d57fe5b04146109815760405162461bcd60e51b81526004018080602001828103825260218152602001806139d06021913960400191505060405180910390fd5b600061098183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612fe7565b6001600160a01b0382166128115760405162461bcd60e51b8152600401808060200182810382526021815260200180613a3f6021913960400191505060405180910390fd5b61281d8260008361186e565b6128608160405180606001604052806022815260200161393f602291396001600160a01b038516600090815260208190526040902054919063ffffffff61134416565b6001600160a01b03831660009081526020819052604090205560025461288c908263ffffffff61237516565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60008360018111156128e257fe5b1415612922576122066001600160a01b037f000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad78216838363ffffffff612f9516565b61186e8282611a5f565b600060086129386110a4565b8154811061294257fe5b6000918252602090912060029091020160010154600160801b90046001600160801b0316431015919050565b60008060008060088563ffffffff168154811061298757fe5b6000918252602080832083805260029283020190819052604080842083015460018552818520840154848652828620850154600387529286209094015492955084938493919290916129dc888585858561304c565b919d50929b509098509096509450866129f85760029a50612a3c565b8660011415612a0a5760029a50612a3c565b8660021415612a1c5760009a50612a3c565b8660031415612a2e5760039a50612a3c565b8660041415612a3c5760019a505b8b63ffffffff167f24f971a36bb1ccca6d5a24e46c30c46b44dc72fdf6b667edd669dee3585552a58c6003811115612a7057fe5b6040805160ff9092168252602082018d90528181018e9052606082018890526080820187905260a0820186905260c08201859052519081900360e00190a26001880154612ac8906001600160801b031687878c6130e2565b50505050505050509193909250565b600068010000000000000000821061272d5760405162461bcd60e51b81526004018080602001828103825260268152602001806139f16026913960400191505060405180910390fd5b6000612b3182600381111561112557fe5b6001811115612b3c57fe5b8351612b4d90600381111561112557fe5b6001811115612b5857fe5b14612b6557506000610831565b8251612b7b906003811115612b7657fe5b612f07565b15612bb857612b8f826003811115612b7657fe5b15612ba95750602082015167ffffffffffffffff16610831565b50670de0b6b3a7640000610831565b612bc78260038111156111b957fe5b15612be15750602082015167ffffffffffffffff16610831565b50600092915050565b6000806000806000612c708c604051806040016040529081600182018054806020026020016040519081016040528092919081815260200182805480156116e9576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116116cb5750505050508152602001600282015481525050612370565b90508991505b858a83031015612cee57808210612c9a575060019350600092508890039050612d14565b60008c6001018381548110612cab57fe5b60009182526020808320909101546001600160a01b0316808352908f9052604090912054909150612ce2908d9083908d8d8d613191565b50600190910190612c76565b808210612d08575060019350600092508890039050612d14565b50600093509150508681035b9750975097945050505050565b60006003826003811115612d3157fe5b1415612d3f57506001610831565b6000612d5083600381111561204e57fe5b6003811115612d5b57fe5b90505b8060041461097d57612d6e6138c9565b846000836003811115612d7d57fe5b6003811115612d8857fe5b6003811115612d9357fe5b815260200190815260200160002060405180604001604052908160018201805480602002602001604051908101604052809291908181526020018280548015612e0557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612de7575b505050505081526020016002820154815250509050612e2381612370565b15612e3357600092505050610831565b50600101612d5e565b60006004826003811115612e4c57fe5b60010181612e5657fe5b06600381111561083157fe5b6000640100000000821061272d5760405162461bcd60e51b8152600401808060200182810382526026815260200180613a856026913960400191505060405180910390fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612f01908590613294565b50505050565b600080826003811115612f1657fe5b14806108315750600161234b565b6008612f48612f31613345565b612f3d43600201612e62565b63ffffffff16613410565b8154600180820184556000938452602093849020835160029093020101805492909301516001600160801b03199092166001600160801b03918216178116600160801b9190921602179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261186e908490613294565b600081836130365760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611398578181015183820152602001611380565b50600083858161304257fe5b0495945050505050565b600185015460009081908190819081906001600160801b0316670de0b6b3a7640000016130cb61307c8b83611a35565b61308c8a8463ffffffff611a3516565b61309c8c8563ffffffff611a3516565b6130ac8b8663ffffffff611a3516565b6006546007546001600160801b03600160801b9092048216911661343a565b939f929e50909c509a509098509650505050505050565b6000806000806000806130f98a8a8a8a6000613551565b6006546005546001600160801b03600160801b90920482169093019850610100909204909116019350600091508190506131378a898b8a6001613551565b6007546006546001600160801b0391821690930197509190911601925061316d91506131649050856126e9565b6119c3856126e9565b613187613179836126e9565b613182836126e9565b6125e1565b5050505050505050565b60006131a78760018111156131a257fe5b6135b7565b905060006131bb868663ffffffff6135dc16565b905060006131f66131da670de0b6b3a76400008663ffffffff6113db16565b6131ea898563ffffffff61237516565b9063ffffffff611a3516565b905060006132058a83886135fa565b90506132128a8a85613636565b61321d848a83613636565b886001600160a01b031661322f6110a4565b63ffffffff1660008c600181111561324357fe5b604080518d815260208101899052808201879052905192909114917fb8221d4e9feabcc28c5e0878f3196eecf38320725898780b22a503239b6bc9969181900360600190a450505050505050505050565b60606132e9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136a79092919063ffffffff16565b80519091501561186e5780806020019051602081101561330857600080fd5b505161186e5760405162461bcd60e51b815260040180806020018281038252602a815260200180613acf602a913960400191505060405180910390fd5b60007f000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf6001600160a01b0316632e66ed1a7f000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac826040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b1580156133df57600080fd5b505af11580156133f3573d6000803e3d6000fd5b505050506040513d602081101561340957600080fd5b5051905090565b613418613894565b50604080518082019091526001600160801b0392831681529116602082015290565b600080600080600061344a6138e3565b6040805163f5eeb35760e01b8152600481018e9052602481018d9052604481018c9052606481018b9052608481018a905260a4810189905290516001600160a01b037f000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d169163f5eeb3579160c48083019260a0929190829003018186803b1580156134d457600080fd5b505afa1580156134e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525060a081101561350d57600080fd5b509050806000602002015181600160200201518260026020020151836003602002015184600460200201519550955095509550955050965096509650965096915050565b60008080613565878963ffffffff6135dc16565b90506000613581826702c68af0bb14000063ffffffff6135dc16565b9050600061359e6135978760018111156131a257fe5b89896135fa565b9282900389019290920393509150509550959350505050565b6000808260018111156135c657fe5b14156135d4575060016109ff565b5060006109ff565b6000610981670de0b6b3a7640000611a53858563ffffffff61273116565b60008084600181111561360957fe5b14156136265761361f838363ffffffff6135dc16565b9050610981565b61361f838363ffffffff611a3516565b600083600181111561364457fe5b1415613684576122066001600160a01b037f000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad78216838363ffffffff612f9516565b6001600160a01b0382166000908152600c60205260409020805482019055505050565b60606136b684846000856136be565b949350505050565b60606136c98561382b565b61371a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106137595780518252601f19909201916020918201910161373a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146137bb576040519150601f19603f3d011682016040523d82523d6000602084013e6137c0565b606091505b509150915081156137d45791506136b69050565b8051156137e45780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315611398578181015183820152602001611380565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906136b6575050151592915050565b6040805160a081019091528060008152600060208201819052604082018190526060820181905260809091015290565b604080518082019091526000808252602082015290565b5080546000825590600052602060002090810190610da69190613901565b604051806040016040528060608152602001600081525090565b6040518060a001604052806005906020820280368337509192915050565b61081691905b8082111561272d576000815560010161390756fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636553616665436173743a2076616c756520646f65736e27742066697420696e203132382062697473536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e203634206269747345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e203332206269747345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220fc8042f134361df36258d94edf8f6d257bae11b393a73d0aa7846d4648c458b864736f6c63430006060033

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

000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad782000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac8200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000e53484152452d49444f4c2d455448000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _token (address): 0xDb4f5Bc7D37816537e8aF48c885Ef28F366aD782
Arg [1] : _priceCalc (address): 0xE9aa04b8D955fD291d44C9fDb8eB1227850b3e2d
Arg [2] : _marketFeeTaker (address): 0xaB37e1358b639Fd877f015027Bb62d3ddAa7557E
Arg [3] : _spreadCalc (address): 0xC05CB1999aB97A9ae5337fBdC4cb0e1458bc5CbF
Arg [4] : _oracle (address): 0x120a078FdC516A1A98bbecb9e961F8741AC7ac82
Arg [5] : _name (string): SHARE-IDOL-ETH

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000db4f5bc7d37816537e8af48c885ef28f366ad782
Arg [1] : 000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d
Arg [2] : 000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e
Arg [3] : 000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf
Arg [4] : 000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac82
Arg [5] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [7] : 53484152452d49444f4c2d455448000000000000000000000000000000000000


Deployed Bytecode Sourcemap

86336:839:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;17757:83:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17757:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;17757:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19863:169;;5:9:-1;2:2;;;27:1;24;17:12;2:2;19863:169:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;19863:169:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;18832:100;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18832:100:0;;;:::i;:::-;;;;;;;;;;;;;;;;81298:316;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81298:316:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;81298:316:0;;;-1:-1:-1;;;;;81298:316:0;;;;;;;;;;;;;;;;;:::i;:::-;;20506:321;;5:9:-1;2:2;;;27:1;24;17:12;2:2;20506:321:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;20506:321:0;;;;;;;;;;;;;;;;;:::i;18684:83::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18684:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;21236:218;;5:9:-1;2:2;;;27:1;24;17:12;2:2;21236:218:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;21236:218:0;;;;;;;;:::i;83975:122::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;83975:122:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;83975:122:0;-1:-1:-1;;;;;83975:122:0;;:::i;42917:396::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;42917:396:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;42917:396:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79663:191;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;79663:191:0;;;;;;;:::i;18995:119::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18995:119:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;18995:119:0;-1:-1:-1;;;;;18995:119:0;;:::i;46378:253::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;46378:253:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;46378:253:0;;-1:-1:-1;;;;;46378:253:0;;;;;;;;:::i;17959:87::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17959:87:0;;;:::i;83450:81::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;83450:81:0;;;:::i;81982:407::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;81982:407:0;;;;;;;:::i;44769:1397::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;44769:1397:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;44769:1397:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21957:269;;5:9:-1;2:2;;;27:1;24;17:12;2:2;21957:269:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;21957:269:0;;;;;;;;:::i;19327:175::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;19327:175:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;19327:175:0;;;;;;;;:::i;39511:29::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;39511:29:0;;;:::i;:::-;;;;-1:-1:-1;;;;;39511:29:0;;;;;;;;;;;;;;83265:111;;5:9:-1;2:2;;;27:1;24;17:12;2:2;83265:111:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;83265:111:0;;;;:::i;39445:29::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;39445:29:0;;;:::i;43837:697::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;43837:697:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19565:151;;5:9:-1;2:2;;;27:1;24;17:12;2:2;19565:151:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;19565:151:0;;;;;;;;;;:::i;83681:180::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;83681:180:0;;;:::i;82886:237::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;82886:237:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;82886:237:0;;;;;;;;;;;;;;;;;:::i;80378:291::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;80378:291:0;;;-1:-1:-1;;;;;80378:291:0;;;;;;;;;;;;:::i;78483:37::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;78483:37:0;;;:::i;:::-;;;;-1:-1:-1;;;;;78483:37:0;;;;;;;;;;;;;;17757:83;17827:5;17820:12;;;;;;;;-1:-1:-1;;17820:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17794:13;;17820:12;;17827:5;;17820:12;;17827:5;17820:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17757:83;;:::o;19863:169::-;19946:4;19963:39;19972:12;:10;:12::i;:::-;19986:7;19995:6;19963:8;:39::i;:::-;-1:-1:-1;20020:4:0;19863:169;;;;;:::o;18832:100::-;18912:12;;18832:100;:::o;81298:316::-;81459:11;41641;41633:54;;;;;-1:-1:-1;;;41633:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;81481:7:::1;41779:19;:17;:19::i;:::-;41769:7;:29;41761:50;;;::::0;;-1:-1:-1;;;41761:50:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;41761:50:0;;;;;;;;;;;;;::::1;;81501:19:::2;81523:28;81537:4;81543:7;81523:13;:28::i;:::-;81501:50;;81562:44;81572:9;81583:11;81596:9;81562;:44::i;:::-;41822:1;41698::::1;81298:316:::0;;;;;:::o;20506:321::-;20612:4;20629:36;20639:6;20647:9;20658:6;20629:9;:36::i;:::-;20676:121;20685:6;20693:12;:10;:12::i;:::-;20707:89;20745:6;20707:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;20707:19:0;;;;;;:11;:19;;;;;;20727:12;:10;:12::i;:::-;-1:-1:-1;;;;;20707:33:0;;;;;;;;;;;;-1:-1:-1;20707:33:0;;;:89;;:37;:89;:::i;:::-;20676:8;:121::i;:::-;-1:-1:-1;20815:4:0;20506:321;;;;;;:::o;18684:83::-;18750:9;;;;18684:83;:::o;21236:218::-;21324:4;21341:83;21350:12;:10;:12::i;:::-;21364:7;21373:50;21412:10;21373:11;:25;21385:12;:10;:12::i;:::-;-1:-1:-1;;;;;21373:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;21373:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;83975:122::-;-1:-1:-1;;;;;84067:22:0;;84040:7;84067:22;;;:11;:22;;;;;;83975:122;;;;:::o;42917:396::-;43111:15;43141:16;43172:18;43238:67;43253:9;43264:29;43278:5;43285:7;43264:13;:29::i;:::-;43295:9;43238:14;:67::i;:::-;43218:87;;;;;;42917:396;;;;;;;;;:::o;79663:191::-;79785:61;79799:11;79821:9;79833:12;79785:5;:61::i;:::-;79663:191;;:::o;18995:119::-;-1:-1:-1;;;;;19088:18:0;19061:7;19088:18;;;;;;;;;;;;18995:119::o;46378:253::-;46488:7;46533:10;46544:19;:17;:19::i;:::-;46533:31;;;;;;;;;;;;;;;;;;:42;;:53;46576:9;46533:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46533:53:0;;;-1:-1:-1;;;;;46533:90:0;;;;;;;;;;;-1:-1:-1;46378:253:0;;;;:::o;17959:87::-;18031:7;18024:14;;;;;;;;-1:-1:-1;;18024:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17998:13;;18024:14;;18031:7;;18024:14;;18031:7;18024:14;;;;;;;;;;;;;;;;;;;;;;;;83450:81;83501:22;:20;:22::i;:::-;83450:81::o;81982:407::-;82098:9;41641:11;41633:54;;;;;-1:-1:-1;;;41633:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;82127:7:::1;41779:19;:17;:19::i;:::-;41769:7;:29;41761:50;;;::::0;;-1:-1:-1;;;41761:50:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;41761:50:0;;;;;;;;;;;;;::::1;;82153:17:::2;82172::::0;82193:14:::2;:12;:14::i;:::-;82152:55;;;;82233:148;82261:9;82285;82309;82333:10;82358:12;82233:13;:148::i;:::-;41822:1;;41698::::1;81982:407:::0;;;:::o;44769:1397::-;44873:29;44917:26;44958:28;45001:26;45042:28;45342:26;45371:18;:28;;;;;;;;;;;;45342:57;;;;45431:10;45442:9;45431:21;;;;;;;;;;;;;;;;:66;;;:21;;;;;:66;;;;;;:94;;45559:10;:21;;45431:94;;-1:-1:-1;45559:10:0;45570:9;;45559:21;;;;;;;;;;;;;;;:68;;;:21;;;;:68;;;;;;:96;;45687:10;:21;;45559:96;;-1:-1:-1;45687:10:0;45698:9;;45687:21;;;;;;;;;;;;;;45720:32;45687:66;;:21;;;;;:66;;;;;;:94;;45815:10;:21;;45687:94;;-1:-1:-1;45815:10:0;45826:9;;45815:21;;;;;;;;;;;;;;45848:34;45815:68;;:21;;;;;:68;;;;;;:96;;;-1:-1:-1;45926:30:0;;;45922:237;;;45997:1;45973:25;;45922:237;;;46047:18;46034:9;:31;:61;;;;-1:-1:-1;46069:18:0;:26;-1:-1:-1;;;46069:26:0;;;;46034:61;46016:143;;;46146:1;46122:25;;46016:143;44769:1397;;;;;;;;:::o;21957:269::-;22050:4;22067:129;22076:12;:10;:12::i;:::-;22090:7;22099:96;22138:15;22099:96;;;;;;;;;;;;;;;;;:11;:25;22111:12;:10;:12::i;:::-;-1:-1:-1;;;;;22099:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;22099:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;19327:175::-;19413:4;19430:42;19440:12;:10;:12::i;:::-;19454:9;19465:6;19430:9;:42::i;39511:29::-;;;-1:-1:-1;;;;;39511:29:0;;:::o;83265:111::-;83334:34;83356:11;83334:21;:34::i;:::-;83265:111;:::o;39445:29::-;;;;;;-1:-1:-1;;;;;39445:29:0;;:::o;43837:697::-;43945:17;43977;44009;44041:18;44074:24;44113:25;44153;44218:19;:17;:19::i;:::-;44206:31;;44273:14;:12;:14::i;:::-;44248:39;;;;;;;;44317:10;44328:9;44317:21;;;;;;;;;;;;;;;;:32;:21;;;;;:32;;-1:-1:-1;;;;;44317:32:0;;-1:-1:-1;44373:13:0;:11;:13::i;:::-;44360:26;;44417:39;44434:9;44445:10;44417:16;:39::i;:::-;44397:59;;44487:39;44504:9;44515:10;44487:16;:39::i;:::-;44467:59;;43837:697;;;;;;;:::o;19565:151::-;-1:-1:-1;;;;;19681:18:0;;;19654:7;19681:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;19565:151::o;83681:180::-;83757:10;83724:18;83745:23;;;:11;:23;;;;;;;83779:27;;;83745:23;83817:36;;83745:23;83817:12;:36::i;82886:237::-;83046:7;41779:19;:17;:19::i;:::-;41769:7;:29;41761:50;;;;;-1:-1:-1;;;41761:50:0;;;;;;;;;;;;-1:-1:-1;;;41761:50:0;;;;;;;;;;;;;;;83066:49:::1;83083:9;83094:6;83102:12;83066:16;:49::i;:::-;82886:237:::0;;;;;:::o;80378:291::-;80517:9;41641:11;41633:54;;;;;-1:-1:-1;;;41633:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;80537:7:::1;41779:19;:17;:19::i;:::-;41769:7;:29;41761:50;;;::::0;;-1:-1:-1;;;41761:50:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;41761:50:0;;;;;;;;;;;;;::::1;;80557:19:::2;80579:29;80593:5;80600:7;80579:13;:29::i;:::-;80557:51;;80619:42;80629:9;80640;80651;80619;:42::i;78483:37::-:0;;;:::o;657:106::-;745:10;657:106;:::o;25104:346::-;-1:-1:-1;;;;;25206:19:0;;25198:68;;;;-1:-1:-1;;;25198:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;25285:21:0;;25277:68;;;;-1:-1:-1;;;25277:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;25358:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;25410:32;;;;;;;;;;;;;;;;;25104:346;;;:::o;66326:108::-;66405:10;:17;-1:-1:-1;;66405:21:0;66326:108;:::o;73132:487::-;73232:9;73263:5;73259:353;;;73289:8;73285:142;;;-1:-1:-1;73325:20:0;73318:27;;73285:142;-1:-1:-1;73393:18:0;73386:25;;73259:353;73463:8;73459:142;;;-1:-1:-1;73499:20:0;73492:27;;73459:142;-1:-1:-1;73567:18:0;73560:25;;50901:694;51040:12;:10;:12::i;:::-;51063:25;51091:19;:17;:19::i;:::-;51063:47;;51121:36;51136:1;51139:17;51121:14;:36::i;:::-;-1:-1:-1;;;;;51172:23:0;;51168:78;;51224:10;51212:22;;51168:78;51256:57;51271:19;:9;:17;;;;;;;;;:19::i;:::-;51292:10;51304:8;51256:14;:57::i;:::-;51324:70;51363:9;51374:8;51384:9;51324:10;51335:17;51324:29;;;;;;;;;;;;;;;;;;:38;;:70;;;;;;:::i;:::-;51500:17;51410:177;;51461:17;:9;:15;;;;;;;;;:17::i;:::-;51410:177;;51437:9;-1:-1:-1;;;;;51410:177:0;;51533:20;:9;:18;;;;;;;;;:20::i;:::-;51410:177;;;;;;;;;;;;;;;;;;;;;;;50901:694;;;;:::o;22716:539::-;-1:-1:-1;;;;;22822:20:0;;22814:70;;;;-1:-1:-1;;;22814:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22903:23:0;;22895:71;;;;-1:-1:-1;;;22895:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22979:47;23000:6;23008:9;23019:6;22979:20;:47::i;:::-;23059:71;23081:6;23059:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23059:17:0;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;-1:-1:-1;;;;;23039:17:0;;;:9;:17;;;;;;;;;;;:91;;;;23164:20;;;;;;;:32;;23189:6;23164:32;:24;:32;:::i;:::-;-1:-1:-1;;;;;23141:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;23212:35;;;;;;;23141:20;;23212:35;;;;;;;;;;;;;22716:539;;;:::o;5704:192::-;5790:7;5826:12;5818:6;;;;5810:29;;;;-1:-1:-1;;;5810:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;5810:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5862:5:0;;;5704:192::o;4801:181::-;4859:7;4891:5;;;4915:6;;;;4907:46;;;;;-1:-1:-1;;;4907:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;66500:382;66599:22;66643:5;:16;;;;;66652:7;66643:16;66639:236;;;-1:-1:-1;66693:1:0;66639:236;;;66717:5;66712:163;;66743:7;66739:125;;;-1:-1:-1;66788:1:0;66739:125;;61923:2440;62107:15;62137:16;62168:18;62230:19;:17;:19::i;:::-;62218:9;:31;62214:84;;;-1:-1:-1;62274:5:0;;-1:-1:-1;62274:5:0;;-1:-1:-1;62274:5:0;62266:20;;62214:84;62308:29;62340:10;62351:9;62340:21;;;;;;;;;;;;;;;;;;62308:53;;62372:27;62402:12;:23;;:74;62450:14;62426:49;;;;;;;;62402:74;;;;;;;;;;;;;;;;;;;;;;;;;;;:99;;62372:129;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;62372:129:0;;;;;;;;;;;;;;;;-1:-1:-1;;62541:18:0;:28;62600:29;;:19;62667:38;62372:129;;-1:-1:-1;;;;62541:28:0;;;;;;62600:29;;-1:-1:-1;62512:26:0;;-1:-1:-1;62667:38:0;;;-1:-1:-1;62659:47:0;;;;;;;;62732:18;:26;62640:66;;-1:-1:-1;;;;62732:26:0;;;;62717:12;;;62816:208;62841:10;:17;62836:1;:22;62816:208;;62901:9;-1:-1:-1;;;;;62884:26:0;:10;62895:1;62884:13;;;;;;;;;;;;;;-1:-1:-1;;;;;62884:26:0;;62880:133;;;62941:4;62931:14;;62972:1;62964:9;;62992:5;;62880:133;62860:3;;62816:208;;;;63316:18;63304:9;:30;63303:225;;;;63354:7;:44;;;;;63379:18;63366:9;:31;63354:44;63353:174;;;;;63439:8;63422:14;:25;63421:105;;;;63493:8;63475:14;:26;63474:51;;;;;63515:9;63507:5;:17;63474:51;63285:301;;;-1:-1:-1;63563:4:0;;-1:-1:-1;63569:1:0;;-1:-1:-1;63569:1:0;;-1:-1:-1;63555:19:0;;-1:-1:-1;;;;;;;63555:19:0;63285:301;63603:7;63598:61;;-1:-1:-1;63635:5:0;;-1:-1:-1;63635:5:0;;-1:-1:-1;63635:5:0;;-1:-1:-1;63627:20:0;;-1:-1:-1;;;;;;;63627:20:0;63598:61;63734:14;63776:18;63763:9;:31;:42;;;;;63798:7;63763:42;63759:597;;;63839:8;63822:147;63853:14;63849:1;:18;63822:147;;;63903:50;:12;:23;63937:1;63927:12;;;;;;;;63903:37;;;;;;;;;;;;;;;;;;;;;;;;;;;:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63903:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:50::i;:::-;63893:60;;;;63869:3;;63822:147;;;-1:-1:-1;63994:1:0;;-1:-1:-1;64023:32:0;64045:9;64023:17;:6;64034:5;64023:17;:10;:17;:::i;:::-;:21;:32;:21;:32;:::i;:::-;64058:1;64023:36;64010:49;;63759:597;;;64097:9;64092:141;64117:14;64112:1;:19;64092:141;;64167:50;:12;:23;64201:1;64191:12;;;;;;;64167:50;64157:60;;;;64133:3;;64092:141;;;-1:-1:-1;64258:33:0;:9;64272:18;64258:33;:13;:33;:::i;:::-;64294:1;64258:37;;-1:-1:-1;64323:17:0;:6;64334:5;64323:17;:10;:17;:::i;:::-;64343:1;64323:21;64310:34;;63759:597;61923:2440;;;;;;;;;;;;;;;;;:::o;47697:461::-;47838:13;:11;:13::i;:::-;:18;47830:50;;;;;-1:-1:-1;;;47830:50:0;;;;;;;;;;;;-1:-1:-1;;;47830:50:0;;;;;;;;;;;;;;;47899:10;-1:-1:-1;;;;;47913:7:0;47899:21;;47891:30;;12:1:-1;9;2:12;47891:30:0;47932:32;47947:7;47956;47932:14;:32::i;:::-;47975:31;47981:10;47993:12;47975:5;:31::i;:::-;48017:49;48032:12;48046:10;48058:7;-1:-1:-1;;;;;48017:49:0;:14;:49::i;:::-;48077;48092:12;48106:10;48118:7;-1:-1:-1;;;;;48077:49:0;:14;:49::i;:::-;48137:13;:11;:13::i;:::-;47697:461;;;:::o;51981:353::-;52056:23;52094;52131:20;:18;:20::i;:::-;52041:110;;;;52162:26;52183:1;52186;52162:20;:26::i;:::-;52206:46;;;;;;;;;;;;;;;;;;;;;;;;;52263:63;52277:14;52293:15;52310;52263:13;:63::i;64371:187::-;64511:8;;64542;;-1:-1:-1;;;;;;;;64511:8:0;;;;;;64542;;;64371:187::o;48418:806::-;48611:15;48628;48645:13;48662:121;48694:6;48715:9;48739;48763;48662:17;:121::i;:::-;48610:173;;;;;;48811:8;48802:5;:17;;48794:61;;;;;-1:-1:-1;;;48794:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;48866:49;48881:12;48895:10;48907:7;48866:14;:49::i;:::-;48926;48941:12;48955:10;48967:7;48926:14;:49::i;:::-;48986:123;49015:34;:22;:9;49029:7;49015:22;:13;:22;:::i;:::-;:32;:34::i;:::-;49064;:22;:9;49078:7;49064:22;:13;:22;:::i;:34::-;48986:14;:123::i;:::-;49120:24;49126:10;49138:5;49120;:24::i;:::-;49160:56;;;;;;;;;;;;;;;;;;;;49186:4;;49174:10;;49160:56;;;;;;;;;48418:806;;;;;;;;:::o;51753:134::-;51831:48;51846:11;51831:48;;51859:19;:17;:19::i;:::-;51831:14;:48::i;35499:132::-;35561:7;35588:35;35621:1;35588:28;:1;35462:19;35588:28;:5;:28;:::i;:::-;:32;:35;:32;:35;:::i;85985:230::-;86134:26;;86116:12;;-1:-1:-1;;;;;86134:7:0;;;86149:6;;86116:12;86134:26;86116:12;86134:26;86149:6;86134:7;:26;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;86115:45:0;;;86179:7;86171:36;;;;;-1:-1:-1;;;86171:36:0;;;;;;;;;;;;-1:-1:-1;;;86171:36:0;;;;;;;;;;;;;;49644:896;49788:17;49807;49828:14;:12;:14::i;:::-;49787:55;;;;49868:20;49891:13;:11;:13::i;:::-;49868:36;-1:-1:-1;49915:15:0;49933:38;49868:36;49933:20;:9;49947:5;49933:20;:13;:20;:::i;:38::-;49915:56;-1:-1:-1;49982:15:0;50000:38;50025:12;50000:20;:9;50014:5;50000:20;:13;:20;:::i;:38::-;49982:56;;50082:10;50071:7;:21;;:46;;;;;50107:10;50096:7;:21;;50071:46;50049:127;;;;;-1:-1:-1;;;50049:127:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;50187:123;50216:34;:22;:9;50230:7;50216:22;:13;:22;:::i;:34::-;50265;:22;:9;50279:7;50265:22;:13;:22;:::i;50187:123::-;50321:24;50327:10;50339:5;50321;:24::i;:::-;50356:46;50368:12;50382:10;50394:7;50356:11;:46::i;:::-;50413;50425:12;50439:10;50451:7;50413:11;:46::i;:::-;50475:57;;;;;;;;;;;;;;;;;;;;50501:5;;50489:10;;50475:57;;;;;;;;;49644:896;;;;;;;;:::o;52694:164::-;52783:26;:24;:26::i;:::-;52779:72;;;52826:13;:11;:13::i;53107:3738::-;53212:45;;:::i;:::-;:66;;;;;;;;;53260:18;53212:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53212:66:0;;-1:-1:-1;;;;;53212:66:0;;;;;-1:-1:-1;;;53212:66:0;;;;;;;;-1:-1:-1;;;53212:66:0;;;;;;;;;;;;-1:-1:-1;53289:47:0;;:::i;:::-;:69;;;;;;;;;53339:19;53289:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53629:17;53596:19;:29;;;:50;;;;:166;;;;;53665:26;:24;:26::i;:::-;53664:27;:97;;;;53744:17;53712:19;:29;;;:49;;;53664:97;53578:229;;;53789:7;;;;53578:229;53822:19;:27;;;53817:950;;54028:34;54085:27;54135:12;54169:105;54226:19;:29;;;54169:34;:105::i;:::-;54005:269;;-1:-1:-1;54005:269:0;-1:-1:-1;54005:269:0;-1:-1:-1;54293:19:0;54005:269;54293:93;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54447:52:0;:19;:50;:52::i;:::-;54405:94;;:39;;;:94;54545:16;:4;:14;:16::i;:::-;-1:-1:-1;;;;;54518:43:0;:24;;;:43;-1:-1:-1;;54610:4:0;54580:27;;;:34;-1:-1:-1;;54633:54:0;;;54706:30;;;:34;53817:950;54879:16;;54872:1862;;54912:31;54946:10;54957:19;:47;;;54946:59;;;;;;;;;;;;;;;;;55035:39;;54946:59;;;;;;;:129;;;;;;;;;;;;;;;;;;;;;;;;;;;54912:163;;55109:19;55147:17;55183:24;55225:458;55264:13;55296:49;:20;:39;;;:47;;;;;;;:49;55364:30;;;;55466:39;;55413:111;;:19;;:111;:30;:111;:::i;:::-;55543:19;:24;;;-1:-1:-1;;;;;55225:458:0;55586:10;55597:19;:29;;;55586:41;;;;;;;;;;;;;;;;;;:52;:41;;;;;:52;;-1:-1:-1;;;;;55586:52:0;55657:11;55225:20;:458::i;:::-;55090:593;;;;;;55702:14;55698:911;;;55737:18;55758:159;55795:10;55806:19;:29;;;55795:41;;;;;;;;;;;;;;;;;;;;55859:20;:39;;;55758:14;:159::i;:::-;55737:180;;55943:10;55954:19;:29;;;55943:41;;;;;;;;;;;;;;;;;56018:39;;55943:41;;;;;;;:115;;;;;;;;;;;;;;;;;;;;;;;;;;;;55936:122;;;;;;;;:::i;:::-;;;;;;;;;56157:13;56153:290;;;56195:29;;;:34;;;56228:1;56195:34;;;;;;;-1:-1:-1;56252:27:0;;;:35;56310:40;;:18;:40;;56195:19;;56310:18;;:40;:18;;-1:-1:-1;;56310:40:0;;;;;;;;;;;;;;;-1:-1:-1;56310:40:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;56310:40:0;-1:-1:-1;;;;56310:40:0;;;;-1:-1:-1;;;56310:40:0;-1:-1:-1;;;;;;;;;56310:40:0;;;-1:-1:-1;;;56310:40:0;-1:-1:-1;;;;;;;;56310:40:0;;;;;;-1:-1:-1;;56310:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56375:7:0;;-1:-1:-1;;;;;;56375:7:0;56153:290;56503:61;;:90;;:88;;;;;;;;;:90::i;:::-;56461:20;;:132;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;55698:911:0;56656:20;:9;:18;:20::i;:::-;56623:53;;:30;;;:53;56691:31;;;;-1:-1:-1;54872:1862:0;;-1:-1:-1;;54872:1862:0;;56744:40;;:18;:40;;56765:19;;56744:40;:18;;-1:-1:-1;;56744:40:0;;;;;;;;;;;;;;;-1:-1:-1;56744:40:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;56744:40:0;-1:-1:-1;;;;56744:40:0;;;;-1:-1:-1;;;56744:40:0;-1:-1:-1;;;;;;;;;56744:40:0;;;-1:-1:-1;;;56744:40:0;-1:-1:-1;;;;;;;;56744:40:0;;;;;;-1:-1:-1;;56744:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56795:42;;:19;:42;;56817:20;;56795:42;:19;;-1:-1:-1;;56795:42:0;56744:40;56795:42;;;;;;;;;;;;;;;;;;;;;;;;;53107:3738;;;;:::o;34485:243::-;34541:5;;34563:4;:26;;;;;;;;;:58;;;-1:-1:-1;34601:20:0;34593:4;:28;;;;;;;;;34563:58;34559:162;;;-1:-1:-1;34645:12:0;34638:19;;34559:162;-1:-1:-1;34697:12:0;34690:19;;84287:335;84438:12;84425:9;:25;;;;;;;;;84421:194;;;84467:51;-1:-1:-1;;;;;84467:5:0;:22;84490:4;84504;84511:6;84467:51;:22;:51;:::i;:::-;84421:194;;;84572:6;84559:9;:19;84551:52;;;;;-1:-1:-1;;;84551:52:0;;;;;;;;;;;;-1:-1:-1;;;84551:52:0;;;;;;;;;;;;;;38043:526;38205:27;38235:4;38205:27;38251:9;38235:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38235:26:0;;;-1:-1:-1;;;;;38276:30:0;;;;;;;;;;38235:26;;-1:-1:-1;38272:104:0;;38328:20;;;;27:10:-1;;23:18;;;45:23;;-1:-1;38328:36:0;;;;;;;;;-1:-1:-1;;;;;;38328:36:0;-1:-1:-1;;;;;38328:36:0;;;;;38272:104;-1:-1:-1;;;;;38419:30:0;;:19;:30;;;;;;;;;;;:68;;38468:8;38419:68;:34;:68;:::i;:::-;-1:-1:-1;;;;;38386:30:0;;:19;:30;;;;;;;;;;:101;38524:23;;;;:37;;38552:8;38524:37;:27;:37;:::i;:::-;38498:23;;;;:63;-1:-1:-1;;;;38043:526:0:o;35129:146::-;35183:4;;35208;:26;;;;;;;;;:58;;;-1:-1:-1;35246:20:0;35238:28;:4;:28;;;;;;;;;35200:67;35129:146;-1:-1:-1;;35129:146:0:o;34887:102::-;34944:4;34969:12;34976:4;34969:6;:12::i;:::-;34968:13;;34887:102;-1:-1:-1;;34887:102:0:o;38608:123::-;38701:15;:22;;38608:123::o;5265:136::-;5323:7;5350:43;5354:1;5357;5350:43;;;;;;;;;;;;;;;;;:3;:43::i;64803:219::-;64889:8;:22;;-1:-1:-1;;;;;64889:22:0;;;-1:-1:-1;;;64889:22:0;;;;;;;;64922:8;:22;;-1:-1:-1;;;;;;64922:22:0;;;;;;;;;;64960:54;64889:22;64922;65000:13;:11;:13::i;:::-;64960:54;;;-1:-1:-1;;;;;64960:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;64803:219;;:::o;23536:378::-;-1:-1:-1;;;;;23620:21:0;;23612:65;;;;;-1:-1:-1;;;23612:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;23690:49;23719:1;23723:7;23732:6;23690:20;:49::i;:::-;23767:12;;:24;;23784:6;23767:24;:16;:24;:::i;:::-;23752:12;:39;-1:-1:-1;;;;;23823:18:0;;:9;:18;;;;;;;;;;;:30;;23846:6;23823:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;23802:18:0;;:9;:18;;;;;;;;;;;:51;;;;23869:37;;;;;;;23802:18;;:9;;23869:37;;;;;;;;;;23536:378;;:::o;85725:252::-;85777:19;:17;:19::i;:::-;85807:18;85828:19;:17;:19::i;:::-;85807:40;;85888:22;:10;:20;:22::i;:::-;-1:-1:-1;;;;;85863:106:0;;85925:10;85936;85925:22;;;;;;;;;;;;;;;;;:33;:22;;;;;:33;;85863:106;;;-1:-1:-1;;;;;85925:33:0;;;85863:106;;;;;;;;;;;;85725:252;:::o;64566:229::-;64730:14;;64773;;-1:-1:-1;;;;;64730:14:0;;;;;;;64773;;;64566:229::o;66890:215::-;67018:14;:34;;-1:-1:-1;;67018:34:0;;-1:-1:-1;;;;;67018:34:0;;;;;;;67063:14;:34;;-1:-1:-1;;;;;;67063:34:0;;;;;;;;66890:215::o;84919:334::-;85068:12;;85064:89;;85097:44;-1:-1:-1;;;;;85097:5:0;:18;85116:15;85133:7;85097:44;:18;:44;:::i;:::-;85167:12;;85163:83;;85196:38;85209:15;85226:7;85196:12;:38::i;67113:703::-;67317:7;;;;67400:9;:25;;;;;;;;;67396:413;;;67468:6;67493:36;67519:9;67493:21;67468:6;67504:9;67493:21;:10;:21;:::i;:36::-;67548:40;67578:9;67548:25;67559:13;:11;:13::i;:::-;67548:6;;:25;:10;:25;:::i;:40::-;67442:161;;;;;;;;67396:413;67662:36;67688:9;67662:21;:6;67673:9;67662:21;:10;:21;:::i;:36::-;67717:6;67742:40;67772:9;67742:25;67753:13;:11;:13::i;27739:184::-;27796:7;-1:-1:-1;;;27824:5:0;:14;27816:67;;;;-1:-1:-1;;;27816:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27909:5:0;27739:184::o;6155:471::-;6213:7;6458:6;6454:47;;-1:-1:-1;6488:1:0;6481:8;;6454:47;6525:5;;;6529:1;6525;:5;:1;6549:5;;;;;:10;6541:56;;;;-1:-1:-1;;;6541:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7102:132;7160:7;7187:39;7191:1;7194;7187:39;;;;;;;;;;;;;;;;;:3;:39::i;24246:418::-;-1:-1:-1;;;;;24330:21:0;;24322:67;;;;-1:-1:-1;;;24322:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24402:49;24423:7;24440:1;24444:6;24402:20;:49::i;:::-;24485:68;24508:6;24485:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24485:18:0;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;-1:-1:-1;;;;;24464:18:0;;:9;:18;;;;;;;;;;:89;24579:12;;:24;;24596:6;24579:24;:16;:24;:::i;:::-;24564:12;:39;24619:37;;;;;;;;24645:1;;-1:-1:-1;;;;;24619:37:0;;;;;;;;;;;;24246:418;;:::o;84630:281::-;84776:12;84763:9;:25;;;;;;;;;84759:145;;;84805:30;-1:-1:-1;;;;;84805:5:0;:18;84824:2;84828:6;84805:30;:18;:30;:::i;84759:145::-;84868:24;84881:2;84885:6;84868:12;:24::i;85561:156::-;85629:4;85669:10;85680:19;:17;:19::i;:::-;85669:31;;;;;;;;;;;;;;;;;;;;;:40;;;-1:-1:-1;;;85669:40:0;;-1:-1:-1;;;;;85669:40:0;85653:12;:56;;;85561:156;-1:-1:-1;85561:156:0:o;68830:2706::-;68941:34;68990:27;69032:12;69072:25;69100:10;69111:9;69100:21;;;;;;;;;;;;;;;;;;69563:39;;;69100:21;;;;;69563:39;;;;;;;;:67;;;69693:18;69673:39;;;;;:67;;;69785:55;;;;;;:83;;;69933:34;69913:55;;;;;:83;;;;69100:21;;-1:-1:-1;69100:21:0;;;;69563:67;;69673;;70189:202;69100:21;69563:67;69673;69785:83;69913;70189:20;:202::i;:::-;70007:384;;-1:-1:-1;70007:384:0;;-1:-1:-1;70007:384:0;;-1:-1:-1;70007:384:0;;-1:-1:-1;70007:384:0;-1:-1:-1;70423:17:0;70419:580;;70488:20;70461:47;;70419:580;;;70569:12;70585:1;70569:17;70565:434;;;70634:20;70607:47;;70565:434;;;70680:12;70696:1;70680:17;70676:323;;;70745:18;70718:45;;70676:323;;;70789:12;70805:1;70789:17;70785:214;;;70854:20;70827:47;;70785:214;;;70900:12;70916:1;70900:17;70896:103;;;70965:18;70938:45;;70896:103;71056:9;71025:298;;;71086:24;71080:31;;;;;;;;71025:298;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71391:19;;;;71334:194;;-1:-1:-1;;;;;71391:19:0;71425:29;71469;71513:4;71334:42;:194::i;:::-;68830:2706;;;;;;;;;;;;;:::o;28222:179::-;28278:6;28313:5;28305;:13;28297:65;;;;-1:-1:-1;;;28297:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36485:874;36608:7;36734:19;:9;:17;;;;;;;:19;36691:62;;;;;;;;:29;;:39;;:37;;;;;;;:39;:62;;;;;;;;;36687:103;;-1:-1:-1;36777:1:0;36770:8;;36687:103;36919:29;;:38;;:36;;;;;;;;;:38::i;:::-;36915:282;;;37012:18;:9;:16;;;;;;;:18;37008:90;;;-1:-1:-1;37058:24:0;;;;37051:31;;;;37008:90;-1:-1:-1;35462:19:0;37148:37;;36915:282;37253:20;:9;:18;;;;;;;:20;37249:84;;;-1:-1:-1;37297:24:0;;;;37290:31;;;;37249:84;-1:-1:-1;37350:1:0;36485:874;;;;:::o;57285:1140::-;57575:4;57594:7;57616;57651:13;57675:18;57696:22;:9;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57696:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:22::i;:::-;57675:43;;57756:12;57748:20;;57729:535;57806:11;57791:12;57783:5;:20;:34;57729:535;;;57879:10;57870:5;:19;57866:98;;-1:-1:-1;57918:4:0;;-1:-1:-1;57924:1:0;;-1:-1:-1;57927:20:0;;;;-1:-1:-1;57910:38:0;;57866:98;57978:17;57998:9;:20;;58019:5;57998:27;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57998:27:0;58126:30;;;;;;;;;;;;57998:27;;-1:-1:-1;58040:212:0;;58072:7;;57998:27;;58175:10;58204:4;58227:10;58040:13;:212::i;:::-;-1:-1:-1;57832:7:0;;;;;57729:535;;;58287:10;58278:5;:19;58274:90;;-1:-1:-1;58322:4:0;;-1:-1:-1;58328:1:0;;-1:-1:-1;58331:20:0;;;;-1:-1:-1;58314:38:0;;58274:90;-1:-1:-1;58382:5:0;;-1:-1:-1;58389:5:0;-1:-1:-1;;58396:20:0;;;57285:1140;;;;;;;;;;;;:::o;71726:627::-;71855:4;71957:20;71932:21;:45;;;;;;;;;71928:89;;;-1:-1:-1;72001:4:0;71994:11;;71928:89;72032:9;72052:28;:21;:26;;;;;;;:28;72044:37;;;;;;;;72032:49;;72027:297;72083:1;72088;72083:6;72027:297;;72111:21;;:::i;:::-;72135:6;:17;72163:1;72153:12;;;;;;;;72135:31;;;;;;;;;;;;;;;;;;;;;;;;;;;72111:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;72111:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72242:17;:4;:15;:17::i;:::-;:22;72238:75;;72292:5;72285:12;;;;;;72238:75;-1:-1:-1;72091:3:0;;72027:297;;34997:124;35050:9;35111:1;35098:4;35090:13;;;;;;;;35106:1;35090:17;35089:23;;;;;;35079:34;;;;;;;28700:179;28756:6;28791:5;28783;:13;28775:65;;;;-1:-1:-1;;;28775:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74500:205;74628:68;;;-1:-1:-1;;;;;74628:68:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;74628:68:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;74601:96:0;;74621:5;;74601:19;:96::i;:::-;74500:205;;;;:::o;34736:143::-;34791:4;;34815;:26;;;;;;;;;:56;;;-1:-1:-1;34853:18:0;34845:26;;52467:219;52518:10;52548:119;52594:10;:8;:10::i;:::-;52623:29;52624:12;52639:1;52624:16;52623:27;:29::i;:::-;52548:119;;:27;:119::i;:::-;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;52518:160:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;52518:160:0;;;-1:-1:-1;;;;;52518:160:0;;;;;;-1:-1:-1;;;52518:160:0;;;;;;;;52467:219::o;74315:177::-;74425:58;;;-1:-1:-1;;;;;74425:58:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;74425:58:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;74398:86:0;;74418:5;;74398:19;:86::i;7730:278::-;7816:7;7851:12;7844:5;7836:28;;;;-1:-1:-1;;;7836:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;7836:28:0;;7875:9;7891:1;7887;:5;;;;;;;7730:278;-1:-1:-1;;;;;7730:278:0:o;67824:998::-;68393:19;;;;68124:12;;;;;;;;;;-1:-1:-1;;;;;68393:19:0;35462;68347:65;68443:371;68484:50;:21;68347:65;68484:31;:50::i;:::-;68553:52;:23;68587:17;68553:52;:33;:52;:::i;:::-;68624:50;:21;68656:17;68624:50;:31;:50;:::i;:::-;68693:52;:23;68727:17;68693:52;:33;:52;:::i;:::-;68764:8;;68791;;-1:-1:-1;;;;;;;;68764:8:0;;;;;;68791;68443:22;:371::i;:::-;68423:391;;;;-1:-1:-1;68423:391:0;;-1:-1:-1;68423:391:0;-1:-1:-1;68423:391:0;;-1:-1:-1;67824:998:0;-1:-1:-1;;;;;;;67824:998:0:o;60324:1591::-;60559:19;60589;60619:25;60655;60725:27;60771:29;60818:230;60873:10;60902:29;60950;60998:4;61021:12;60818:36;:230::i;:::-;61077:8;;61142:14;;-1:-1:-1;;;;;;;;61077:8:0;;;;;:30;;;;-1:-1:-1;61077:8:0;61142:14;;;;;;:38;;-1:-1:-1;61236:27:0;;-1:-1:-1;61236:27:0;;-1:-1:-1;61329:230:0;61384:10;61413:29;61461;61509:4;61142:14;61329:36;:230::i;:::-;61588:8;;61653:14;;-1:-1:-1;;;;;61588:8:0;;;:30;;;;-1:-1:-1;61653:14:0;;;;:38;;-1:-1:-1;61713:64:0;;-1:-1:-1;61728:23:0;;-1:-1:-1;61728:11:0;:21;:23::i;:::-;61753;:11;:21;:23::i;61713:64::-;61788:119;61823:29;:17;:27;:29::i;:::-;61867;:17;:27;:29::i;:::-;61788:20;:119::i;:::-;60324:1591;;;;;;;;:::o;58745:1250::-;58955:14;58972:17;:7;:15;;;;;;;;;:17::i;:::-;58955:34;-1:-1:-1;59049:20:0;59072:30;:8;59091:10;59072:30;:18;:30;:::i;:::-;59049:53;-1:-1:-1;59201:38:0;59242:112;59307:46;35462:19;59342:10;59307:46;:34;:46;:::i;:::-;59242:40;:8;59269:12;59242:40;:26;:40;:::i;:::-;:64;:112;:64;:112;:::i;:::-;59201:153;;59501:17;59521:120;59559:7;59581:30;59626:4;59521:23;:120::i;:::-;59501:140;;59652:55;59674:7;59683:9;59694:12;59652:21;:55::i;:::-;59718:53;59740:8;59750:9;59761;59718:21;:53::i;:::-;59893:9;-1:-1:-1;;;;;59787:200:0;59858:19;:17;:19::i;:::-;59787:200;;59823:12;59812:7;:23;;;;;;;;59787:200;;;;;;;;;;;;;;;;;;;;59812:23;;;;;59787:200;;;;;;;;;58745:1250;;;;;;;;;;:::o;76620:761::-;77044:23;77070:69;77098:4;77070:69;;;;;;;;;;;;;;;;;77078:5;-1:-1:-1;;;;;77070:27:0;;;:69;;;;;:::i;:::-;77154:17;;77044:95;;-1:-1:-1;77154:21:0;77150:224;;77296:10;77285:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;77285:30:0;77277:85;;;;-1:-1:-1;;;77277:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84146:133;84193:7;84220:10;-1:-1:-1;;;;;84220:43:0;;84264:6;84220:51;;;;;;;;;;;;;-1:-1:-1;;;;;84220:51:0;-1:-1:-1;;;;;84220:51:0;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84220:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;84220:51:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;84220:51:0;;-1:-1:-1;84146:133:0;:::o;37824:211::-;37933:15;;:::i;:::-;-1:-1:-1;37973:54:0;;;;;;;;;-1:-1:-1;;;;;37973:54:0;;;;;;;;;;;;37824:211::o;65030:877::-;65369:12;65396:20;65431:27;65473:24;65512;65564:22;;:::i;:::-;65589:247;;;-1:-1:-1;;;65589:247:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;65589:9:0;:24;;;;:247;;;;;;;;;;;;;;:24;:247;;;2:2:-1;;;;27:1;24;17:12;2:2;65589:247:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65589:247:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;15:3;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;65589:247:0;-1:-1:-1;65589:247:0;65860:1;65855:7;;;;65864:4;65869:1;65864:7;;;;65873:4;65878:1;65873:7;;;;65882:4;65887:1;65882:7;;;;65891:4;65896:1;65891:7;;;;65847:52;;;;;;;;;;;65030:877;;;;;;;;;;;;:::o;72361:763::-;72611:7;;;72662:74;:28;72715:10;72662:74;:38;:74;:::i;:::-;72640:96;-1:-1:-1;72747:17:0;72767:38;72640:96;39233:18;72767:38;:21;:38;:::i;:::-;72747:58;;72816:18;72922:153;72964:19;:9;:17;;;;;;;:19;73002:35;73056:4;72922:23;:153::i;:::-;72882:23;;;;72837:69;;:238;;;;;-1:-1:-1;72896:9:0;-1:-1:-1;;72361:763:0;;;;;;;;:::o;34245:201::-;34297:5;;34319:4;:20;;;;;;;;;34315:124;;;-1:-1:-1;34363:12:0;34356:19;;34315:124;-1:-1:-1;34415:12:0;34408:19;;35825:178;35922:7;35954:41;35462:19;35954:14;:4;35963;35954:14;:8;:14;:::i;65998:320::-;66136:7;;66160:5;:21;;;;;;;;;66156:155;;;66205:27;:6;66222:9;66205:27;:16;:27;:::i;:::-;66198:34;;;;66156:155;66272:27;:6;66289:9;66272:27;:16;:27;:::i;85261:292::-;85417:12;85404:9;:25;;;;;;;;;85400:146;;;85446:30;-1:-1:-1;;;;;85446:5:0;:18;85465:2;85469:6;85446:30;:18;:30;:::i;85400:146::-;-1:-1:-1;;;;;85509:15:0;;;;;;:11;:15;;;;;:25;;;;;;85261:292;;;:::o;13173:196::-;13276:12;13308:53;13331:6;13339:4;13345:1;13348:12;13308:22;:53::i;:::-;13301:60;13173:196;-1:-1:-1;;;;13173:196:0:o;14550:979::-;14680:12;14713:18;14724:6;14713:10;:18::i;:::-;14705:60;;;;;-1:-1:-1;;;14705:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;14839:12;14853:23;14880:6;-1:-1:-1;;;;;14880:11:0;14900:8;14911:4;14880:36;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;14880:36:0;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;14838:78:0;;;;14931:7;14927:595;;;14962:10;-1:-1:-1;14955:17:0;;-1:-1:-1;14955:17:0;14927:595;15076:17;;:21;15072:439;;15339:10;15333:17;15400:15;15387:10;15383:2;15379:19;15372:44;15287:148;15475:20;;-1:-1:-1;;;15475:20:0;;;;;;;;;;;;;;;;;15482:12;;15475:20;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;10058:619:0;10118:4;10586:20;;10429:66;10626:23;;;;;;:42;;-1:-1:-1;;10653:15:0;;;10618:51;-1:-1:-1;;10058:619:0:o;86336:839::-;;;;;;;;;;;-1:-1:-1;86336:839:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;86336:839:0;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;86336:839:0;;;-1:-1:-1;;86336:839:0:o;:::-;;;;;;;;;;;;;;;;;

Swarm Source

ipfs://fc8042f134361df36258d94edf8f6d257bae11b393a73d0aa7846d4648c458b8

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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