More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,415 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Remove Liquidity | 10928860 | 1607 days ago | IN | 0 ETH | 0.00757141 | ||||
Order Base To Se... | 10907087 | 1611 days ago | IN | 0 ETH | 0.0276571 | ||||
Execute Unexecut... | 10891995 | 1613 days ago | IN | 0 ETH | 0.02165912 | ||||
Order Base To Se... | 10891452 | 1613 days ago | IN | 0 ETH | 0.0237583 | ||||
Execute Unexecut... | 10888954 | 1613 days ago | IN | 0 ETH | 0.01523683 | ||||
Order Base To Se... | 10887809 | 1614 days ago | IN | 0 ETH | 0.10754818 | ||||
Remove Liquidity | 10882235 | 1614 days ago | IN | 0 ETH | 0.0466569 | ||||
Remove Liquidity | 10881950 | 1614 days ago | IN | 0 ETH | 0.04219857 | ||||
Remove Liquidity | 10880988 | 1615 days ago | IN | 0 ETH | 0.05132259 | ||||
Remove Liquidity | 10878725 | 1615 days ago | IN | 0 ETH | 0.051841 | ||||
Remove Liquidity | 10878620 | 1615 days ago | IN | 0 ETH | 0.09138514 | ||||
Order Settlement... | 10872902 | 1616 days ago | IN | 0 ETH | 0.03409853 | ||||
Order Settlement... | 10872886 | 1616 days ago | IN | 0 ETH | 0.03646742 | ||||
Order Settlement... | 10872833 | 1616 days ago | IN | 0 ETH | 0.03208467 | ||||
Order Base To Se... | 10872828 | 1616 days ago | IN | 0 ETH | 0.02073862 | ||||
Execute Unexecut... | 10872822 | 1616 days ago | IN | 0 ETH | 0.01904604 | ||||
Order Base To Se... | 10872820 | 1616 days ago | IN | 0 ETH | 0.03200437 | ||||
Order Base To Se... | 10872813 | 1616 days ago | IN | 0 ETH | 0.02156817 | ||||
Execute Unexecut... | 10872809 | 1616 days ago | IN | 0 ETH | 0.01302949 | ||||
Order Base To Se... | 10872797 | 1616 days ago | IN | 0 ETH | 0.03815933 | ||||
Order Base To Se... | 10872794 | 1616 days ago | IN | 0 ETH | 0.06142665 | ||||
Order Base To Se... | 10872789 | 1616 days ago | IN | 0 ETH | 0.00963512 | ||||
Order Base To Se... | 10872789 | 1616 days ago | IN | 0 ETH | 0.02651385 | ||||
Order Base To Se... | 10872783 | 1616 days ago | IN | 0 ETH | 0.00495001 | ||||
Order Base To Se... | 10872783 | 1616 days ago | IN | 0 ETH | 0.03026079 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
LienBoxExchange
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-08-31 */ // 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: contracts/Interfaces/ERC20Interface.sol pragma solidity >=0.6.6; interface ERC20Interface is IERC20 { function name() external view returns (string memory); } // 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/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/TokenBoxExchange/TokenBoxExchange.sol pragma solidity >=0.6.6; abstract contract TokenBoxExchange is BoxExchange { using SafeERC20 for ERC20Interface; ERC20Interface public immutable idol; // token0 ERC20Interface public immutable token; SpreadCalculatorInterface internal immutable spreadCalc; OracleInterface internal immutable oracle; event SpreadRate(uint128 indexed boxNumber, uint128 spreadRate); /** * @param _idol iDOL contract * @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 * @param _name Name of share token **/ constructor( ERC20Interface _idol, ERC20Interface _token, PriceCalculatorInterface _priceCalc, address _marketFeeTaker, SpreadCalculatorInterface _spreadCalc, OracleInterface _oracle, string memory _name ) public BoxExchange(_priceCalc, _marketFeeTaker, _name) { idol = _idol; token = _token; spreadCalc = _spreadCalc; oracle = _oracle; } /** * @param IDOLAmount Amount of initial liquidity of iDOL to be provided * @param settlementTokenAmount Amount of initial liquidity of the other token to be provided * @param initialShare Initial amount of share token **/ function initializeExchange( uint256 IDOLAmount, uint256 settlementTokenAmount, uint256 initialShare ) external { _init( uint128(IDOLAmount), uint128(settlementTokenAmount), initialShare ); } /** * @param timeout Revert if nextBoxNumber exceeds `timeout` * @param recipient Recipient of swapped token. If `recipient` == address(0), recipient is msg.sender * @param IDOLAmount 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 orderBaseToSettlement( uint256 timeout, address recipient, uint256 IDOLAmount, bool isLimit ) external isAmountSafe(IDOLAmount) isInTime(timeout) { OrderType orderType = _getTokenType(true, isLimit); _addOrder(orderType, IDOLAmount, recipient); } /** * @param timeout Revert if nextBoxNumber exceeds `timeout` * @param recipient Recipient of swapped token. If `recipient` == address(0), recipient is msg.sender * @param settlementTokenAmount 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 * 0.999 > `rate`, the order will be executed, otherwise token will be refunded * @dev if isLimit is false and reserve0/reserve1 * 0.95 > `rate`, the order will be executed, otherwise token will be refunded **/ function orderSettlementToBase( uint256 timeout, address recipient, uint256 settlementTokenAmount, bool isLimit ) external isAmountSafe(settlementTokenAmount) isInTime(timeout) { OrderType orderType = _getTokenType(false, isLimit); _addOrder(orderType, settlementTokenAmount, recipient); } /** * @notice LP provides liquidity and receives share token * @param timeout Revert if nextBoxNumber exceeds `timeout` * @param IDOLAmount Amount of iDOL to be provided. The amount of the other token required is calculated based on this amount * @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 IDOLAmount, uint256 settlementTokenAmount, uint256 minShares ) external isAmountSafe(IDOLAmount) isAmountSafe(settlementTokenAmount) isInTime(timeout) { require(timeout > _currentOpenBoxId(), "Time out"); (uint256 _reserve0, uint256 _reserve1) = _getReserves(); // gas savings uint256 settlementAmountInBase = settlementTokenAmount .mul(_reserve0) .div(_reserve1); if (IDOLAmount <= settlementAmountInBase) { _addLiquidity( _reserve0, _reserve1, IDOLAmount, minShares, Token.TOKEN0 ); } else { _addLiquidity( _reserve0, _reserve1, settlementTokenAmount, minShares, Token.TOKEN1 ); } } /** * @notice LP burns share token and receives iDOL and the other token * @param timeout Revert if nextBoxNumber exceeds `timeout` * @param minBaseTokens Minimum amount of iDOL LP will receive. If amount of iDOL is less than `minBaseTokens`, revert the transaction * @param minSettlementTokens Minimum amount of the other token LP will get. If amount is less than `minSettlementTokens`, revert the transaction * @param sharesBurned Amount of share token to be burned **/ function removeLiquidity( uint256 timeout, uint256 minBaseTokens, uint256 minSettlementTokens, uint256 sharesBurned ) external isInTime(timeout) { require(timeout > _currentOpenBoxId(), "Time out"); _removeLiquidity(minBaseTokens, minSettlementTokens, 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(); } // definition of abstract functions function _receiveTokens( Token tokenType, address from, uint256 amount ) internal override { _IERC20(tokenType).safeTransferFrom(from, address(this), amount); } function _sendTokens( Token tokenType, address to, uint256 amount ) internal override { _IERC20(tokenType).safeTransfer(to, amount); } function _payForOrderExecution( Token tokenType, address to, uint256 amount ) internal override { _IERC20(tokenType).safeTransfer(to, amount); } function _isCurrentOpenBoxExpired() internal override view returns (bool) { return block.number >= orderBoxes[_currentOpenBoxId()].expireAt; } function _openNewBox() internal override(BoxExchange) { super._openNewBox(); uint256 _boxNumber = _currentOpenBoxId(); emit SpreadRate( _boxNumber.toUint128(), orderBoxes[_boxNumber].spreadRate ); } function _IERC20(Token tokenType) internal view returns (ERC20Interface) { if (tokenType == Token.TOKEN0) { return idol; } return token; } } // File: contracts/BoxExchange/TokenBoxExchange/IDOLvsERC20/ERC20BoxExchange.sol pragma solidity >=0.6.6; contract ERC20BoxExchange is TokenBoxExchange { /** * @param _idol iDOL contract * @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 * @param _name Name of share token **/ constructor( ERC20Interface _idol, ERC20Interface _token, PriceCalculatorInterface _priceCalc, address _marketFeeTaker, SpreadCalculatorInterface _spreadCalc, OracleInterface _oracle, string memory _name ) public TokenBoxExchange( _idol, _token, _priceCalc, _marketFeeTaker, _spreadCalc, _oracle, _name ) {} // definition of abstract functions function _feeRate() internal override returns (uint128) { return spreadCalc.calculateSpreadByAssetVolatility(oracle); } function _payMarketFee( address _marketFeeTaker, uint256 amount0, uint256 amount1 ) internal override { if (amount0 != 0) { idol.safeTransfer(_marketFeeTaker, amount0); } } /** * @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 override { uint256 newReserve0; uint256 newReserve1; uint256 newMarketFeePool0; uint256 marketFee1; { ( uint256 differenceOfReserve, uint256 differenceOfMarketFee ) = _calculateNewReserveAndMarketFeePool( spreadRate, executingAmount0WithoutSpread, executingAmount1WithoutSpread, rate, Token.TOKEN0 ); newReserve0 = reserve0 + differenceOfReserve; newMarketFeePool0 = marketFeePool0 + differenceOfMarketFee; } { (newReserve1, marketFee1) = _calculateNewReserveAndMarketFeePool( spreadRate, executingAmount1WithoutSpread, executingAmount0WithoutSpread, rate, Token.TOKEN1 ); newReserve1 = newReserve1 + reserve1; } { uint256 convertedSpread1to0 = marketFee1 .mulByRate(newReserve0.divByRate(newReserve1.add(marketFee1))) .divByRate(RateMath.RATE_POINT_MULTIPLIER); newReserve1 = newReserve1 + marketFee1; newReserve0 = newReserve0 - convertedSpread1to0; newMarketFeePool0 = newMarketFeePool0 + convertedSpread1to0; } _updateReserve(newReserve0.toUint128(), newReserve1.toUint128()); _updateMarketFeePool(newMarketFeePool0.toUint128()); } /** * updates only pool0 */ function _updateMarketFeePool(uint256 newMarketFeePool0) internal { marketFeePool0 = newMarketFeePool0.toUint128(); } } // File: @openzeppelin/contracts/math/Math.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: @openzeppelin/contracts/utils/Arrays.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Collection of functions related to array types. */ library Arrays { /** * @dev Searches a sorted `array` and returns the first index that contains * a value greater or equal to `element`. If no such index exists (i.e. all * values in the array are strictly less than `element`), the array length is * returned. Time complexity O(log n). * * `array` is expected to be sorted in ascending order, and to contain no * repeated elements. */ function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { if (array.length == 0) { return 0; } uint256 low = 0; uint256 high = array.length; while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds down (it does integer division with truncation). if (array[mid] > element) { high = mid; } else { low = mid + 1; } } // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. if (low > 0 && array[low - 1] == element) { return low - 1; } else { return low; } } } // File: @openzeppelin/contracts/utils/Counters.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never * directly accessed. */ library Counters { using SafeMath for uint256; struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { // The {SafeMath} overflow check can be skipped here, see the comment at the top counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } } // File: @openzeppelin/contracts/token/ERC20/ERC20Snapshot.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and * total supply at the time are recorded for later access. * * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting. * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be * used to create an efficient ERC20 forking mechanism. * * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id * and the account address. * * ==== Gas Costs * * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much * smaller since identical balances in subsequent snapshots are stored as a single entry. * * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent * transfers will have normal cost until the next snapshot, and so on. */ abstract contract ERC20Snapshot is ERC20 { // Inspired by Jordi Baylina's MiniMeToken to record historical balances: // https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol using SafeMath for uint256; using Arrays for uint256[]; using Counters for Counters.Counter; // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a // Snapshot struct, but that would impede usage of functions that work on an array. struct Snapshots { uint256[] ids; uint256[] values; } mapping (address => Snapshots) private _accountBalanceSnapshots; Snapshots private _totalSupplySnapshots; // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid. Counters.Counter private _currentSnapshotId; /** * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created. */ event Snapshot(uint256 id); /** * @dev Creates a new snapshot and returns its snapshot id. * * Emits a {Snapshot} event that contains the same id. * * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a * set of accounts, for example using {AccessControl}, or it may be open to the public. * * [WARNING] * ==== * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking, * you must consider that it can potentially be used by attackers in two ways. * * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs * section above. * * We haven't measured the actual numbers; if this is something you're interested in please reach out to us. * ==== */ function _snapshot() internal virtual returns (uint256) { _currentSnapshotId.increment(); uint256 currentId = _currentSnapshotId.current(); emit Snapshot(currentId); return currentId; } /** * @dev Retrieves the balance of `account` at the time `snapshotId` was created. */ function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]); return snapshotted ? value : balanceOf(account); } /** * @dev Retrieves the total supply at the time `snapshotId` was created. */ function totalSupplyAt(uint256 snapshotId) public view returns(uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots); return snapshotted ? value : totalSupply(); } // _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the // snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value. // The same is true for the total supply and _mint and _burn. function _transfer(address from, address to, uint256 value) internal virtual override { _updateAccountSnapshot(from); _updateAccountSnapshot(to); super._transfer(from, to, value); } function _mint(address account, uint256 value) internal virtual override { _updateAccountSnapshot(account); _updateTotalSupplySnapshot(); super._mint(account, value); } function _burn(address account, uint256 value) internal virtual override { _updateAccountSnapshot(account); _updateTotalSupplySnapshot(); super._burn(account, value); } function _valueAt(uint256 snapshotId, Snapshots storage snapshots) private view returns (bool, uint256) { require(snapshotId > 0, "ERC20Snapshot: id is 0"); // solhint-disable-next-line max-line-length require(snapshotId <= _currentSnapshotId.current(), "ERC20Snapshot: nonexistent id"); // When a valid snapshot is queried, there are three possibilities: // a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never // created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds // to this id is the current one. // b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the // requested id, and its value is the one to return. // c) More snapshots were created after the requested one, and the queried value was later modified. There will be // no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is // larger than the requested one. // // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does // exactly this. uint256 index = snapshots.ids.findUpperBound(snapshotId); if (index == snapshots.ids.length) { return (false, 0); } else { return (true, snapshots.values[index]); } } function _updateAccountSnapshot(address account) private { _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account)); } function _updateTotalSupplySnapshot() private { _updateSnapshot(_totalSupplySnapshots, totalSupply()); } function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private { uint256 currentId = _currentSnapshotId.current(); if (_lastSnapshotId(snapshots.ids) < currentId) { snapshots.ids.push(currentId); snapshots.values.push(currentValue); } } function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) { if (ids.length == 0) { return 0; } else { return ids[ids.length - 1]; } } } // File: contracts/Interfaces/LienTokenInterface.sol pragma solidity >=0.6.6; interface LienTokenInterface is IERC20 { function currentTerm() external view returns (uint256); function expiration() external view returns (uint256); function receiveDividend(address token, address recipient) external; function dividendAt( address token, address account, uint256 term ) external view returns (uint256); } // File: contracts/BoxExchange/TokenBoxExchange/IDOLvsERC20/IDOLvsLien/ERC20Redistribution.sol pragma solidity >=0.6.6; abstract contract ERC20Redistribution is ERC20Snapshot { using SafeERC20 for ERC20Interface; struct Dividend { mapping(ERC20Interface => uint256) tokens; uint256 eth; } LienTokenInterface public lien; mapping(uint256 => uint256) private snapshotsOfTermEnd; mapping(uint256 => Dividend) private totalDividendsAt; mapping(address => mapping(ERC20Interface => uint256)) private lastReceivedTermsOfTokens; mapping(address => uint256) private lastReceivedTermsOfEth; event ReceiveDividendETH(address indexed recipient, uint256 amount); event ReceiveDividendToken( address indexed recipient, address indexed tokenAddress, uint256 amount ); modifier termValidation(uint256 _term) { require(_term > 0, "0 is invalid value as term"); _; } receive() external payable {} constructor(LienTokenInterface _lien) public { lien = _lien; } /** * @notice Transfers ERC20 token dividend to Liquidity Provider * @notice Before transfer dividend, this exchange withdraws dividend in this ERC20 token from Lien Token * @param token Target ERC20 token to be received */ function receiveDividendToken(ERC20Interface token) public { uint256 _currentTerm = currentTerm(); if (_currentTerm == 1) { return; } _moveDividendTokenFromLIEN(token, _currentTerm); uint256 lastReceivedTerm = lastReceivedTermsOfTokens[msg.sender][token]; lastReceivedTermsOfTokens[msg.sender][token] = _currentTerm - 1; uint256 dividend; for (uint256 term = lastReceivedTerm + 1; term < _currentTerm; term++) { dividend += dividendTokenAt(msg.sender, token, term); } emit ReceiveDividendToken(msg.sender, address(token), dividend); token.safeTransfer(msg.sender, dividend); } /** * @notice Transfers ETH dividend to Liquidity Provider * @notice Before transfer dividend, this exchange withdraws dividend in ETH from Lien Token */ function receiveDividendEth() public { uint256 _currentTerm = currentTerm(); if (_currentTerm == 1) { return; } _moveDividendEthFromLIEN(_currentTerm); uint256 lastReceivedTerm = lastReceivedTermsOfEth[msg.sender]; lastReceivedTermsOfEth[msg.sender] = _currentTerm - 1; uint256 dividend; for (uint256 term = lastReceivedTerm + 1; term < _currentTerm; term++) { dividend += dividendEthAt(msg.sender, term); } emit ReceiveDividendETH(msg.sender, dividend); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = msg.sender.call{value: dividend}(""); require(success, "ETH transfer failed"); } /** * @notice Gets current term in Lien Token **/ function currentTerm() public view returns (uint256) { return lien.currentTerm(); } /** * @notice Gets amount of ERC20 token dividend LP can get in the `term` * @param account Target account * @param token Target ERC20 token * @param term Target term **/ function dividendTokenAt( address account, ERC20Interface token, uint256 term ) public view returns (uint256) { uint256 balanceAtTermEnd = balanceOfAtTermEnd(account, term); uint256 totalSupplyAtTermEnd = totalSupplyAtTermEnd(term); uint256 totalDividend = totalDividendTokenAt(token, term); return totalDividend.mul(balanceAtTermEnd).div(totalSupplyAtTermEnd); } /** * @notice Gets Amount of ETH dividend LP can get in the `term` * @param account Target account * @param term Target term **/ function dividendEthAt(address account, uint256 term) public view returns (uint256) { uint256 balanceAtTermEnd = balanceOfAtTermEnd(account, term); uint256 totalSupplyAtTermEnd = totalSupplyAtTermEnd(term); uint256 totalDividend = totalDividendEthAt(term); return totalDividend.mul(balanceAtTermEnd).div(totalSupplyAtTermEnd); } /** * @notice Gets total amount of ERC20 token dividend this exchange received in the `term` * @param token Target ERC20 token * @param term Target term **/ function totalDividendTokenAt(ERC20Interface token, uint256 term) public view returns (uint256) { return totalDividendsAt[term].tokens[token]; } /** * @notice Gets total amount of ETH dividend this exchange received in the `term` * @param term Target term **/ function totalDividendEthAt(uint256 term) public view returns (uint256) { return totalDividendsAt[term].eth; } /** * @notice Retrieves the balance of `account` at the end of the term `term` * @param account Target account * @param term Target term */ function balanceOfAtTermEnd(address account, uint256 term) public view termValidation(term) returns (uint256) { uint256 _currentTerm = currentTerm(); for (uint256 i = term; i < _currentTerm; i++) { if (_isSnapshottedOnTermEnd(i)) { return balanceOfAt(account, snapshotsOfTermEnd[i]); } } return balanceOf(account); } /** * @notice Retrieves the total supply at the end of the term `term` * @param term Target term */ function totalSupplyAtTermEnd(uint256 term) public view termValidation(term) returns (uint256) { uint256 _currentTerm = currentTerm(); for (uint256 i = term; i < _currentTerm; i++) { if (_isSnapshottedOnTermEnd(i)) { return totalSupplyAt(snapshotsOfTermEnd[i]); } } return totalSupply(); } function _transfer( address from, address to, uint256 value ) internal virtual override { _snapshotOnTermEnd(); super._transfer(from, to, value); } function _mint(address account, uint256 value) internal virtual override { _snapshotOnTermEnd(); super._mint(account, value); } function _burn(address account, uint256 value) internal virtual override { _snapshotOnTermEnd(); super._burn(account, value); } function _snapshotOnTermEnd() private { uint256 _currentTerm = currentTerm(); if (_currentTerm > 1 && !_isSnapshottedOnTermEnd(_currentTerm - 1)) { snapshotsOfTermEnd[_currentTerm - 1] = _snapshot(); } } function _isSnapshottedOnTermEnd(uint256 term) private view returns (bool) { return snapshotsOfTermEnd[term] != 0; } /** * @notice Withdraws dividends in ETH and iDOL from Lien Token * @dev At first, this function registers amount of dividends from Lien Token, and thereafter withdraws it **/ function _moveDividendTokenFromLIEN( ERC20Interface token, uint256 _currentTerm ) private { uint256 expiration = lien.expiration(); uint256 start; uint256 totalNewDividend; if (_currentTerm > expiration) { start = _currentTerm - expiration; } else { start = 1; } //get and register dividend amount in the exchange from Lien Token contract for (uint256 i = _currentTerm - 1; i >= start; i--) { if (totalDividendsAt[i].tokens[token] != 0) { break; } uint256 dividend = lien.dividendAt( address(token), address(this), i ); totalDividendsAt[i].tokens[token] = dividend; totalNewDividend += dividend; } if (totalNewDividend == 0) { return; } lien.receiveDividend(address(token), address(this)); } /** * @notice Withdraws dividends in ETH and iDOL from lienToken * @dev At first, this function registers amount of dividend from Lien Token, and thereafter withdraws it **/ function _moveDividendEthFromLIEN(uint256 _currentTerm) private { uint256 expiration = lien.expiration(); uint256 start; uint256 totalNewDividend; if (_currentTerm > expiration) { start = _currentTerm - expiration; } else { start = 1; } //get and register dividend amount in the exchange from Lien Token contract for (uint256 i = _currentTerm - 1; i >= start; i--) { if (totalDividendsAt[i].eth != 0) { break; } uint256 dividend = lien.dividendAt(address(0), address(this), i); totalDividendsAt[i].eth = dividend; totalNewDividend += dividend; } if (totalNewDividend == 0) { return; } lien.receiveDividend(address(0), address(this)); } } // File: contracts/BoxExchange/TokenBoxExchange/IDOLvsERC20/IDOLvsLien/LienBoxExchange.sol pragma solidity >=0.6.6; contract LienBoxExchange is ERC20BoxExchange, ERC20Redistribution { /** * @param _idol iDOL contract * @param _priceCalc Price Calculator contract * @param _lien Lien Token contract * @param _spreadCalc Spread Calculator contract * @param _name Name of share token **/ constructor( ERC20Interface _idol, PriceCalculatorInterface _priceCalc, LienTokenInterface _lien, SpreadCalculatorInterface _spreadCalc, string memory _name ) public ERC20Redistribution(_lien) ERC20BoxExchange( _idol, ERC20Interface(address(_lien)), _priceCalc, address(_lien), _spreadCalc, OracleInterface(address(0)), _name ) {} // overriding ERC20 functions function _transfer( address from, address to, uint256 value ) internal override(ERC20, ERC20Redistribution) { ERC20Redistribution._transfer(from, to, value); } function _burn(address account, uint256 value) internal override(ERC20, ERC20Redistribution) { ERC20Redistribution._burn(account, value); } function _mint(address account, uint256 value) internal override(ERC20, ERC20Redistribution) { ERC20Redistribution._mint(account, value); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ERC20Interface","name":"_idol","type":"address"},{"internalType":"contract PriceCalculatorInterface","name":"_priceCalc","type":"address"},{"internalType":"contract LienTokenInterface","name":"_lien","type":"address"},{"internalType":"contract SpreadCalculatorInterface","name":"_spreadCalc","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":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveDividendETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveDividendToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","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":"IDOLAmount","type":"uint256"},{"internalType":"uint256","name":"settlementTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minShares","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"balanceOfAtTermEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTerm","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":"address","name":"account","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"dividendEthAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"contract ERC20Interface","name":"token","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"dividendTokenAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"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":[],"name":"idol","outputs":[{"internalType":"contract ERC20Interface","name":"","type":"address"}],"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":"IDOLAmount","type":"uint256"},{"internalType":"uint256","name":"settlementTokenAmount","type":"uint256"},{"internalType":"uint256","name":"initialShare","type":"uint256"}],"name":"initializeExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lien","outputs":[{"internalType":"contract LienTokenInterface","name":"","type":"address"}],"stateMutability":"view","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":"uint256","name":"IDOLAmount","type":"uint256"},{"internalType":"bool","name":"isLimit","type":"bool"}],"name":"orderBaseToSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeout","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"settlementTokenAmount","type":"uint256"},{"internalType":"bool","name":"isLimit","type":"bool"}],"name":"orderSettlementToBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"receiveDividendEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20Interface","name":"token","type":"address"}],"name":"receiveDividendToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeout","type":"uint256"},{"internalType":"uint256","name":"minBaseTokens","type":"uint256"},{"internalType":"uint256","name":"minSettlementTokens","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":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"totalDividendEthAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20Interface","name":"token","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"totalDividendTokenAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"totalSupplyAtTermEnd","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"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101606040523480156200001257600080fd5b5060405162004e0c38038062004e0c833981810160405260a08110156200003857600080fd5b81516020830151604080850151606086015160808701805193519597949692959194919392820192846401000000008211156200007457600080fd5b9083019060208201858111156200008a57600080fd5b8251640100000000811182820188101715620000a557600080fd5b82525081516020918201929091019080838360005b83811015620000d4578181015183820152602001620000ba565b50505050905090810190601f168015620001025780820380516001836020036101000a031916815260200191505b5060405250505082858486868660008786868686868686848482806040518060400160405280600581526020017f736861726500000000000000000000000000000000000000000000000000000081525081600390805190602001906200016b92919062000248565b5080516200018190600490602084019062000248565b50506005805460ff191660121790555033606090811b6080526001600160601b031984821b811660c0529083901b1660a052620001c860086001600160e01b036200023216565b50505050606095861b6001600160601b031990811660e05294861b85166101005290851b84166101205290931b909116610140525050601080546001600160a01b0319166001600160a01b03999099169890981790975550620002ed9a5050505050505050505050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200028b57805160ff1916838001178555620002bb565b82800160010185558215620002bb579182015b82811115620002bb5782518255916020019190600101906200029e565b50620002c9929150620002cd565b5090565b620002ea91905b80821115620002c95760008155600101620002d4565b90565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c614aa7620003656000398061406952508061403a52508061183252806139f2525080610dac528061326d52806139cb5250806142ea5250806121be5250806120f45250614aa76000f3fe6080604052600436106102295760003560e01c806395d89b4111610123578063bb2f53b4116100ab578063dd62ed3e1161006f578063dd62ed3e14610923578063dec7bfd21461095e578063e1b4df2a146109a1578063f88bf15a146109e8578063fc0c546a14610a2457610230565b8063bb2f53b41461086a578063c48c73421461087f578063c9a01af914610894578063d5855e7a146108c1578063da84fb0b146108d657610230565b8063a3fee072116100f2578063a3fee07214610736578063a457c2d71461078b578063a9059cbb146107c4578063aebf3e41146107fd578063b196a3521461083957610230565b806395d89b41146106af578063981b24d0146106c45780639c558c4b146106ee578063a11bc81f1461070357610230565b806339509351116101b15780636d294d06116101755780636d294d06146105bc57806370a08231146105f55780637112ed021461062857806384c76abc1461065e57806392dea49c1461069a57610230565b8063395093511461047e5780634ee2cd7e146104b75780634fc0bf09146104f057806359e713141461052957806369cb06541461059257610230565b806318160ddd116101f857806318160ddd146103a05780631c67247c146103b557806323b872dd146103df578063313ce56714610422578063385a8d501461044d57610230565b8063068228591461023557806306fdde0314610280578063095ea7b31461030a5780630d96ad311461035757610230565b3661023057005b600080fd5b34801561024157600080fd5b5061026e6004803603604081101561025857600080fd5b506001600160a01b038135169060200135610a39565b60408051918252519081900360200190f35b34801561028c57600080fd5b50610295610af5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102cf5781810151838201526020016102b7565b50505050905090810190601f1680156102fc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561031657600080fd5b506103436004803603604081101561032d57600080fd5b506001600160a01b038135169060200135610b8c565b604080519115158252519081900360200190f35b34801561036357600080fd5b5061039e6004803603608081101561037a57600080fd5b508035906001600160a01b0360208201351690604081013590606001351515610baa565b005b3480156103ac57600080fd5b5061026e610c55565b3480156103c157600080fd5b5061026e600480360360208110156103d857600080fd5b5035610c5b565b3480156103eb57600080fd5b506103436004803603606081101561040257600080fd5b506001600160a01b03813581169160208101359091169060400135610d13565b34801561042e57600080fd5b50610437610da1565b6040805160ff9092168252519081900360200190f35b34801561045957600080fd5b50610462610daa565b604080516001600160a01b039092168252519081900360200190f35b34801561048a57600080fd5b50610343600480360360408110156104a157600080fd5b506001600160a01b038135169060200135610dce565b3480156104c357600080fd5b5061026e600480360360408110156104da57600080fd5b506001600160a01b038135169060200135610e22565b3480156104fc57600080fd5b5061026e6004803603604081101561051357600080fd5b506001600160a01b038135169060200135610e68565b34801561053557600080fd5b506105726004803603608081101561054c57600080fd5b506001600160a01b03813516906020810135906040810135151590606001351515610ebb565b604080519315158452602084019290925282820152519081900360600190f35b34801561059e57600080fd5b5061026e600480360360208110156105b557600080fd5b5035610ee5565b3480156105c857600080fd5b5061026e600480360360408110156105df57600080fd5b506001600160a01b038135169060200135610efd565b34801561060157600080fd5b5061026e6004803603602081101561061857600080fd5b50356001600160a01b0316610f24565b34801561063457600080fd5b5061039e6004803603606081101561064b57600080fd5b5080359060208101359060400135610f3f565b34801561066a57600080fd5b5061026e6004803603604081101561068157600080fd5b5080356001600160a01b0316906020013560ff16610f4f565b3480156106a657600080fd5b50610462610fbe565b3480156106bb57600080fd5b50610295610fcd565b3480156106d057600080fd5b5061026e600480360360208110156106e757600080fd5b503561102e565b3480156106fa57600080fd5b5061039e611054565b34801561070f57600080fd5b5061039e6004803603602081101561072657600080fd5b50356001600160a01b031661105e565b34801561074257600080fd5b506107606004803603602081101561075957600080fd5b5035611137565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561079757600080fd5b50610343600480360360408110156107ae57600080fd5b506001600160a01b038135169060200135611252565b3480156107d057600080fd5b50610343600480360360408110156107e757600080fd5b506001600160a01b0381351690602001356112c0565b34801561080957600080fd5b5061039e6004803603608081101561082057600080fd5b50803590602081013590604081013590606001356112d4565b34801561084557600080fd5b5061084e61143f565b604080516001600160801b039092168252519081900360200190f35b34801561087657600080fd5b5061039e61144e565b34801561088b57600080fd5b5061026e611579565b3480156108a057600080fd5b5061039e600480360360208110156108b757600080fd5b503560ff166115ef565b3480156108cd57600080fd5b5061084e6115f8565b3480156108e257600080fd5b506108eb61160c565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561092f57600080fd5b5061026e6004803603604081101561094657600080fd5b506001600160a01b0381358116916020013516611688565b34801561096a57600080fd5b5061026e6004803603606081101561098157600080fd5b506001600160a01b038135811691602081013590911690604001356116b3565b3480156109ad57600080fd5b5061039e600480360360808110156109c457600080fd5b508035906001600160a01b03602082013516906040810135906060013515156116fc565b3480156109f457600080fd5b5061039e60048036036080811015610a0b57600080fd5b5080359060208101359060408101359060600135611791565b348015610a3057600080fd5b50610462611830565b60008160008111610a91576040805162461bcd60e51b815260206004820152601a60248201527f3020697320696e76616c69642076616c7565206173207465726d000000000000604482015290519081900360640190fd5b6000610a9b611579565b9050835b81811015610ae057610ab081611854565b15610ad857600081815260116020526040902054610acf908790610e22565b93505050610aee565b600101610a9f565b50610aea85610f24565b9250505b5092915050565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b815780601f10610b5657610100808354040283529160200191610b81565b820191906000526020600020905b815481529060010190602001808311610b6457829003601f168201915b505050505090505b90565b6000610ba0610b99611868565b848461186c565b5060015b92915050565b8180610beb576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b84610bf4611958565b8111610c32576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000610c3f600185611962565b9050610c4c818688611996565b50505050505050565b60025490565b60008160008111610cb3576040805162461bcd60e51b815260206004820152601a60248201527f3020697320696e76616c69642076616c7565206173207465726d000000000000604482015290519081900360640190fd5b6000610cbd611579565b9050835b81811015610d0057610cd281611854565b15610cf857600081815260116020526040902054610cef9061102e565b93505050610d0d565b600101610cc1565b50610d09610c55565b9250505b50919050565b6000610d20848484611a91565b610d9684610d2c611868565b610d918560405180606001604052806028815260200161496b602891396001600160a01b038a16600090815260016020526040812090610d6a611868565b6001600160a01b03168152602081019190915260400160002054919063ffffffff611a9c16565b61186c565b5060015b9392505050565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ba0610ddb611868565b84610d918560016000610dec611868565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff611b3316565b6001600160a01b0382166000908152600c6020526040812081908190610e49908590611b8d565b9150915081610e6057610e5b85610f24565b610aea565b949350505050565b600080610e758484610a39565b90506000610e8284610c5b565b90506000610e8f85610ee5565b9050610eb182610ea5838663ffffffff611c9016565b9063ffffffff611ce916565b9695505050505050565b6000806000610ed487610ece8787611d2b565b88611d57565b9250925092505b9450945094915050565b6000818152601260205260409020600101545b919050565b60009081526012602090815260408083206001600160a01b03949094168352929052205490565b6001600160a01b031660009081526020819052604090205490565b610f4a838383612099565b505050565b60006008610f5b611958565b81548110610f6557fe5b90600052602060002090600202016000016000836003811115610f8457fe5b6003811115610f8f57fe5b8152602080820192909252604090810160009081206001600160a01b0387168252909252902054905092915050565b6010546001600160a01b031681565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b815780601f10610b5657610100808354040283529160200191610b81565b600080600061103e84600d611b8d565b9150915081610d9a5761104f610c55565b610d09565b61105c612164565b565b6000611068611579565b905080600114156110795750611134565b61108382826121e8565b3360009081526013602090815260408083206001600160a01b038616845290915281208054600019840190915590600182015b838110156110d5576110c93386836116b3565b909101906001016110b6565b506040805182815290516001600160a01b0386169133917f9b64af6bc8380496b8d368590f1460af6043202bca9d05998fcee10cd105fd5c9181900360200190a36111306001600160a01b038516338363ffffffff6123ee16565b5050505b50565b600080600080600080600960000160199054906101000a900463ffffffff1663ffffffff1690506008878154811061116b57fe5b6000918252602080832083805260029283020190526040909120015460088054919650908890811061119957fe5b600091825260208083206002808552928302019052604090912001546008805491955090889081106111c757fe5b60009182526020808320600184526002928302019052604090912001546008805491945090889081106111f657fe5b60009182526020808320600384526002928302019052604090912001549150808710156112265760029550611248565b808714801561123e5750600954600160e81b900460ff165b1561124857600195505b5091939590929450565b6000610ba061125f611868565b84610d9185604051806060016040528060258152602001614a4d6025913960016000611289611868565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff611a9c16565b6000610ba06112cd611868565b8484611a91565b8280611315576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b8280611356576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b8561135f611958565b811161139d576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6113a5611958565b87116113e3576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000806113ee612440565b9092509050600061140982610ea58a8663ffffffff611c9016565b90508089116114255761142083838b8a600061245e565b611433565b61143383838a8a600161245e565b50505050505050505050565b6006546001600160801b031681565b6000611458611579565b90508060011415611469575061105c565b6114728161256e565b3360009081526014602052604081208054600019840190915590600182015b838110156114af576114a33382610e68565b90910190600101611491565b5060408051828152905133917fe3fdc68a57b01b663baef2bfbaa7da3ef2d8a090c25c00577be52fd50cc45859919081900360200190a2604051600090339083908381818185875af1925050503d8060008114611528576040519150601f19603f3d011682016040523d82523d6000602084013e61152d565b606091505b5050905080611130576040805162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015290519081900360640190fd5b6010546040805163624639a160e11b815290516000926001600160a01b03169163c48c7342916004808301926020929190829003018186803b1580156115be57600080fd5b505afa1580156115d2573d6000803e3d6000fd5b505050506040513d60208110156115e857600080fd5b5051905090565b6111348161274c565b60055461010090046001600160801b031681565b600080600080600080600061161f611958565b9650611629612440565b80965081975050506008878154811061163e57fe5b60009182526020909120600160029092020101546001600160801b03169250611665610c55565b93506116718685612760565b915061167d8585612760565b905090919293949596565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6000806116c08584610a39565b905060006116cd84610c5b565b905060006116db8686610efd565b90506116f182610ea5838663ffffffff611c9016565b979650505050505050565b818061173d576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b84611746611958565b8111611784576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000610c3f600085611962565b8361179a611958565b81116117d8576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6117e0611958565b851161181e576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b61182984848461277e565b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600090815260116020526040902054151590565b3390565b6001600160a01b0383166118b15760405162461bcd60e51b81526004018080602001828103825260248152602001806149ff6024913960400191505060405180910390fd5b6001600160a01b0382166118f65760405162461bcd60e51b81526004018080602001828103825260228152602001806148956022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6008546000190190565b6000821561198057811561197857506002610ba4565b506000610ba4565b811561198e57506003610ba4565b506001610ba4565b61199e6128c4565b60006119a8611958565b90506119b56005826128d9565b6001600160a01b0382166119c7573391505b6119e56119de8560038111156119d957fe5b612e02565b3385612e3d565b611a16848484600885815481106119f857fe5b9060005260206000209060020201612e63909392919063ffffffff16565b8063ffffffff16611a31856003811115611a2c57fe5b612f3f565b1515836001600160a01b03167fd54c711b2fd79474dc74606062c8605c0dac9e6089a74320ccf470dc2e33e19a611a72886003811115611a6d57fe5b612f6b565b604080519115158252602082018990528051918290030190a450505050565b610f4a838383612f7d565b60008184841115611b2b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611af0578181015183820152602001611ad8565b50505050905090810190601f168015611b1d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610d9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008060008411611bde576040805162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b604482015290519081900360640190fd5b611be8600f612f90565b841115611c3c576040805162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000604482015290519081900360640190fd5b6000611c4e848663ffffffff612f9416565b8454909150811415611c67575060009150819050611c89565b6001846001018281548110611c7857fe5b906000526020600020015492509250505b9250929050565b600082611c9f57506000610ba4565b82820282848281611cac57fe5b0414610d9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806149246021913960400191505060405180910390fd5b6000610d9a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613035565b6000828015611d375750815b15611d4457506002610ba4565b82610ba4578115610ba057506003610ba4565b6000806000611d64611958565b841115611d7957506000915081905080612090565b600060088581548110611d8857fe5b906000526020600020906002020190506060816000016000886003811115611dac57fe5b6003811115611db757fe5b6003811115611dc257fe5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611e2757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e09575b5050600954600b54600a54959650600160c81b90910463ffffffff16949093506000925060ff1690506003811115611e5b57fe5b600954909150600160e81b900460ff16600080805b87518114611eb9578e6001600160a01b0316888281518110611e8e57fe5b60200260200101516001600160a01b03161415611eb15760019250809150611eb9565b600101611e70565b50858c1080611eed5750828015611ecf5750858c145b8015611eed5750838d1080611eed5750838d148015611eed57508481105b15611f0b575060019950600098508897506120909650505050505050565b81611f285750600099508998508897506120909650505050505050565b6000868d148015611f365750835b1561203257845b8e81101561200357611ff78a6000836003811115611f5757fe5b6003811115611f6257fe5b6003811115611f6d57fe5b815260200190815260200160002060405180604001604052908160018201805480602002602001604051908101604052809291908181526020018280548015611fdf57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc1575b5050505050815260200160028201548152505061309a565b90910190600101611f3d565b5060019a506120288661201c838563ffffffff611b3316565b9063ffffffff61309f16565b6001019950612086565b60005b8e811461205a5761204e8a6000836003811115611f5757fe5b90910190600101612035565b5061206b8d8863ffffffff61309f16565b6001019a50612080818363ffffffff611b3316565b60010199505b5050505050505050505b93509350939050565b6120a1610c55565b156120e9576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461211e57600080fd5b61212883836130e1565b612132338261316c565b612147600033856001600160801b0316612e3d565b61215c600133846001600160801b0316612e3d565b610f4a613176565b60008061216f6131fd565b9150915061217e600080613219565b604080518381526020810183905281517f72715c0cf03be5e4479cb972219945b83aee28f65875993b1de62bda86892d1e929181900390910190a16121e47f0000000000000000000000000000000000000000000000000000000000000000838361325a565b5050565b60105460408051634665096d60e01b815290516000926001600160a01b031691634665096d916004808301926020929190829003018186803b15801561222d57600080fd5b505afa158015612241573d6000803e3d6000fd5b505050506040513d602081101561225757600080fd5b5051905060008082841115612270578284039150612275565b600191505b60001984015b82811061236d5760008181526012602090815260408083206001600160a01b038a168452909152902054156122af5761236d565b6010546040805163021e20ab60e61b81526001600160a01b03898116600483015230602483015260448201859052915160009392909216916387882ac091606480820192602092909190829003018186803b15801561230d57600080fd5b505afa158015612321573d6000803e3d6000fd5b505050506040513d602081101561233757600080fd5b505160008381526012602090815260408083206001600160a01b038c16845290915290208190559290920191506000190161227b565b508061237b575050506121e4565b6010546040805163125bdfc160e11b81526001600160a01b038881166004830152306024830152915191909216916324b7bf8291604480830192600092919082900301818387803b1580156123cf57600080fd5b505af11580156123e3573d6000803e3d6000fd5b505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610f4a90849061329a565b6006546007546001600160801b03600160801b909204821692911690565b600080600061246f8689898761334b565b925092509250848110156124ca576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f7567682073686172657300604482015290519081900360640190fd5b6124d660003385612e3d565b6124e260013384612e3d565b6125156124fd6124f88a8663ffffffff611b3316565b6133c2565b6125106124f88a8663ffffffff611b3316565b6130e1565b61251f338261316c565b6040805184815260208101849052808201839052905160019133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b60105460408051634665096d60e01b815290516000926001600160a01b031691634665096d916004808301926020929190829003018186803b1580156125b357600080fd5b505afa1580156125c7573d6000803e3d6000fd5b505050506040513d60208110156125dd57600080fd5b50519050600080828411156125f65782840391506125fb565b600191505b60001984015b8281106126ce5760008181526012602052604090206001015415612624576126ce565b6010546040805163021e20ab60e61b815260006004820181905230602483015260448201859052915191926001600160a01b0316916387882ac091606480820192602092909190829003018186803b15801561267f57600080fd5b505afa158015612693573d6000803e3d6000fd5b505050506040513d60208110156126a957600080fd5b5051600083815260126020526040902060010181905592909201915060001901612601565b50806126dc57505050611134565b6010546040805163125bdfc160e11b815260006004820181905230602483015291516001600160a01b03909316926324b7bf829260448084019391929182900301818387803b15801561272e57600080fd5b505af1158015612742573d6000803e3d6000fd5b5050505050505050565b6111348160ff1661275b611958565b6128d9565b6000610d9a82610ea585670de0b6b3a764000063ffffffff611c9016565b600080612789612440565b915091506000612797610c55565b905060006127af82610ea5868863ffffffff611c9016565b905060006127c783610ea5868963ffffffff611c9016565b90508782101580156127d95750868110155b61282a576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f75676820746f6b656e7300604482015290519081900360640190fd5b6128536128406124f8878563ffffffff61309f16565b6125106124f8878563ffffffff61309f16565b61285d338761340a565b61286960003384613414565b61287560013383613414565b6040805183815260208101839052808201889052905160009133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b6128cc613438565b1561105c5761105c613176565b6128e1614798565b6040805160a0810190915260098054829060ff16600381111561290057fe5b600381111561290b57fe5b81529054610100810467ffffffffffffffff166020830152600160481b81046001600160801b03166040830152600160c81b810463ffffffff166060830152600160e81b900460ff16151560809091015290506129666147c8565b60408051808201909152600a8054829060ff16600381111561298457fe5b600381111561298f57fe5b8152602001600182015481525050905082826060015163ffffffff16101580156129d157506129bc613438565b15806129d1575082826060015163ffffffff16115b156129dd5750506121e4565b8160800151612a605760008060006129f8856060015161347a565b9194509250905084836003811115612a0c57fe5b90816003811115612a1957fe5b905250612a25826135e3565b67ffffffffffffffff166020860152612a3d816133c2565b6001600160801b0316604086015250506001608084015250600080825260208201525b8315612d195760006008836060015163ffffffff1681548110612a7f57fe5b600091825260208220845160029092020191906003811115612a9d57fe5b6003811115612aa857fe5b815260200190815260200160002090506000806000612b3484612ad4876000015160038111156119d957fe5b60208801518851612aec908b9063ffffffff61362c16565b8a604001516001600160801b031660088c6060015163ffffffff1681548110612b1157fe5b60009182526020909120600160029092020101546001600160801b03168e6136f6565b9250925092508215612cf8576000612b746008886060015163ffffffff1681548110612b5c57fe5b9060005260206000209060020201876000015161382d565b90506008876060015163ffffffff1681548110612b8d57fe5b600091825260208220885160029092020191906003811115612bab57fe5b6003811115612bb657fe5b81526020019081526020016000206000600182016000612bd691906147df565b600282016000905550508015612cc35760608701805163ffffffff600191820116909152600060808901528751600980548a93919291839160ff191690836003811115612c1f57fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff0019909516949094179490941692909217169190911792909216919091179055506121e495505050505050565b8551612cd9906003811115612cd457fe5b613948565b86906003811115612ce657fe5b90816003811115612cf357fe5b905250505b612d018261396e565b63ffffffff1660208601529096039550612a60915050565b815160098054849290829060ff19166001836003811115612d3657fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff00199095169490941794909416929092171691909117929092169190911790558051600a8054839290829060ff19166001836003811115612dea57fe5b02179055506020820151816001015590505050505050565b600080826003811115612e1157fe5b1480612e2857506002826003811115612e2657fe5b145b15612e3557506000610ef8565b506001610ef8565b610f4a823083612e4c876139b3565b6001600160a01b031692919063ffffffff613a1616565b60008481856003811115612e7357fe5b6003811115612e7e57fe5b8152602080820192909252604090810160009081206001600160a01b0386168252928390522054909150612edc576001818101805491820181556000908152602090200180546001600160a01b0319166001600160a01b0384161790555b6001600160a01b038216600090815260208290526040902054612f05908463ffffffff611b3316565b6001600160a01b0383166000908152602083905260409020556002810154612f33908463ffffffff611b3316565b60029091015550505050565b600080826003811115612f4e57fe5b1480610ba4575060025b826003811115612f6457fe5b1492915050565b6000612f7682613a70565b1592915050565b612f85613a8d565b610f4a838383613ad6565b5490565b8154600090612fa557506000610ba4565b82546000905b80821015612ff4576000612fbf8383613af3565b905084868281548110612fce57fe5b90600052602060002001541115612fe757809150612fee565b8060010192505b50612fab565b60008211801561301c57508385600184038154811061300f57fe5b9060005260206000200154145b1561302d5750600019019050610ba4565b509050610ba4565b600081836130845760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611af0578181015183820152602001611ad8565b50600083858161309057fe5b0495945050505050565b515190565b6000610d9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611a9c565b600680546001600160801b03908116600160801b8583160217909155600780546001600160801b0319169183169190911790557f17226eb45b590dffadbc03fba4681aa4c198e7e838ab8a6fb7e32a51634b3e80828261313f610c55565b604080516001600160801b0394851681529290931660208301528183015290519081900360600190a15050565b6121e48282613b18565b61317e613b2a565b6000613188611958565b9050613193816133c2565b6001600160801b03167f5ab5824685efa3ca4a723a2f94da7d225628bfae130cc14663932a3bf11140a8600883815481106131ca57fe5b600091825260209182902060016002909202010154604080516001600160801b039092168252519081900390910190a250565b6005546006546001600160801b03610100909204821692911690565b6005805470ffffffffffffffffffffffffffffffff0019166101006001600160801b0394851602179055600680546001600160801b03191691909216179055565b8115610f4a57610f4a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016848463ffffffff6123ee16565b60606132ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613b9b9092919063ffffffff16565b805190915015610f4a5780806020019051602081101561330e57600080fd5b5051610f4a5760405162461bcd60e51b815260040180806020018281038252602a815260200180614a23602a913960400191505060405180910390fd5b600080808084600181111561335c57fe5b141561339e578661337787610ea5838963ffffffff611c9016565b61339388610ea5613386610c55565b8c9063ffffffff611c9016565b925092509250610edb565b6133b285610ea5898963ffffffff611c9016565b8761339387610ea5613386610c55565b6000600160801b82106134065760405162461bcd60e51b81526004018080602001828103825260278152602001806148dd6027913960400191505060405180910390fd5b5090565b6121e48282613baa565b610f4a8282613422866139b3565b6001600160a01b0316919063ffffffff6123ee16565b60006008613444611958565b8154811061344e57fe5b6000918252602090912060029091020160010154600160801b90046001600160801b0316431015919050565b60008060008060088563ffffffff168154811061349357fe5b6000918252602080832083805260029283020190819052604080842083015460018552818520840154848652828620850154600387529286209094015492955084938493919290916134e88885858585613bbc565b919d50929b509098509096509450866135045760029a50613548565b86600114156135165760029a50613548565b86600214156135285760009a50613548565b866003141561353a5760039a50613548565b86600414156135485760019a505b8b63ffffffff167f24f971a36bb1ccca6d5a24e46c30c46b44dc72fdf6b667edd669dee3585552a58c600381111561357c57fe5b6040805160ff9092168252602082018d90528181018e9052606082018890526080820187905260a0820186905260c08201859052519081900360e00190a260018801546135d4906001600160801b031687878c613c52565b50505050505050509193909250565b60006801000000000000000082106134065760405162461bcd60e51b81526004018080602001828103825260268152602001806149456026913960400191505060405180910390fd5b600061363d8260038111156119d957fe5b600181111561364857fe5b83516136599060038111156119d957fe5b600181111561366457fe5b1461367157506000610ba4565b825161368790600381111561368257fe5b613a70565b156136c45761369b82600381111561368257fe5b156136b55750602082015167ffffffffffffffff16610ba4565b50670de0b6b3a7640000610ba4565b6136d3826003811115611a6d57fe5b156136ed5750602082015167ffffffffffffffff16610ba4565b50600092915050565b600080600080600061377c8c60405180604001604052908160018201805480602002602001604051908101604052809291908181526020018280548015611fdf576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc1575050505050815260200160028201548152505061309a565b90508991505b858a830310156137fa578082106137a6575060019350600092508890039050613820565b60008c60010183815481106137b757fe5b60009182526020808320909101546001600160a01b0316808352908f90526040909120549091506137ee908d9083908d8d8d613d3f565b50600190910190613782565b808210613814575060019350600092508890039050613820565b50600093509150508681035b9750975097945050505050565b6000600382600381111561383d57fe5b141561384b57506001610ba4565b600061385c836003811115612cd457fe5b600381111561386757fe5b90505b80600414610d965761387a6147fd565b84600083600381111561388957fe5b600381111561389457fe5b600381111561389f57fe5b81526020019081526020016000206040518060400160405290816001820180548060200260200160405190810160405280929190818152602001828054801561391157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116138f3575b50505050508152602001600282015481525050905061392f8161309a565b1561393f57600092505050610ba4565b5060010161386a565b6000600482600381111561395857fe5b6001018161396257fe5b066003811115610ba457fe5b600064010000000082106134065760405162461bcd60e51b81526004018080602001828103825260268152602001806149d96026913960400191505060405180910390fd5b6000808260018111156139c257fe5b14156139ef57507f0000000000000000000000000000000000000000000000000000000000000000610ef8565b507f0000000000000000000000000000000000000000000000000000000000000000919050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261113090859061329a565b600080826003811115613a7f57fe5b1480610ba457506001612f58565b6000613a97611579565b9050600181118015613ab25750613ab060018203611854565b155b1561113457613abf613e36565b600019820160009081526011602052604090205550565b613adf83613e8a565b613ae882613e8a565b610f4a838383613eb4565b60006002808306600285060181613b0657fe5b04600283046002850401019392505050565b613b20613a8d565b6121e4828261401b565b6008613b4e613b37614036565b613b434360020161396e565b63ffffffff166140e4565b8154600180820184556000938452602093849020835160029093020101805492909301516001600160801b03199092166001600160801b03918216178116600160801b9190921602179055565b6060610e60848460008561410e565b613bb2613a8d565b6121e4828261427b565b600185015460009081908190819081906001600160801b0316670de0b6b3a764000001613c3b613bec8b83612760565b613bfc8a8463ffffffff61276016565b613c0c8c8563ffffffff61276016565b613c1c8b8663ffffffff61276016565b6006546007546001600160801b03600160801b90920482169116614296565b939f929e50909c509a509098509650505050505050565b600080600080600080613c698a8a8a8a60006143ad565b6006546005546001600160801b03600160801b90920482169093019850610100909204909116019350613ca4915089905087898860016143ad565b6007546001600160801b0316909101935090506000613d01670de0b6b3a7640000613cf5613ce8613cdb888763ffffffff611b3316565b899063ffffffff61276016565b859063ffffffff61441316565b9063ffffffff61276016565b948590039493820193929092019150613d25613d1c856133c2565b612510856133c2565b612742613d31836133c2565b6001600160801b0316614431565b6000613d55876001811115613d5057fe5b614463565b90506000613d69868663ffffffff61441316565b90506000613d98613d88670de0b6b3a76400008663ffffffff611b3316565b613cf5898563ffffffff61309f16565b90506000613da78a8388614488565b9050613db48a8a85613414565b613dbf848a83613414565b886001600160a01b0316613dd1611958565b63ffffffff1660008c6001811115613de557fe5b604080518d815260208101899052808201879052905192909114917fb8221d4e9feabcc28c5e0878f3196eecf38320725898780b22a503239b6bc9969181900360600190a450505050505050505050565b6000613e42600f6144c4565b6000613e4e600f612f90565b6040805182815290519192507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67919081900360200190a1905090565b6001600160a01b0381166000908152600c6020526040902061113490613eaf83610f24565b6144cd565b6001600160a01b038316613ef95760405162461bcd60e51b81526004018080602001828103825260258152602001806149b46025913960400191505060405180910390fd5b6001600160a01b038216613f3e5760405162461bcd60e51b81526004018080602001828103825260238152602001806148506023913960400191505060405180910390fd5b613f49838383610f4a565b613f8c816040518060600160405280602681526020016148b7602691396001600160a01b038616600090815260208190526040902054919063ffffffff611a9c16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613fc1908263ffffffff611b3316565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b61402482613e8a565b61402c614519565b6121e48282614526565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e66ed1a7f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b1580156140d057600080fd5b505af11580156115d2573d6000803e3d6000fd5b6140ec6147c8565b50604080518082019091526001600160801b0392831681529116602082015290565b606061411985614622565b61416a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106141a95780518252601f19909201916020918201910161418a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461420b576040519150601f19603f3d011682016040523d82523d6000602084013e614210565b606091505b50915091508115614224579150610e609050565b8051156142345780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315611af0578181015183820152602001611ad8565b61428482613e8a565b61428c614519565b6121e4828261465b565b60008060008060006142a6614817565b6040805163f5eeb35760e01b8152600481018e9052602481018d9052604481018c9052606481018b9052608481018a905260a4810189905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163f5eeb3579160c48083019260a0929190829003018186803b15801561433057600080fd5b505afa158015614344573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525060a081101561436957600080fd5b509050806000602002015181600160200201518260026020020151836003602002015184600460200201519550955095509550955050965096509650965096915050565b600080806143c1878963ffffffff61441316565b905060006143dd826702c68af0bb14000063ffffffff61441316565b905060006143fa6143f3876001811115613d5057fe5b8989614488565b9282900389019290920393509150509550959350505050565b6000610d9a670de0b6b3a7640000610ea5858563ffffffff611c9016565b61443a816133c2565b600560016101000a8154816001600160801b0302191690836001600160801b0316021790555050565b60008082600181111561447257fe5b141561448057506001610ef8565b506000610ef8565b60008084600181111561449757fe5b14156144b4576144ad838363ffffffff61441316565b9050610d9a565b6144ad838363ffffffff61276016565b80546001019055565b60006144d9600f612f90565b9050806144e584614763565b1015610f4a578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b61105c600d613eaf610c55565b6001600160a01b038216614581576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61458d60008383610f4a565b6002546145a0908263ffffffff611b3316565b6002556001600160a01b0382166000908152602081905260409020546145cc908263ffffffff611b3316565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610d09575050151592915050565b6001600160a01b0382166146a05760405162461bcd60e51b81526004018080602001828103825260218152602001806149936021913960400191505060405180910390fd5b6146ac82600083610f4a565b6146ef81604051806060016040528060228152602001614873602291396001600160a01b038516600090815260208190526040902054919063ffffffff611a9c16565b6001600160a01b03831660009081526020819052604090205560025461471b908263ffffffff61309f16565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b805460009061477457506000610ef8565b81548290600019810190811061478657fe5b90600052602060002001549050610ef8565b6040805160a081019091528060008152600060208201819052604082018190526060820181905260809091015290565b604080518082019091526000808252602082015290565b50805460008255906000526020600020908101906111349190614835565b604051806040016040528060608152602001600081525090565b6040518060a001604052806005906020820280368337509192915050565b610b8991905b80821115613406576000815560010161483b56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636553616665436173743a2076616c756520646f65736e27742066697420696e203132382062697473416d6f756e742073686f756c6420626520626967676572207468616e20300000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e203634206269747345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e203332206269747345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212203c590c87bd38dd085d6955877b99a555774bfae076e5428f7abd4b10ff0f724864736f6c634300060600330000000000000000000000007591a309df68bf43ba42dd11b0344220a260020a000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f53484152452d49444f4c2d4c49454e0000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102295760003560e01c806395d89b4111610123578063bb2f53b4116100ab578063dd62ed3e1161006f578063dd62ed3e14610923578063dec7bfd21461095e578063e1b4df2a146109a1578063f88bf15a146109e8578063fc0c546a14610a2457610230565b8063bb2f53b41461086a578063c48c73421461087f578063c9a01af914610894578063d5855e7a146108c1578063da84fb0b146108d657610230565b8063a3fee072116100f2578063a3fee07214610736578063a457c2d71461078b578063a9059cbb146107c4578063aebf3e41146107fd578063b196a3521461083957610230565b806395d89b41146106af578063981b24d0146106c45780639c558c4b146106ee578063a11bc81f1461070357610230565b806339509351116101b15780636d294d06116101755780636d294d06146105bc57806370a08231146105f55780637112ed021461062857806384c76abc1461065e57806392dea49c1461069a57610230565b8063395093511461047e5780634ee2cd7e146104b75780634fc0bf09146104f057806359e713141461052957806369cb06541461059257610230565b806318160ddd116101f857806318160ddd146103a05780631c67247c146103b557806323b872dd146103df578063313ce56714610422578063385a8d501461044d57610230565b8063068228591461023557806306fdde0314610280578063095ea7b31461030a5780630d96ad311461035757610230565b3661023057005b600080fd5b34801561024157600080fd5b5061026e6004803603604081101561025857600080fd5b506001600160a01b038135169060200135610a39565b60408051918252519081900360200190f35b34801561028c57600080fd5b50610295610af5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102cf5781810151838201526020016102b7565b50505050905090810190601f1680156102fc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561031657600080fd5b506103436004803603604081101561032d57600080fd5b506001600160a01b038135169060200135610b8c565b604080519115158252519081900360200190f35b34801561036357600080fd5b5061039e6004803603608081101561037a57600080fd5b508035906001600160a01b0360208201351690604081013590606001351515610baa565b005b3480156103ac57600080fd5b5061026e610c55565b3480156103c157600080fd5b5061026e600480360360208110156103d857600080fd5b5035610c5b565b3480156103eb57600080fd5b506103436004803603606081101561040257600080fd5b506001600160a01b03813581169160208101359091169060400135610d13565b34801561042e57600080fd5b50610437610da1565b6040805160ff9092168252519081900360200190f35b34801561045957600080fd5b50610462610daa565b604080516001600160a01b039092168252519081900360200190f35b34801561048a57600080fd5b50610343600480360360408110156104a157600080fd5b506001600160a01b038135169060200135610dce565b3480156104c357600080fd5b5061026e600480360360408110156104da57600080fd5b506001600160a01b038135169060200135610e22565b3480156104fc57600080fd5b5061026e6004803603604081101561051357600080fd5b506001600160a01b038135169060200135610e68565b34801561053557600080fd5b506105726004803603608081101561054c57600080fd5b506001600160a01b03813516906020810135906040810135151590606001351515610ebb565b604080519315158452602084019290925282820152519081900360600190f35b34801561059e57600080fd5b5061026e600480360360208110156105b557600080fd5b5035610ee5565b3480156105c857600080fd5b5061026e600480360360408110156105df57600080fd5b506001600160a01b038135169060200135610efd565b34801561060157600080fd5b5061026e6004803603602081101561061857600080fd5b50356001600160a01b0316610f24565b34801561063457600080fd5b5061039e6004803603606081101561064b57600080fd5b5080359060208101359060400135610f3f565b34801561066a57600080fd5b5061026e6004803603604081101561068157600080fd5b5080356001600160a01b0316906020013560ff16610f4f565b3480156106a657600080fd5b50610462610fbe565b3480156106bb57600080fd5b50610295610fcd565b3480156106d057600080fd5b5061026e600480360360208110156106e757600080fd5b503561102e565b3480156106fa57600080fd5b5061039e611054565b34801561070f57600080fd5b5061039e6004803603602081101561072657600080fd5b50356001600160a01b031661105e565b34801561074257600080fd5b506107606004803603602081101561075957600080fd5b5035611137565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b34801561079757600080fd5b50610343600480360360408110156107ae57600080fd5b506001600160a01b038135169060200135611252565b3480156107d057600080fd5b50610343600480360360408110156107e757600080fd5b506001600160a01b0381351690602001356112c0565b34801561080957600080fd5b5061039e6004803603608081101561082057600080fd5b50803590602081013590604081013590606001356112d4565b34801561084557600080fd5b5061084e61143f565b604080516001600160801b039092168252519081900360200190f35b34801561087657600080fd5b5061039e61144e565b34801561088b57600080fd5b5061026e611579565b3480156108a057600080fd5b5061039e600480360360208110156108b757600080fd5b503560ff166115ef565b3480156108cd57600080fd5b5061084e6115f8565b3480156108e257600080fd5b506108eb61160c565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561092f57600080fd5b5061026e6004803603604081101561094657600080fd5b506001600160a01b0381358116916020013516611688565b34801561096a57600080fd5b5061026e6004803603606081101561098157600080fd5b506001600160a01b038135811691602081013590911690604001356116b3565b3480156109ad57600080fd5b5061039e600480360360808110156109c457600080fd5b508035906001600160a01b03602082013516906040810135906060013515156116fc565b3480156109f457600080fd5b5061039e60048036036080811015610a0b57600080fd5b5080359060208101359060408101359060600135611791565b348015610a3057600080fd5b50610462611830565b60008160008111610a91576040805162461bcd60e51b815260206004820152601a60248201527f3020697320696e76616c69642076616c7565206173207465726d000000000000604482015290519081900360640190fd5b6000610a9b611579565b9050835b81811015610ae057610ab081611854565b15610ad857600081815260116020526040902054610acf908790610e22565b93505050610aee565b600101610a9f565b50610aea85610f24565b9250505b5092915050565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b815780601f10610b5657610100808354040283529160200191610b81565b820191906000526020600020905b815481529060010190602001808311610b6457829003601f168201915b505050505090505b90565b6000610ba0610b99611868565b848461186c565b5060015b92915050565b8180610beb576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b84610bf4611958565b8111610c32576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000610c3f600185611962565b9050610c4c818688611996565b50505050505050565b60025490565b60008160008111610cb3576040805162461bcd60e51b815260206004820152601a60248201527f3020697320696e76616c69642076616c7565206173207465726d000000000000604482015290519081900360640190fd5b6000610cbd611579565b9050835b81811015610d0057610cd281611854565b15610cf857600081815260116020526040902054610cef9061102e565b93505050610d0d565b600101610cc1565b50610d09610c55565b9250505b50919050565b6000610d20848484611a91565b610d9684610d2c611868565b610d918560405180606001604052806028815260200161496b602891396001600160a01b038a16600090815260016020526040812090610d6a611868565b6001600160a01b03168152602081019190915260400160002054919063ffffffff611a9c16565b61186c565b5060015b9392505050565b60055460ff1690565b7f0000000000000000000000007591a309df68bf43ba42dd11b0344220a260020a81565b6000610ba0610ddb611868565b84610d918560016000610dec611868565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff611b3316565b6001600160a01b0382166000908152600c6020526040812081908190610e49908590611b8d565b9150915081610e6057610e5b85610f24565b610aea565b949350505050565b600080610e758484610a39565b90506000610e8284610c5b565b90506000610e8f85610ee5565b9050610eb182610ea5838663ffffffff611c9016565b9063ffffffff611ce916565b9695505050505050565b6000806000610ed487610ece8787611d2b565b88611d57565b9250925092505b9450945094915050565b6000818152601260205260409020600101545b919050565b60009081526012602090815260408083206001600160a01b03949094168352929052205490565b6001600160a01b031660009081526020819052604090205490565b610f4a838383612099565b505050565b60006008610f5b611958565b81548110610f6557fe5b90600052602060002090600202016000016000836003811115610f8457fe5b6003811115610f8f57fe5b8152602080820192909252604090810160009081206001600160a01b0387168252909252902054905092915050565b6010546001600160a01b031681565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b815780601f10610b5657610100808354040283529160200191610b81565b600080600061103e84600d611b8d565b9150915081610d9a5761104f610c55565b610d09565b61105c612164565b565b6000611068611579565b905080600114156110795750611134565b61108382826121e8565b3360009081526013602090815260408083206001600160a01b038616845290915281208054600019840190915590600182015b838110156110d5576110c93386836116b3565b909101906001016110b6565b506040805182815290516001600160a01b0386169133917f9b64af6bc8380496b8d368590f1460af6043202bca9d05998fcee10cd105fd5c9181900360200190a36111306001600160a01b038516338363ffffffff6123ee16565b5050505b50565b600080600080600080600960000160199054906101000a900463ffffffff1663ffffffff1690506008878154811061116b57fe5b6000918252602080832083805260029283020190526040909120015460088054919650908890811061119957fe5b600091825260208083206002808552928302019052604090912001546008805491955090889081106111c757fe5b60009182526020808320600184526002928302019052604090912001546008805491945090889081106111f657fe5b60009182526020808320600384526002928302019052604090912001549150808710156112265760029550611248565b808714801561123e5750600954600160e81b900460ff165b1561124857600195505b5091939590929450565b6000610ba061125f611868565b84610d9185604051806060016040528060258152602001614a4d6025913960016000611289611868565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff611a9c16565b6000610ba06112cd611868565b8484611a91565b8280611315576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b8280611356576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b8561135f611958565b811161139d576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6113a5611958565b87116113e3576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000806113ee612440565b9092509050600061140982610ea58a8663ffffffff611c9016565b90508089116114255761142083838b8a600061245e565b611433565b61143383838a8a600161245e565b50505050505050505050565b6006546001600160801b031681565b6000611458611579565b90508060011415611469575061105c565b6114728161256e565b3360009081526014602052604081208054600019840190915590600182015b838110156114af576114a33382610e68565b90910190600101611491565b5060408051828152905133917fe3fdc68a57b01b663baef2bfbaa7da3ef2d8a090c25c00577be52fd50cc45859919081900360200190a2604051600090339083908381818185875af1925050503d8060008114611528576040519150601f19603f3d011682016040523d82523d6000602084013e61152d565b606091505b5050905080611130576040805162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015290519081900360640190fd5b6010546040805163624639a160e11b815290516000926001600160a01b03169163c48c7342916004808301926020929190829003018186803b1580156115be57600080fd5b505afa1580156115d2573d6000803e3d6000fd5b505050506040513d60208110156115e857600080fd5b5051905090565b6111348161274c565b60055461010090046001600160801b031681565b600080600080600080600061161f611958565b9650611629612440565b80965081975050506008878154811061163e57fe5b60009182526020909120600160029092020101546001600160801b03169250611665610c55565b93506116718685612760565b915061167d8585612760565b905090919293949596565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6000806116c08584610a39565b905060006116cd84610c5b565b905060006116db8686610efd565b90506116f182610ea5838663ffffffff611c9016565b979650505050505050565b818061173d576040805162461bcd60e51b815260206004820152601e6024820152600080516020614904833981519152604482015290519081900360640190fd5b84611746611958565b8111611784576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6000610c3f600085611962565b8361179a611958565b81116117d8576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b6117e0611958565b851161181e576040805162461bcd60e51b8152602060048201526008602482015267151a5b59481bdd5d60c21b604482015290519081900360640190fd5b61182984848461277e565b5050505050565b7f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e81565b600090815260116020526040902054151590565b3390565b6001600160a01b0383166118b15760405162461bcd60e51b81526004018080602001828103825260248152602001806149ff6024913960400191505060405180910390fd5b6001600160a01b0382166118f65760405162461bcd60e51b81526004018080602001828103825260228152602001806148956022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6008546000190190565b6000821561198057811561197857506002610ba4565b506000610ba4565b811561198e57506003610ba4565b506001610ba4565b61199e6128c4565b60006119a8611958565b90506119b56005826128d9565b6001600160a01b0382166119c7573391505b6119e56119de8560038111156119d957fe5b612e02565b3385612e3d565b611a16848484600885815481106119f857fe5b9060005260206000209060020201612e63909392919063ffffffff16565b8063ffffffff16611a31856003811115611a2c57fe5b612f3f565b1515836001600160a01b03167fd54c711b2fd79474dc74606062c8605c0dac9e6089a74320ccf470dc2e33e19a611a72886003811115611a6d57fe5b612f6b565b604080519115158252602082018990528051918290030190a450505050565b610f4a838383612f7d565b60008184841115611b2b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611af0578181015183820152602001611ad8565b50505050905090810190601f168015611b1d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610d9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008060008411611bde576040805162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b604482015290519081900360640190fd5b611be8600f612f90565b841115611c3c576040805162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000604482015290519081900360640190fd5b6000611c4e848663ffffffff612f9416565b8454909150811415611c67575060009150819050611c89565b6001846001018281548110611c7857fe5b906000526020600020015492509250505b9250929050565b600082611c9f57506000610ba4565b82820282848281611cac57fe5b0414610d9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806149246021913960400191505060405180910390fd5b6000610d9a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613035565b6000828015611d375750815b15611d4457506002610ba4565b82610ba4578115610ba057506003610ba4565b6000806000611d64611958565b841115611d7957506000915081905080612090565b600060088581548110611d8857fe5b906000526020600020906002020190506060816000016000886003811115611dac57fe5b6003811115611db757fe5b6003811115611dc257fe5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611e2757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611e09575b5050600954600b54600a54959650600160c81b90910463ffffffff16949093506000925060ff1690506003811115611e5b57fe5b600954909150600160e81b900460ff16600080805b87518114611eb9578e6001600160a01b0316888281518110611e8e57fe5b60200260200101516001600160a01b03161415611eb15760019250809150611eb9565b600101611e70565b50858c1080611eed5750828015611ecf5750858c145b8015611eed5750838d1080611eed5750838d148015611eed57508481105b15611f0b575060019950600098508897506120909650505050505050565b81611f285750600099508998508897506120909650505050505050565b6000868d148015611f365750835b1561203257845b8e81101561200357611ff78a6000836003811115611f5757fe5b6003811115611f6257fe5b6003811115611f6d57fe5b815260200190815260200160002060405180604001604052908160018201805480602002602001604051908101604052809291908181526020018280548015611fdf57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc1575b5050505050815260200160028201548152505061309a565b90910190600101611f3d565b5060019a506120288661201c838563ffffffff611b3316565b9063ffffffff61309f16565b6001019950612086565b60005b8e811461205a5761204e8a6000836003811115611f5757fe5b90910190600101612035565b5061206b8d8863ffffffff61309f16565b6001019a50612080818363ffffffff611b3316565b60010199505b5050505050505050505b93509350939050565b6120a1610c55565b156120e9576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b336001600160a01b037f00000000000000000000000039a5bbc3f5536d7a9f40acfcb34738ff29540f49161461211e57600080fd5b61212883836130e1565b612132338261316c565b612147600033856001600160801b0316612e3d565b61215c600133846001600160801b0316612e3d565b610f4a613176565b60008061216f6131fd565b9150915061217e600080613219565b604080518381526020810183905281517f72715c0cf03be5e4479cb972219945b83aee28f65875993b1de62bda86892d1e929181900390910190a16121e47f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e838361325a565b5050565b60105460408051634665096d60e01b815290516000926001600160a01b031691634665096d916004808301926020929190829003018186803b15801561222d57600080fd5b505afa158015612241573d6000803e3d6000fd5b505050506040513d602081101561225757600080fd5b5051905060008082841115612270578284039150612275565b600191505b60001984015b82811061236d5760008181526012602090815260408083206001600160a01b038a168452909152902054156122af5761236d565b6010546040805163021e20ab60e61b81526001600160a01b03898116600483015230602483015260448201859052915160009392909216916387882ac091606480820192602092909190829003018186803b15801561230d57600080fd5b505afa158015612321573d6000803e3d6000fd5b505050506040513d602081101561233757600080fd5b505160008381526012602090815260408083206001600160a01b038c16845290915290208190559290920191506000190161227b565b508061237b575050506121e4565b6010546040805163125bdfc160e11b81526001600160a01b038881166004830152306024830152915191909216916324b7bf8291604480830192600092919082900301818387803b1580156123cf57600080fd5b505af11580156123e3573d6000803e3d6000fd5b505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610f4a90849061329a565b6006546007546001600160801b03600160801b909204821692911690565b600080600061246f8689898761334b565b925092509250848110156124ca576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f7567682073686172657300604482015290519081900360640190fd5b6124d660003385612e3d565b6124e260013384612e3d565b6125156124fd6124f88a8663ffffffff611b3316565b6133c2565b6125106124f88a8663ffffffff611b3316565b6130e1565b61251f338261316c565b6040805184815260208101849052808201839052905160019133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b60105460408051634665096d60e01b815290516000926001600160a01b031691634665096d916004808301926020929190829003018186803b1580156125b357600080fd5b505afa1580156125c7573d6000803e3d6000fd5b505050506040513d60208110156125dd57600080fd5b50519050600080828411156125f65782840391506125fb565b600191505b60001984015b8281106126ce5760008181526012602052604090206001015415612624576126ce565b6010546040805163021e20ab60e61b815260006004820181905230602483015260448201859052915191926001600160a01b0316916387882ac091606480820192602092909190829003018186803b15801561267f57600080fd5b505afa158015612693573d6000803e3d6000fd5b505050506040513d60208110156126a957600080fd5b5051600083815260126020526040902060010181905592909201915060001901612601565b50806126dc57505050611134565b6010546040805163125bdfc160e11b815260006004820181905230602483015291516001600160a01b03909316926324b7bf829260448084019391929182900301818387803b15801561272e57600080fd5b505af1158015612742573d6000803e3d6000fd5b5050505050505050565b6111348160ff1661275b611958565b6128d9565b6000610d9a82610ea585670de0b6b3a764000063ffffffff611c9016565b600080612789612440565b915091506000612797610c55565b905060006127af82610ea5868863ffffffff611c9016565b905060006127c783610ea5868963ffffffff611c9016565b90508782101580156127d95750868110155b61282a576040805162461bcd60e51b815260206004820152601f60248201527f596f752063616e2774207265636569766520656e6f75676820746f6b656e7300604482015290519081900360640190fd5b6128536128406124f8878563ffffffff61309f16565b6125106124f8878563ffffffff61309f16565b61285d338761340a565b61286960003384613414565b61287560013383613414565b6040805183815260208101839052808201889052905160009133917ff13afa8e6af2cf800415b27d44406182e9ea706876b2470dac00aff3def8161c9181900360600190a35050505050505050565b6128cc613438565b1561105c5761105c613176565b6128e1614798565b6040805160a0810190915260098054829060ff16600381111561290057fe5b600381111561290b57fe5b81529054610100810467ffffffffffffffff166020830152600160481b81046001600160801b03166040830152600160c81b810463ffffffff166060830152600160e81b900460ff16151560809091015290506129666147c8565b60408051808201909152600a8054829060ff16600381111561298457fe5b600381111561298f57fe5b8152602001600182015481525050905082826060015163ffffffff16101580156129d157506129bc613438565b15806129d1575082826060015163ffffffff16115b156129dd5750506121e4565b8160800151612a605760008060006129f8856060015161347a565b9194509250905084836003811115612a0c57fe5b90816003811115612a1957fe5b905250612a25826135e3565b67ffffffffffffffff166020860152612a3d816133c2565b6001600160801b0316604086015250506001608084015250600080825260208201525b8315612d195760006008836060015163ffffffff1681548110612a7f57fe5b600091825260208220845160029092020191906003811115612a9d57fe5b6003811115612aa857fe5b815260200190815260200160002090506000806000612b3484612ad4876000015160038111156119d957fe5b60208801518851612aec908b9063ffffffff61362c16565b8a604001516001600160801b031660088c6060015163ffffffff1681548110612b1157fe5b60009182526020909120600160029092020101546001600160801b03168e6136f6565b9250925092508215612cf8576000612b746008886060015163ffffffff1681548110612b5c57fe5b9060005260206000209060020201876000015161382d565b90506008876060015163ffffffff1681548110612b8d57fe5b600091825260208220885160029092020191906003811115612bab57fe5b6003811115612bb657fe5b81526020019081526020016000206000600182016000612bd691906147df565b600282016000905550508015612cc35760608701805163ffffffff600191820116909152600060808901528751600980548a93919291839160ff191690836003811115612c1f57fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff0019909516949094179490941692909217169190911792909216919091179055506121e495505050505050565b8551612cd9906003811115612cd457fe5b613948565b86906003811115612ce657fe5b90816003811115612cf357fe5b905250505b612d018261396e565b63ffffffff1660208601529096039550612a60915050565b815160098054849290829060ff19166001836003811115612d3657fe5b021790555060208201518154604084015160608501516080909501511515600160e81b0260ff60e81b1963ffffffff909616600160c81b0263ffffffff60c81b196001600160801b03909316600160481b02600160481b600160c81b031967ffffffffffffffff9096166101000268ffffffffffffffff00199095169490941794909416929092171691909117929092169190911790558051600a8054839290829060ff19166001836003811115612dea57fe5b02179055506020820151816001015590505050505050565b600080826003811115612e1157fe5b1480612e2857506002826003811115612e2657fe5b145b15612e3557506000610ef8565b506001610ef8565b610f4a823083612e4c876139b3565b6001600160a01b031692919063ffffffff613a1616565b60008481856003811115612e7357fe5b6003811115612e7e57fe5b8152602080820192909252604090810160009081206001600160a01b0386168252928390522054909150612edc576001818101805491820181556000908152602090200180546001600160a01b0319166001600160a01b0384161790555b6001600160a01b038216600090815260208290526040902054612f05908463ffffffff611b3316565b6001600160a01b0383166000908152602083905260409020556002810154612f33908463ffffffff611b3316565b60029091015550505050565b600080826003811115612f4e57fe5b1480610ba4575060025b826003811115612f6457fe5b1492915050565b6000612f7682613a70565b1592915050565b612f85613a8d565b610f4a838383613ad6565b5490565b8154600090612fa557506000610ba4565b82546000905b80821015612ff4576000612fbf8383613af3565b905084868281548110612fce57fe5b90600052602060002001541115612fe757809150612fee565b8060010192505b50612fab565b60008211801561301c57508385600184038154811061300f57fe5b9060005260206000200154145b1561302d5750600019019050610ba4565b509050610ba4565b600081836130845760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611af0578181015183820152602001611ad8565b50600083858161309057fe5b0495945050505050565b515190565b6000610d9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611a9c565b600680546001600160801b03908116600160801b8583160217909155600780546001600160801b0319169183169190911790557f17226eb45b590dffadbc03fba4681aa4c198e7e838ab8a6fb7e32a51634b3e80828261313f610c55565b604080516001600160801b0394851681529290931660208301528183015290519081900360600190a15050565b6121e48282613b18565b61317e613b2a565b6000613188611958565b9050613193816133c2565b6001600160801b03167f5ab5824685efa3ca4a723a2f94da7d225628bfae130cc14663932a3bf11140a8600883815481106131ca57fe5b600091825260209182902060016002909202010154604080516001600160801b039092168252519081900390910190a250565b6005546006546001600160801b03610100909204821692911690565b6005805470ffffffffffffffffffffffffffffffff0019166101006001600160801b0394851602179055600680546001600160801b03191691909216179055565b8115610f4a57610f4a6001600160a01b037f0000000000000000000000007591a309df68bf43ba42dd11b0344220a260020a16848463ffffffff6123ee16565b60606132ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613b9b9092919063ffffffff16565b805190915015610f4a5780806020019051602081101561330e57600080fd5b5051610f4a5760405162461bcd60e51b815260040180806020018281038252602a815260200180614a23602a913960400191505060405180910390fd5b600080808084600181111561335c57fe5b141561339e578661337787610ea5838963ffffffff611c9016565b61339388610ea5613386610c55565b8c9063ffffffff611c9016565b925092509250610edb565b6133b285610ea5898963ffffffff611c9016565b8761339387610ea5613386610c55565b6000600160801b82106134065760405162461bcd60e51b81526004018080602001828103825260278152602001806148dd6027913960400191505060405180910390fd5b5090565b6121e48282613baa565b610f4a8282613422866139b3565b6001600160a01b0316919063ffffffff6123ee16565b60006008613444611958565b8154811061344e57fe5b6000918252602090912060029091020160010154600160801b90046001600160801b0316431015919050565b60008060008060088563ffffffff168154811061349357fe5b6000918252602080832083805260029283020190819052604080842083015460018552818520840154848652828620850154600387529286209094015492955084938493919290916134e88885858585613bbc565b919d50929b509098509096509450866135045760029a50613548565b86600114156135165760029a50613548565b86600214156135285760009a50613548565b866003141561353a5760039a50613548565b86600414156135485760019a505b8b63ffffffff167f24f971a36bb1ccca6d5a24e46c30c46b44dc72fdf6b667edd669dee3585552a58c600381111561357c57fe5b6040805160ff9092168252602082018d90528181018e9052606082018890526080820187905260a0820186905260c08201859052519081900360e00190a260018801546135d4906001600160801b031687878c613c52565b50505050505050509193909250565b60006801000000000000000082106134065760405162461bcd60e51b81526004018080602001828103825260268152602001806149456026913960400191505060405180910390fd5b600061363d8260038111156119d957fe5b600181111561364857fe5b83516136599060038111156119d957fe5b600181111561366457fe5b1461367157506000610ba4565b825161368790600381111561368257fe5b613a70565b156136c45761369b82600381111561368257fe5b156136b55750602082015167ffffffffffffffff16610ba4565b50670de0b6b3a7640000610ba4565b6136d3826003811115611a6d57fe5b156136ed5750602082015167ffffffffffffffff16610ba4565b50600092915050565b600080600080600061377c8c60405180604001604052908160018201805480602002602001604051908101604052809291908181526020018280548015611fdf576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc1575050505050815260200160028201548152505061309a565b90508991505b858a830310156137fa578082106137a6575060019350600092508890039050613820565b60008c60010183815481106137b757fe5b60009182526020808320909101546001600160a01b0316808352908f90526040909120549091506137ee908d9083908d8d8d613d3f565b50600190910190613782565b808210613814575060019350600092508890039050613820565b50600093509150508681035b9750975097945050505050565b6000600382600381111561383d57fe5b141561384b57506001610ba4565b600061385c836003811115612cd457fe5b600381111561386757fe5b90505b80600414610d965761387a6147fd565b84600083600381111561388957fe5b600381111561389457fe5b600381111561389f57fe5b81526020019081526020016000206040518060400160405290816001820180548060200260200160405190810160405280929190818152602001828054801561391157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116138f3575b50505050508152602001600282015481525050905061392f8161309a565b1561393f57600092505050610ba4565b5060010161386a565b6000600482600381111561395857fe5b6001018161396257fe5b066003811115610ba457fe5b600064010000000082106134065760405162461bcd60e51b81526004018080602001828103825260268152602001806149d96026913960400191505060405180910390fd5b6000808260018111156139c257fe5b14156139ef57507f0000000000000000000000007591a309df68bf43ba42dd11b0344220a260020a610ef8565b507f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e919050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261113090859061329a565b600080826003811115613a7f57fe5b1480610ba457506001612f58565b6000613a97611579565b9050600181118015613ab25750613ab060018203611854565b155b1561113457613abf613e36565b600019820160009081526011602052604090205550565b613adf83613e8a565b613ae882613e8a565b610f4a838383613eb4565b60006002808306600285060181613b0657fe5b04600283046002850401019392505050565b613b20613a8d565b6121e4828261401b565b6008613b4e613b37614036565b613b434360020161396e565b63ffffffff166140e4565b8154600180820184556000938452602093849020835160029093020101805492909301516001600160801b03199092166001600160801b03918216178116600160801b9190921602179055565b6060610e60848460008561410e565b613bb2613a8d565b6121e4828261427b565b600185015460009081908190819081906001600160801b0316670de0b6b3a764000001613c3b613bec8b83612760565b613bfc8a8463ffffffff61276016565b613c0c8c8563ffffffff61276016565b613c1c8b8663ffffffff61276016565b6006546007546001600160801b03600160801b90920482169116614296565b939f929e50909c509a509098509650505050505050565b600080600080600080613c698a8a8a8a60006143ad565b6006546005546001600160801b03600160801b90920482169093019850610100909204909116019350613ca4915089905087898860016143ad565b6007546001600160801b0316909101935090506000613d01670de0b6b3a7640000613cf5613ce8613cdb888763ffffffff611b3316565b899063ffffffff61276016565b859063ffffffff61441316565b9063ffffffff61276016565b948590039493820193929092019150613d25613d1c856133c2565b612510856133c2565b612742613d31836133c2565b6001600160801b0316614431565b6000613d55876001811115613d5057fe5b614463565b90506000613d69868663ffffffff61441316565b90506000613d98613d88670de0b6b3a76400008663ffffffff611b3316565b613cf5898563ffffffff61309f16565b90506000613da78a8388614488565b9050613db48a8a85613414565b613dbf848a83613414565b886001600160a01b0316613dd1611958565b63ffffffff1660008c6001811115613de557fe5b604080518d815260208101899052808201879052905192909114917fb8221d4e9feabcc28c5e0878f3196eecf38320725898780b22a503239b6bc9969181900360600190a450505050505050505050565b6000613e42600f6144c4565b6000613e4e600f612f90565b6040805182815290519192507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67919081900360200190a1905090565b6001600160a01b0381166000908152600c6020526040902061113490613eaf83610f24565b6144cd565b6001600160a01b038316613ef95760405162461bcd60e51b81526004018080602001828103825260258152602001806149b46025913960400191505060405180910390fd5b6001600160a01b038216613f3e5760405162461bcd60e51b81526004018080602001828103825260238152602001806148506023913960400191505060405180910390fd5b613f49838383610f4a565b613f8c816040518060600160405280602681526020016148b7602691396001600160a01b038616600090815260208190526040902054919063ffffffff611a9c16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613fc1908263ffffffff611b3316565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b61402482613e8a565b61402c614519565b6121e48282614526565b60007f000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf6001600160a01b0316632e66ed1a7f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b1580156140d057600080fd5b505af11580156115d2573d6000803e3d6000fd5b6140ec6147c8565b50604080518082019091526001600160801b0392831681529116602082015290565b606061411985614622565b61416a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106141a95780518252601f19909201916020918201910161418a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461420b576040519150601f19603f3d011682016040523d82523d6000602084013e614210565b606091505b50915091508115614224579150610e609050565b8051156142345780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315611af0578181015183820152602001611ad8565b61428482613e8a565b61428c614519565b6121e4828261465b565b60008060008060006142a6614817565b6040805163f5eeb35760e01b8152600481018e9052602481018d9052604481018c9052606481018b9052608481018a905260a4810189905290516001600160a01b037f000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d169163f5eeb3579160c48083019260a0929190829003018186803b15801561433057600080fd5b505afa158015614344573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525060a081101561436957600080fd5b509050806000602002015181600160200201518260026020020151836003602002015184600460200201519550955095509550955050965096509650965096915050565b600080806143c1878963ffffffff61441316565b905060006143dd826702c68af0bb14000063ffffffff61441316565b905060006143fa6143f3876001811115613d5057fe5b8989614488565b9282900389019290920393509150509550959350505050565b6000610d9a670de0b6b3a7640000610ea5858563ffffffff611c9016565b61443a816133c2565b600560016101000a8154816001600160801b0302191690836001600160801b0316021790555050565b60008082600181111561447257fe5b141561448057506001610ef8565b506000610ef8565b60008084600181111561449757fe5b14156144b4576144ad838363ffffffff61441316565b9050610d9a565b6144ad838363ffffffff61276016565b80546001019055565b60006144d9600f612f90565b9050806144e584614763565b1015610f4a578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b61105c600d613eaf610c55565b6001600160a01b038216614581576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61458d60008383610f4a565b6002546145a0908263ffffffff611b3316565b6002556001600160a01b0382166000908152602081905260409020546145cc908263ffffffff611b3316565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610d09575050151592915050565b6001600160a01b0382166146a05760405162461bcd60e51b81526004018080602001828103825260218152602001806149936021913960400191505060405180910390fd5b6146ac82600083610f4a565b6146ef81604051806060016040528060228152602001614873602291396001600160a01b038516600090815260208190526040902054919063ffffffff611a9c16565b6001600160a01b03831660009081526020819052604090205560025461471b908263ffffffff61309f16565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b805460009061477457506000610ef8565b81548290600019810190811061478657fe5b90600052602060002001549050610ef8565b6040805160a081019091528060008152600060208201819052604082018190526060820181905260809091015290565b604080518082019091526000808252602082015290565b50805460008255906000526020600020908101906111349190614835565b604051806040016040528060608152602001600081525090565b6040518060a001604052806005906020820280368337509192915050565b610b8991905b80821115613406576000815560010161483b56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636553616665436173743a2076616c756520646f65736e27742066697420696e203132382062697473416d6f756e742073686f756c6420626520626967676572207468616e20300000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e203634206269747345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e203332206269747345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212203c590c87bd38dd085d6955877b99a555774bfae076e5428f7abd4b10ff0f724864736f6c63430006060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007591a309df68bf43ba42dd11b0344220a260020a000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f53484152452d49444f4c2d4c49454e0000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _idol (address): 0x7591a309Df68bf43ba42dD11b0344220A260020A
Arg [1] : _priceCalc (address): 0xE9aa04b8D955fD291d44C9fDb8eB1227850b3e2d
Arg [2] : _lien (address): 0xaB37e1358b639Fd877f015027Bb62d3ddAa7557E
Arg [3] : _spreadCalc (address): 0xC05CB1999aB97A9ae5337fBdC4cb0e1458bc5CbF
Arg [4] : _name (string): SHARE-IDOL-LIEN
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000007591a309df68bf43ba42dd11b0344220a260020a
Arg [1] : 000000000000000000000000e9aa04b8d955fd291d44c9fdb8eb1227850b3e2d
Arg [2] : 000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e
Arg [3] : 000000000000000000000000c05cb1999ab97a9ae5337fbdc4cb0e1458bc5cbf
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [6] : 53484152452d49444f4c2d4c49454e0000000000000000000000000000000000
Deployed Bytecode Sourcemap
112231:1446:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;107899:441:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;107899:441:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;107899:441:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;17757:83;;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;:::-;;;;;;;;;;;;;;;;;;80746:319;;5:9:-1;2:2;;;27:1;24;17:12;2:2;80746:319:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;80746:319:0;;;-1:-1:-1;;;;;80746:319:0;;;;;;;;;;;;;;;;;:::i;:::-;;18832:100;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18832:100:0;;;:::i;108471:414::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;108471:414:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;108471:414: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;:::-;;;;;;;;;;;;;;;;;;;78487:36;;5:9:-1;2:2;;;27:1;24;17:12;2:2;78487:36:0;;;:::i;:::-;;;;-1:-1:-1;;;;;78487:36:0;;;;;;;;;;;;;;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;98111:258::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;98111:258:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;98111:258:0;;;;;;;;:::i;106667:401::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;106667:401:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;106667:401:0;;;;;;;;:::i;42915:396::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;42915:396:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;42915:396:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107598:124;;5:9:-1;2:2;;;27:1;24;17:12;2:2;107598:124:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;107598:124:0;;:::i;107262:190::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;107262:190:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;107262:190: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;79830:285::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79830:285:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;79830:285:0;;;;;;;;;;;;:::i;46376:253::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;46376:253:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;46376:253:0;;-1:-1:-1;;;;;46376:253:0;;;;;;;;:::i;102990:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;102990:30:0;;;:::i;17959:87::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17959:87:0;;;:::i;98473:225::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;98473:225:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;98473:225:0;;:::i;84692:81::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84692:81:0;;;:::i;104035:706::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;104035:706:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;104035:706:0;-1:-1:-1;;;;;104035:706:0;;:::i;44767:1397::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;44767:1397:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;44767: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;82491:1021::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;82491:1021:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;82491:1021:0;;;;;;;;;;;;;;;;;:::i;39509:29::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;39509:29:0;;;:::i;:::-;;;;-1:-1:-1;;;;;39509:29:0;;;;;;;;;;;;;;104926:753;;5:9:-1;2:2;;;27:1;24;17:12;2:2;104926:753:0;;;:::i;105754:97::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;105754:97:0;;;:::i;84507:111::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84507:111:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;84507:111:0;;;;:::i;39443:29::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;39443:29:0;;;:::i;43835:697::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;43835: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;106065:436::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;106065:436:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;106065:436:0;;;;;;;;;;;;;;;;;:::i;81706:353::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81706:353:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;81706:353:0;;;-1:-1:-1;;;;;81706:353:0;;;;;;;;;;;;;;;;;:::i;84033:332::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84033:332:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;84033:332:0;;;;;;;;;;;;;;;;;:::i;78540:37::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;78540:37:0;;;:::i;107899:441::-;108036:7;108012:4;103601:1;103593:5;:9;103585:48;;;;;-1:-1:-1;;;103585:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;108061:20:::1;108084:13;:11;:13::i;:::-;108061:36:::0;-1:-1:-1;108125:4:0;108108:189:::1;108135:12;108131:1;:16;108108:189;;;108173:26;108197:1;108173:23;:26::i;:::-;108169:117;;;108248:21;::::0;;;:18:::1;:21;::::0;;;;;108227:43:::1;::::0;108239:7;;108227:11:::1;:43::i;:::-;108220:50;;;;;;108169:117;108149:3;;108108:189;;;;108314:18;108324:7;108314:9;:18::i;:::-;108307:25;;;103644:1;107899:441:::0;;;;;:::o;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;80746:319::-;80912:10;41639:11;41631:54;;;;;-1:-1:-1;;;41631:54:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41631:54:0;;;;;;;;;;;;;;;80933:7:::1;41777:19;:17;:19::i;:::-;41767:7;:29;41759:50;;;::::0;;-1:-1:-1;;;41759:50:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;41759:50:0;;;;;;;;;;;;;::::1;;80953:19:::2;80975:28;80989:4;80995:7;80975:13;:28::i;:::-;80953:50;;81014:43;81024:9;81035:10;81047:9;81014;:43::i;:::-;41820:1;41696::::1;80746:319:::0;;;;;:::o;18832:100::-;18912:12;;18832:100;:::o;108471:414::-;108593:7;108569:4;103601:1;103593:5;:9;103585:48;;;;;-1:-1:-1;;;103585:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;108618:20:::1;108641:13;:11;:13::i;:::-;108618:36:::0;-1:-1:-1;108682:4:0;108665:182:::1;108692:12;108688:1;:16;108665:182;;;108730:26;108754:1;108730:23;:26::i;:::-;108726:110;;;108798:21;::::0;;;:18:::1;:21;::::0;;;;;108784:36:::1;::::0;:13:::1;:36::i;:::-;108777:43;;;;;;108726:110;108706:3;;108665:182;;;;108864:13;:11;:13::i;:::-;108857:20;;;103644:1;108471:414:::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;78487:36::-;;;:::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;98111:258::-;-1:-1:-1;;;;;98267:33:0;;98190:7;98267:33;;;:24;:33;;;;;98190:7;;;;98246:55;;98255:10;;98246:8;:55::i;:::-;98210:91;;;;98321:11;:40;;98343:18;98353:7;98343:9;:18::i;:::-;98321:40;;;98335:5;98111:258;-1:-1:-1;;;;98111:258:0:o;106667:401::-;106769:7;106794:24;106821:33;106840:7;106849:4;106821:18;:33::i;:::-;106794:60;;106865:28;106896:26;106917:4;106896:20;:26::i;:::-;106865:57;;106933:21;106957:24;106976:4;106957:18;:24::i;:::-;106933:48;-1:-1:-1;106999:61:0;107039:20;106999:35;106933:48;107017:16;106999:35;:17;:35;:::i;:::-;:39;:61;:39;:61;:::i;:::-;106992:68;106667:401;-1:-1:-1;;;;;;106667:401:0:o;42915:396::-;43109:15;43139:16;43170:18;43236:67;43251:9;43262:29;43276:5;43283:7;43262:13;:29::i;:::-;43293:9;43236:14;:67::i;:::-;43216:87;;;;;;42915:396;;;;;;;;;:::o;107598:124::-;107661:7;107688:22;;;:16;:22;;;;;:26;;;107598:124;;;;:::o;107262:190::-;107376:7;107408:22;;;:16;:22;;;;;;;;-1:-1:-1;;;;;107408:36:0;;;;;;;;;;;;107262:190::o;18995:119::-;-1:-1:-1;;;;;19088:18:0;19061:7;19088:18;;;;;;;;;;;;18995:119::o;79830:285::-;79985:122;80013:10;80047:21;80084:12;79985:5;:122::i;:::-;79830:285;;;:::o;46376:253::-;46486:7;46531:10;46542:19;:17;:19::i;:::-;46531:31;;;;;;;;;;;;;;;;;;:42;;:53;46574:9;46531:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46531:53:0;;;-1:-1:-1;;;;;46531:90:0;;;;;;;;;;;-1:-1:-1;46376:253:0;;;;:::o;102990:30::-;;;-1:-1:-1;;;;;102990:30: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;;;;;;;;;;;;;;;;;;;;;;;;98473:225;98536:7;98557:16;98575:13;98592:43;98601:10;98613:21;98592:8;:43::i;:::-;98556:79;;;;98655:11;:35;;98677:13;:11;:13::i;:::-;98655:35;;84692:81;84743:22;:20;:22::i;:::-;84692:81::o;104035:706::-;104105:20;104128:13;:11;:13::i;:::-;104105:36;;104156:12;104172:1;104156:17;104152:56;;;104190:7;;;104152:56;104218:47;104245:5;104252:12;104218:26;:47::i;:::-;104329:10;104276:24;104303:37;;;:25;:37;;;;;;;;-1:-1:-1;;;;;104303:44:0;;;;;;;;;;;-1:-1:-1;;104405:16:0;;104358:63;;;104303:44;-1:-1:-1;104479:20:0;;104459:150;104508:12;104501:4;:19;104459:150;;;104557:40;104573:10;104585:5;104592:4;104557:15;:40::i;:::-;104545:52;;;;104522:6;;104459:150;;;-1:-1:-1;104624:58:0;;;;;;;;-1:-1:-1;;;;;104624:58:0;;;104645:10;;104624:58;;;;;;;;;104693:40;-1:-1:-1;;;;;104693:18:0;;104712:10;104724:8;104693:40;:18;:40;:::i;:::-;104035:706;;;;;:::o;44767:1397::-;44871:29;44915:26;44956:28;44999:26;45040:28;45340:26;45369:18;:28;;;;;;;;;;;;45340:57;;;;45429:10;45440:9;45429:21;;;;;;;;;;;;;;;;:66;;;:21;;;;;:66;;;;;;:94;;45557:10;:21;;45429:94;;-1:-1:-1;45557:10:0;45568:9;;45557:21;;;;;;;;;;;;;;;:68;;;:21;;;;:68;;;;;;:96;;45685:10;:21;;45557:96;;-1:-1:-1;45685:10:0;45696:9;;45685:21;;;;;;;;;;;;;;45718:32;45685:66;;:21;;;;;:66;;;;;;:94;;45813:10;:21;;45685:94;;-1:-1:-1;45813:10:0;45824:9;;45813:21;;;;;;;;;;;;;;45846:34;45813:68;;:21;;;;;:68;;;;;;:96;;;-1:-1:-1;45924:30:0;;;45920:237;;;45995:1;45971:25;;45920:237;;;46045:18;46032:9;:31;:61;;;;-1:-1:-1;46067:18:0;:26;-1:-1:-1;;;46067:26:0;;;;46032:61;46014:143;;;46144:1;46120:25;;46014:143;44767: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;82491:1021::-;82683:10;41639:11;41631:54;;;;;-1:-1:-1;;;41631:54:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41631:54:0;;;;;;;;;;;;;;;82717:21;41639:11;41631:54:::1;;;::::0;;-1:-1:-1;;;41631:54:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;41631:54:0;;;;;;;;;;;;;::::1;;82758:7:::2;41777:19;:17;:19::i;:::-;41767:7;:29;41759:50;;;::::0;;-1:-1:-1;;;41759:50:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;41759:50:0;;;;;;;;;;;;;::::2;;82801:19:::3;:17;:19::i;:::-;82791:7;:29;82783:50;;;::::0;;-1:-1:-1;;;82783:50:0;;::::3;;::::0;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;82783:50:0;;;;;;;;;;;;;::::3;;82845:17;82864::::0;82885:14:::3;:12;:14::i;:::-;82844:55:::0;;-1:-1:-1;82844:55:0;-1:-1:-1;82925:30:0::3;82958:79;82844:55:::0;82958:50:::3;:21:::0;82844:55;82958:50:::3;:39;:50;:::i;:79::-;82925:112;;83066:22;83052:10;:36;83048:457;;83105:172;83137:9;83165;83193:10;83222:9;83250:12;83105:13;:172::i;:::-;83048:457;;;83310:183;83342:9;83370;83398:21;83438:9;83466:12;83310:13;:183::i;:::-;41820:1;;;41696::::2;::::1;82491:1021:::0;;;;;:::o;39509:29::-;;;-1:-1:-1;;;;;39509:29:0;;:::o;104926:753::-;104974:20;104997:13;:11;:13::i;:::-;104974:36;;105025:12;105041:1;105025:17;105021:56;;;105059:7;;;105021:56;105087:38;105112:12;105087:24;:38::i;:::-;105186:10;105136:24;105163:34;;;:22;:34;;;;;;;-1:-1:-1;;105245:16:0;;105208:53;;;105163:34;105260:1;105319:20;;105299:141;105348:12;105341:4;:19;105299:141;;;105397:31;105411:10;105423:4;105397:13;:31::i;:::-;105385:43;;;;105362:6;;105299:141;;;-1:-1:-1;105455:40:0;;;;;;;;105474:10;;105455:40;;;;;;;;;;105585:36;;105567:12;;105585:10;;105608:8;;105567:12;105585:36;105567:12;105585:36;105608:8;105585:10;:36;;;;;;;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;;105566:55:0;;;105640:7;105632:39;;;;;-1:-1:-1;;;105632:39:0;;;;;;;;;;;;-1:-1:-1;;;105632:39:0;;;;;;;;;;;;;;105754:97;105825:4;;:18;;;-1:-1:-1;;;105825:18:0;;;;105798:7;;-1:-1:-1;;;;;105825:4:0;;:16;;:18;;;;;;;;;;;;;;:4;:18;;;2:2:-1;;;;27:1;24;17:12;2:2;105825:18:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;105825:18:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;105825:18:0;;-1:-1:-1;105754:97:0;:::o;84507:111::-;84576:34;84598:11;84576:21;:34::i;39443:29::-;;;;;;-1:-1:-1;;;;;39443:29:0;;:::o;43835:697::-;43943:17;43975;44007;44039:18;44072:24;44111:25;44151;44216:19;:17;:19::i;:::-;44204:31;;44271:14;:12;:14::i;:::-;44246:39;;;;;;;;44315:10;44326:9;44315:21;;;;;;;;;;;;;;;;:32;:21;;;;;:32;;-1:-1:-1;;;;;44315:32:0;;-1:-1:-1;44371:13:0;:11;:13::i;:::-;44358:26;;44415:39;44432:9;44443:10;44415:16;:39::i;:::-;44395:59;;44485:39;44502:9;44513:10;44485:16;:39::i;:::-;44465:59;;43835:697;;;;;;;:::o;19565:151::-;-1:-1:-1;;;;;19681:18:0;;;19654:7;19681:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;19565:151::o;106065:436::-;106198:7;106218:24;106245:33;106264:7;106273:4;106245:18;:33::i;:::-;106218:60;;106289:28;106320:26;106341:4;106320:20;:26::i;:::-;106289:57;;106357:21;106381:33;106402:5;106409:4;106381:20;:33::i;:::-;106357:57;-1:-1:-1;106432:61:0;106472:20;106432:35;106357:57;106450:16;106432:35;:17;:35;:::i;:61::-;106425:68;106065:436;-1:-1:-1;;;;;;;106065:436:0:o;81706:353::-;81883:21;41639:11;41631:54;;;;;-1:-1:-1;;;41631:54:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41631:54:0;;;;;;;;;;;;;;;81915:7:::1;41777:19;:17;:19::i;:::-;41767:7;:29;41759:50;;;::::0;;-1:-1:-1;;;41759:50:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;41759:50:0;;;;;;;;;;;;;::::1;;81935:19:::2;81957:29;81971:5;81978:7;81957:13;:29::i;84033:332::-:0;84210:7;41777:19;:17;:19::i;:::-;41767:7;:29;41759:50;;;;;-1:-1:-1;;;41759:50:0;;;;;;;;;;;;-1:-1:-1;;;41759:50:0;;;;;;;;;;;;;;;84248:19:::1;:17;:19::i;:::-;84238:7;:29;84230:50;;;::::0;;-1:-1:-1;;;84230:50:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;84230:50:0;;;;;;;;;;;;;::::1;;84291:66;84308:13;84323:19;84344:12;84291:16;:66::i;:::-;84033:332:::0;;;;;:::o;78540:37::-;;;:::o;109675:130::-;109744:4;109768:24;;;:18;:24;;;;;;:29;;;109675:130::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;66324:108::-;66403:10;:17;-1:-1:-1;;66403:21:0;66324:108;:::o;73130:487::-;73230:9;73261:5;73257:353;;;73287:8;73283:142;;;-1:-1:-1;73323:20:0;73316:27;;73283:142;-1:-1:-1;73391:18:0;73384:25;;73257:353;73461:8;73457:142;;;-1:-1:-1;73497:20:0;73490:27;;73457:142;-1:-1:-1;73565:18:0;73558:25;;50899:694;51038:12;:10;:12::i;:::-;51061:25;51089:19;:17;:19::i;:::-;51061:47;;51119:36;51134:1;51137:17;51119:14;:36::i;:::-;-1:-1:-1;;;;;51170:23:0;;51166:78;;51222:10;51210:22;;51166:78;51254:57;51269:19;:9;:17;;;;;;;;;:19::i;:::-;51290:10;51302:8;51254:14;:57::i;:::-;51322:70;51361:9;51372:8;51382:9;51322:10;51333:17;51322:29;;;;;;;;;;;;;;;;;;:38;;:70;;;;;;:::i;:::-;51498:17;51408:177;;51459:17;:9;:15;;;;;;;;;:17::i;:::-;51408:177;;51435:9;-1:-1:-1;;;;;51408:177:0;;51531:20;:9;:18;;;;;;;;;:20::i;:::-;51408:177;;;;;;;;;;;;;;;;;;;;;;;50899:694;;;;:::o;113101:205::-;113252:46;113282:4;113288:2;113292:5;113252:29;:46::i;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;;;;;;;;;;;;;;;;;;;;;;;;;;;99649:1692;99747:4;99753:7;99799:1;99786:10;:14;99778:49;;;;;-1:-1:-1;;;99778:49:0;;;;;;;;;;;;-1:-1:-1;;;99778:49:0;;;;;;;;;;;;;;;99914:28;:18;:26;:28::i;:::-;99900:10;:42;;99892:84;;;;;-1:-1:-1;;;99892:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;101115:13;101131:40;:9;101160:10;101131:40;:28;:40;:::i;:::-;101197:20;;101115:56;;-1:-1:-1;101188:29:0;;101184:150;;;-1:-1:-1;101242:5:0;;-1:-1:-1;101242:5:0;;-1:-1:-1;101234:17:0;;101184:150;101292:4;101298:9;:16;;101315:5;101298:23;;;;;;;;;;;;;;;;101284:38;;;;;99649:1692;;;;;;:::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;66498:382::-;66597:22;66641:5;:16;;;;;66650:7;66641:16;66637:236;;;-1:-1:-1;66691:1:0;66637:236;;;66715:5;66710:163;;66741:7;66737:125;;;-1:-1:-1;66786:1:0;66737:125;;61921:2440;62105:15;62135:16;62166:18;62228:19;:17;:19::i;:::-;62216:9;:31;62212:84;;;-1:-1:-1;62272:5:0;;-1:-1:-1;62272:5:0;;-1:-1:-1;62272:5:0;62264:20;;62212:84;62306:29;62338:10;62349:9;62338:21;;;;;;;;;;;;;;;;;;62306:53;;62370:27;62400:12;:23;;:74;62448:14;62424:49;;;;;;;;62400:74;;;;;;;;;;;;;;;;;;;;;;;;;;;:99;;62370:129;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;62370:129:0;;;;;;;;;;;;;;;;-1:-1:-1;;62539:18:0;:28;62598:29;;:19;62665:38;62370:129;;-1:-1:-1;;;;62539:28:0;;;;;;62598:29;;-1:-1:-1;62510:26:0;;-1:-1:-1;62665:38:0;;;-1:-1:-1;62657:47:0;;;;;;;;62730:18;:26;62638:66;;-1:-1:-1;;;;62730:26:0;;;;62715:12;;;62814:208;62839:10;:17;62834:1;:22;62814:208;;62899:9;-1:-1:-1;;;;;62882:26:0;:10;62893:1;62882:13;;;;;;;;;;;;;;-1:-1:-1;;;;;62882:26:0;;62878:133;;;62939:4;62929:14;;62970:1;62962:9;;62990:5;;62878:133;62858:3;;62814:208;;;;63314:18;63302:9;:30;63301:225;;;;63352:7;:44;;;;;63377:18;63364:9;:31;63352:44;63351:174;;;;;63437:8;63420:14;:25;63419:105;;;;63491:8;63473:14;:26;63472:51;;;;;63513:9;63505:5;:17;63472:51;63283:301;;;-1:-1:-1;63561:4:0;;-1:-1:-1;63567:1:0;;-1:-1:-1;63567:1:0;;-1:-1:-1;63553:19:0;;-1:-1:-1;;;;;;;63553:19:0;63283:301;63601:7;63596:61;;-1:-1:-1;63633:5:0;;-1:-1:-1;63633:5:0;;-1:-1:-1;63633:5:0;;-1:-1:-1;63625:20:0;;-1:-1:-1;;;;;;;63625:20:0;63596:61;63732:14;63774:18;63761:9;:31;:42;;;;;63796:7;63761:42;63757:597;;;63837:8;63820:147;63851:14;63847:1;:18;63820:147;;;63901:50;:12;:23;63935:1;63925:12;;;;;;;;63901:37;;;;;;;;;;;;;;;;;;;;;;;;;;;:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63901:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:50::i;:::-;63891:60;;;;63867:3;;63820:147;;;-1:-1:-1;63992:1:0;;-1:-1:-1;64021:32:0;64043:9;64021:17;:6;64032:5;64021:17;:10;:17;:::i;:::-;:21;:32;:21;:32;:::i;:::-;64056:1;64021:36;64008:49;;63757:597;;;64095:9;64090:141;64115:14;64110:1;:19;64090:141;;64165:50;:12;:23;64199:1;64189:12;;;;;;;64165:50;64155:60;;;;64131:3;;64090:141;;;-1:-1:-1;64256:33:0;:9;64270:18;64256:33;:13;:33;:::i;:::-;64292:1;64256:37;;-1:-1:-1;64321:17:0;:6;64332:5;64321:17;:10;:17;:::i;:::-;64341:1;64321:21;64308:34;;63757:597;61921:2440;;;;;;;;;;;;;;;;;:::o;47695:461::-;47836:13;:11;:13::i;:::-;:18;47828:50;;;;;-1:-1:-1;;;47828:50:0;;;;;;;;;;;;-1:-1:-1;;;47828:50:0;;;;;;;;;;;;;;;47897:10;-1:-1:-1;;;;;47911:7:0;47897:21;;47889:30;;12:1:-1;9;2:12;47889:30:0;47930:32;47945:7;47954;47930:14;:32::i;:::-;47973:31;47979:10;47991:12;47973:5;:31::i;:::-;48015:49;48030:12;48044:10;48056:7;-1:-1:-1;;;;;48015:49:0;:14;:49::i;:::-;48075;48090:12;48104:10;48116:7;-1:-1:-1;;;;;48075:49:0;:14;:49::i;:::-;48135:13;:11;:13::i;51979:353::-;52054:23;52092;52129:20;:18;:20::i;:::-;52039:110;;;;52160:26;52181:1;52184;52160:20;:26::i;:::-;52204:46;;;;;;;;;;;;;;;;;;;;;;;;;52261:63;52275:14;52291:15;52308;52261:13;:63::i;:::-;51979:353;;:::o;110012:1012::-;110157:4;;:17;;;-1:-1:-1;;;110157:17:0;;;;110136:18;;-1:-1:-1;;;;;110157:4:0;;:15;;:17;;;;;;;;;;;;;;:4;:17;;;2:2:-1;;;;27:1;24;17:12;2:2;110157:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;110157:17:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;110157:17:0;;-1:-1:-1;110185:13:0;;110248:25;;;110244:133;;;110313:10;110298:12;:25;110290:33;;110244:133;;;110364:1;110356:9;;110244:133;-1:-1:-1;;110489:16:0;;110472:413;110512:5;110507:1;:10;110472:413;;110543:19;;;;:16;:19;;;;;;;;-1:-1:-1;;;;;110543:33:0;;;;;;;;;;:38;110539:84;;110602:5;;110539:84;110656:4;;:115;;;-1:-1:-1;;;110656:115:0;;-1:-1:-1;;;;;110656:115:0;;;;;;;110731:4;110656:115;;;;;;;;;;;;110637:16;;110656:4;;;;;:15;;:115;;;;;;;;;;;;;;;:4;:115;;;2:2:-1;;;;27:1;24;17:12;2:2;110656:115:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;110656:115:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;110656:115:0;110786:19;;;;:16;110656:115;110786:19;;;;;;;-1:-1:-1;;;;;110786:33:0;;;;;;;;;:44;;;110845:28;;;;;-1:-1:-1;;;110519:3:0;110472:413;;;-1:-1:-1;110899:21:0;110895:60;;110937:7;;;;;110895:60;110965:4;;:51;;;-1:-1:-1;;;110965:51:0;;-1:-1:-1;;;;;110965:51:0;;;;;;;111010:4;110965:51;;;;;;:4;;;;;:20;;:51;;;;;:4;;:51;;;;;;;:4;;:51;;;2:2:-1;;;;27:1;24;17:12;2:2;110965:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;110965:51:0;;;;110012:1012;;;;;:::o;74498:177::-;74608:58;;;-1:-1:-1;;;;;74608:58:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;74608:58:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;74581:86:0;;74601:5;;74581:19;:86::i;64369:187::-;64509:8;;64540;;-1:-1:-1;;;;;;;;64509:8:0;;;;;;64540;;;64369:187::o;48416:806::-;48609:15;48626;48643:13;48660:121;48692:6;48713:9;48737;48761;48660:17;:121::i;:::-;48608:173;;;;;;48809:8;48800:5;:17;;48792:61;;;;;-1:-1:-1;;;48792:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;48864:49;48879:12;48893:10;48905:7;48864:14;:49::i;:::-;48924;48939:12;48953:10;48965:7;48924:14;:49::i;:::-;48984:123;49013:34;:22;:9;49027:7;49013:22;:13;:22;:::i;:::-;:32;:34::i;:::-;49062;:22;:9;49076:7;49062:22;:13;:22;:::i;:34::-;48984:14;:123::i;:::-;49118:24;49124:10;49136:5;49118;:24::i;:::-;49158:56;;;;;;;;;;;;;;;;;;;;49184:4;;49172:10;;49158:56;;;;;;;;;48416:806;;;;;;;;:::o;111229:869::-;111325:4;;:17;;;-1:-1:-1;;;111325:17:0;;;;111304:18;;-1:-1:-1;;;;;111325:4:0;;:15;;:17;;;;;;;;;;;;;;:4;:17;;;2:2:-1;;;;27:1;24;17:12;2:2;111325:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;111325:17:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;111325:17:0;;-1:-1:-1;111353:13:0;;111416:25;;;111412:133;;;111481:10;111466:12;:25;111458:33;;111412:133;;;111532:1;111524:9;;111412:133;-1:-1:-1;;111657:16:0;;111640:323;111680:5;111675:1;:10;111640:323;;111711:19;;;;:16;:19;;;;;:23;;;:28;111707:74;;111760:5;;111707:74;111814:4;;:45;;;-1:-1:-1;;;111814:45:0;;111795:16;111814:45;;;;;;111850:4;111814:45;;;;;;;;;;;;111795:16;;-1:-1:-1;;;;;111814:4:0;;:15;;:45;;;;;;;;;;;;;;;:4;:45;;;2:2:-1;;;;27:1;24;17:12;2:2;111814:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;111814:45:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;111814:45:0;111874:19;;;;:16;111814:45;111874:19;;;;:23;;:34;;;111923:28;;;;;-1:-1:-1;;;111687:3:0;111640:323;;;-1:-1:-1;111977:21:0;111973:60;;112015:7;;;;;111973:60;112043:4;;:47;;;-1:-1:-1;;;112043:47:0;;:4;:47;;;;;;112084:4;112043:47;;;;;;-1:-1:-1;;;;;112043:4:0;;;;:20;;:47;;;;;:4;;:47;;;;;;:4;;:47;;;2:2:-1;;;;27:1;24;17:12;2:2;112043:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;112043:47:0;;;;111229:869;;;;:::o;51751:134::-;51829:48;51844:11;51829:48;;51857:19;:17;:19::i;:::-;51829:14;:48::i;35499:132::-;35561:7;35588:35;35621:1;35588:28;:1;35462:19;35588:28;:5;:28;:::i;49642:896::-;49786:17;49805;49826:14;:12;:14::i;:::-;49785:55;;;;49866:20;49889:13;:11;:13::i;:::-;49866:36;-1:-1:-1;49913:15:0;49931:38;49866:36;49931:20;:9;49945:5;49931:20;:13;:20;:::i;:38::-;49913:56;-1:-1:-1;49980:15:0;49998:38;50023:12;49998:20;:9;50012:5;49998:20;:13;:20;:::i;:38::-;49980:56;;50080:10;50069:7;:21;;:46;;;;;50105:10;50094:7;:21;;50069:46;50047:127;;;;;-1:-1:-1;;;50047:127:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;50185:123;50214:34;:22;:9;50228:7;50214:22;:13;:22;:::i;:34::-;50263;:22;:9;50277:7;50263:22;:13;:22;:::i;50185:123::-;50319:24;50325:10;50337:5;50319;:24::i;:::-;50354:46;50366:12;50380:10;50392:7;50354:11;:46::i;:::-;50411;50423:12;50437:10;50449:7;50411:11;:46::i;:::-;50473:57;;;;;;;;;;;;;;;;;;;;50499:5;;50487:10;;50473:57;;;;;;;;;49642:896;;;;;;;;:::o;52692:164::-;52781:26;:24;:26::i;:::-;52777:72;;;52824:13;:11;:13::i;53105:3738::-;53210:45;;:::i;:::-;:66;;;;;;;;;53258:18;53210:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53210:66:0;;-1:-1:-1;;;;;53210:66:0;;;;;-1:-1:-1;;;53210:66:0;;;;;;;;-1:-1:-1;;;53210:66:0;;;;;;;;;;;;-1:-1:-1;53287:47:0;;:::i;:::-;:69;;;;;;;;;53337:19;53287:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53627:17;53594:19;:29;;;:50;;;;:166;;;;;53663:26;:24;:26::i;:::-;53662:27;:97;;;;53742:17;53710:19;:29;;;:49;;;53662:97;53576:229;;;53787:7;;;;53576:229;53820:19;:27;;;53815:950;;54026:34;54083:27;54133:12;54167:105;54224:19;:29;;;54167:34;:105::i;:::-;54003:269;;-1:-1:-1;54003:269:0;-1:-1:-1;54003:269:0;-1:-1:-1;54291:19:0;54003:269;54291:93;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54445:52:0;:19;:50;:52::i;:::-;54403:94;;:39;;;:94;54543:16;:4;:14;:16::i;:::-;-1:-1:-1;;;;;54516:43:0;:24;;;:43;-1:-1:-1;;54608:4:0;54578:27;;;:34;-1:-1:-1;;54631:54:0;;;54704:30;;;:34;53815:950;54877:16;;54870:1862;;54910:31;54944:10;54955:19;:47;;;54944:59;;;;;;;;;;;;;;;;;55033:39;;54944:59;;;;;;;:129;;;;;;;;;;;;;;;;;;;;;;;;;;;54910:163;;55107:19;55145:17;55181:24;55223:458;55262:13;55294:49;:20;:39;;;:47;;;;;;;:49;55362:30;;;;55464:39;;55411:111;;:19;;:111;:30;:111;:::i;:::-;55541:19;:24;;;-1:-1:-1;;;;;55223:458:0;55584:10;55595:19;:29;;;55584:41;;;;;;;;;;;;;;;;;;:52;:41;;;;;:52;;-1:-1:-1;;;;;55584:52:0;55655:11;55223:20;:458::i;:::-;55088:593;;;;;;55700:14;55696:911;;;55735:18;55756:159;55793:10;55804:19;:29;;;55793:41;;;;;;;;;;;;;;;;;;;;55857:20;:39;;;55756:14;:159::i;:::-;55735:180;;55941:10;55952:19;:29;;;55941:41;;;;;;;;;;;;;;;;;56016:39;;55941:41;;;;;;;:115;;;;;;;;;;;;;;;;;;;;;;;;;;;;55934:122;;;;;;;;:::i;:::-;;;;;;;;;56155:13;56151:290;;;56193:29;;;:34;;;56226:1;56193:34;;;;;;;-1:-1:-1;56250:27:0;;;:35;56308:40;;:18;:40;;56193:19;;56308:18;;:40;:18;;-1:-1:-1;;56308:40:0;;;;;;;;;;;;;;;-1:-1:-1;56308:40:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;56308:40:0;-1:-1:-1;;;;56308:40:0;;;;-1:-1:-1;;;56308:40:0;-1:-1:-1;;;;;;;;;56308:40:0;;;-1:-1:-1;;;56308:40:0;-1:-1:-1;;;;;;;;56308:40:0;;;;;;-1:-1:-1;;56308:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56373:7:0;;-1:-1:-1;;;;;;56373:7:0;56151:290;56501:61;;:90;;:88;;;;;;;;;:90::i;:::-;56459:20;;:132;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;55696:911:0;56654:20;:9;:18;:20::i;:::-;56621:53;;:30;;;:53;56689:31;;;;-1:-1:-1;54870:1862:0;;-1:-1:-1;;54870:1862:0;;56742:40;;:18;:40;;56763:19;;56742:40;:18;;-1:-1:-1;;56742:40:0;;;;;;;;;;;;;;;-1:-1:-1;56742:40:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;56742:40:0;-1:-1:-1;;;;56742:40:0;;;;-1:-1:-1;;;56742:40:0;-1:-1:-1;;;;;;;;;56742:40:0;;;-1:-1:-1;;;56742:40:0;-1:-1:-1;;;;;;;;56742:40:0;;;;;;-1:-1:-1;;56742:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56793:42;;:19;:42;;56815:20;;56793:42;:19;;-1:-1:-1;;56793:42:0;56742:40;56793:42;;;;;;;;;;;;;;;;;;;;;;;;;53105: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;;84824:206;84958:64;84994:4;85008;85015:6;84958:18;84966:9;84958:7;:18::i;:::-;-1:-1:-1;;;;;84958:35:0;;:64;;;:35;:64;:::i;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;108893:202::-;109024:20;:18;:20::i;:::-;109055:32;109071:4;109077:2;109081:5;109055:15;:32::i;93371:114::-;93463:14;;93371:114::o;91298:918::-;91411:12;;91387:7;;91407:58;;-1:-1:-1;91452:1:0;91445:8;;91407:58;91518:12;;91477:11;;91543:424;91556:4;91550:3;:10;91543:424;;;91577:11;91591:23;91604:3;91609:4;91591:12;:23::i;:::-;91577:37;;91848:7;91835:5;91841:3;91835:10;;;;;;;;;;;;;;;;:20;91831:125;;;91883:3;91876:10;;91831:125;;;91933:3;91939:1;91933:7;91927:13;;91831:125;91543:424;;;;92093:1;92087:3;:7;:36;;;;;92116:7;92098:5;92110:1;92104:3;:7;92098:14;;;;;;;;;;;;;;;;:25;92087:36;92083:126;;;-1:-1:-1;;;92147:7:0;;-1:-1:-1;92140:14:0;;92083:126;-1:-1:-1;92194:3:0;-1:-1:-1;92187:10:0;;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;38608:123::-;38701:15;:22;;38608:123::o;5265:136::-;5323:7;5350:43;5354:1;5357;5350:43;;;;;;;;;;;;;;;;;:3;:43::i;64801:219::-;64887:8;:22;;-1:-1:-1;;;;;64887:22:0;;;-1:-1:-1;;;64887:22:0;;;;;;;;64920:8;:22;;-1:-1:-1;;;;;;64920:22:0;;;;;;;;;;64958:54;64887:22;64920;64998:13;:11;:13::i;:::-;64958:54;;;-1:-1:-1;;;;;64958:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;64801:219;;:::o;113498:176::-;113625:41;113651:7;113660:5;113625:25;:41::i;85588:265::-;85653:19;:17;:19::i;:::-;85683:18;85704:19;:17;:19::i;:::-;85683:40;;85764:22;:10;:20;:22::i;:::-;-1:-1:-1;;;;;85739:106:0;;85801:10;85812;85801:22;;;;;;;;;;;;;;;;;:33;:22;;;;;:33;;85739:106;;;-1:-1:-1;;;;;85801:33:0;;;85739:106;;;;;;;;;;;;85588:265;:::o;64564:229::-;64728:14;;64771;;-1:-1:-1;;;;;64728:14:0;;;;;;;64771;;;64564:229::o;66888:215::-;67016:14;:34;;-1:-1:-1;;67016:34:0;;-1:-1:-1;;;;;67016:34:0;;;;;;;67061:14;:34;;-1:-1:-1;;;;;;67061:34:0;;;;;;;;66888:215::o;87260:240::-;87409:12;;87405:88;;87438:43;-1:-1:-1;;;;;87438:4:0;:17;87456:15;87473:7;87438:43;:17;:43;:::i;76803:761::-;77227:23;77253:69;77281:4;77253:69;;;;;;;;;;;;;;;;;77261:5;-1:-1:-1;;;;;77253:27:0;;;:69;;;;;:::i;:::-;77337:17;;77227:95;;-1:-1:-1;77337:21:0;77333:224;;77479:10;77468:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;77468:30:0;77460:85;;;;-1:-1:-1;;;77460:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67111:703;67315:7;;;;67398:9;:25;;;;;;;;;67394:413;;;67466:6;67491:36;67517:9;67491:21;67466:6;67502:9;67491:21;:10;:21;:::i;:36::-;67546:40;67576:9;67546:25;67557:13;:11;:13::i;:::-;67546:6;;:25;:10;:25;:::i;:40::-;67440:161;;;;;;;;67394:413;67660:36;67686:9;67660:21;:6;67671:9;67660:21;:10;:21;:::i;:36::-;67715:6;67740:40;67770:9;67740:25;67751: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;113314:176::-;113441:41;113467:7;113476:5;113441:25;:41::i;85038:180::-;85167:43;85199:2;85203:6;85167:18;85175:9;85167:7;:18::i;:::-;-1:-1:-1;;;;;85167:31:0;;:43;;:31;:43;:::i;85424:156::-;85492:4;85532:10;85543:19;:17;:19::i;:::-;85532:31;;;;;;;;;;;;;;;;;;;;;:40;;;-1:-1:-1;;;85532:40:0;;-1:-1:-1;;;;;85532:40:0;85516:12;:56;;;85424:156;-1:-1:-1;85424:156:0:o;68828:2706::-;68939:34;68988:27;69030:12;69070:25;69098:10;69109:9;69098:21;;;;;;;;;;;;;;;;;;69561:39;;;69098:21;;;;;69561:39;;;;;;;;:67;;;69691:18;69671:39;;;;;:67;;;69783:55;;;;;;:83;;;69931:34;69911:55;;;;;:83;;;;69098:21;;-1:-1:-1;69098:21:0;;;;69561:67;;69671;;70187:202;69098:21;69561:67;69671;69783:83;69911;70187:20;:202::i;:::-;70005:384;;-1:-1:-1;70005:384:0;;-1:-1:-1;70005:384:0;;-1:-1:-1;70005:384:0;;-1:-1:-1;70005:384:0;-1:-1:-1;70421:17:0;70417:580;;70486:20;70459:47;;70417:580;;;70567:12;70583:1;70567:17;70563:434;;;70632:20;70605:47;;70563:434;;;70678:12;70694:1;70678:17;70674:323;;;70743:18;70716:45;;70674:323;;;70787:12;70803:1;70787:17;70783:214;;;70852:20;70825:47;;70783:214;;;70898:12;70914:1;70898:17;70894:103;;;70963:18;70936:45;;70894:103;71054:9;71023:298;;;71084:24;71078:31;;;;;;;;71023:298;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71389:19;;;;71332:194;;-1:-1:-1;;;;;71389:19:0;71423:29;71467;71511:4;71332:42;:194::i;:::-;68828: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;57283:1140::-;57573:4;57592:7;57614;57649:13;57673:18;57694:22;:9;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57694:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:22::i;:::-;57673:43;;57754:12;57746:20;;57727:535;57804:11;57789:12;57781:5;:20;:34;57727:535;;;57877:10;57868:5;:19;57864:98;;-1:-1:-1;57916:4:0;;-1:-1:-1;57922:1:0;;-1:-1:-1;57925:20:0;;;;-1:-1:-1;57908:38:0;;57864:98;57976:17;57996:9;:20;;58017:5;57996:27;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57996:27:0;58124:30;;;;;;;;;;;;57996:27;;-1:-1:-1;58038:212:0;;58070:7;;57996:27;;58173:10;58202:4;58225:10;58038:13;:212::i;:::-;-1:-1:-1;57830:7:0;;;;;57727:535;;;58285:10;58276:5;:19;58272:90;;-1:-1:-1;58320:4:0;;-1:-1:-1;58326:1:0;;-1:-1:-1;58329:20:0;;;;-1:-1:-1;58312:38:0;;58272:90;-1:-1:-1;58380:5:0;;-1:-1:-1;58387:5:0;-1:-1:-1;;58394:20:0;;;57283:1140;;;;;;;;;;;;:::o;71724:627::-;71853:4;71955:20;71930:21;:45;;;;;;;;;71926:89;;;-1:-1:-1;71999:4:0;71992:11;;71926:89;72030:9;72050:28;:21;:26;;;;;;;:28;72042:37;;;;;;;;72030:49;;72025:297;72081:1;72086;72081:6;72025:297;;72109:21;;:::i;:::-;72133:6;:17;72161:1;72151:12;;;;;;;;72133:31;;;;;;;;;;;;;;;;;;;;;;;;;;;72109:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;72109:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72240:17;:4;:15;:17::i;:::-;:22;72236:75;;72290:5;72283:12;;;;;;72236:75;-1:-1:-1;72089:3:0;;72025: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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85861:183;85918:14;;85949:9;:25;;;;;;;;;85945:69;;;-1:-1:-1;85998:4:0;85991:11;;85945:69;-1:-1:-1;86031:5:0;85861:183;;;:::o;74683:205::-;74811:68;;;-1:-1:-1;;;;;74811:68:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;74811:68:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;74784:96:0;;74804:5;;74784:19;:96::i;34736:143::-;34791:4;;34815;:26;;;;;;;;;:56;;;-1:-1:-1;34853:18:0;34845:26;;109419:248;109468:20;109491:13;:11;:13::i;:::-;109468:36;;109534:1;109519:12;:16;:62;;;;;109540:41;109579:1;109564:12;:16;109540:23;:41::i;:::-;109539:42;109519:62;109515:145;;;109637:11;:9;:11::i;:::-;-1:-1:-1;;109617:16:0;;109598:36;;;;:18;:36;;;;;:50;109419:248;:::o;99006:215::-;99103:28;99126:4;99103:22;:28::i;:::-;99142:26;99165:2;99142:22;:26::i;:::-;99181:32;99197:4;99203:2;99207:5;99181:15;:32::i;90472:193::-;90534:7;90655:1;;90646;:5;90642:1;90638;:5;:13;90637:19;;;;;;90631:1;90627;:5;90621:1;90617;:5;90616:17;:41;;90472:193;-1:-1:-1;;;90472:193:0:o;109103:150::-;109187:20;:18;:20::i;:::-;109218:27;109230:7;109239:5;109218:11;:27::i;52465:219::-;52516:10;52546:119;52592:10;:8;:10::i;:::-;52621:29;52622:12;52637:1;52622:16;52621:27;:29::i;:::-;52546:119;;:27;:119::i;:::-;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;52516:160:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;52516:160:0;;;-1:-1:-1;;;;;52516:160:0;;;;;;-1:-1:-1;;;52516:160:0;;;;;;;;52465:219::o;13173:196::-;13276:12;13308:53;13331:6;13339:4;13345:1;13348:12;13308:22;:53::i;109261:150::-;109345:20;:18;:20::i;:::-;109376:27;109388:7;109397:5;109376:11;:27::i;67822:998::-;68391:19;;;;68122:12;;;;;;;;;;-1:-1:-1;;;;;68391:19:0;35462;68345:65;68441:371;68482:50;:21;68345:65;68482:31;:50::i;:::-;68551:52;:23;68585:17;68551:52;:33;:52;:::i;:::-;68622:50;:21;68654:17;68622:50;:31;:50;:::i;:::-;68691:52;:23;68725:17;68691:52;:33;:52;:::i;:::-;68762:8;;68789;;-1:-1:-1;;;;;;;;68762:8:0;;;;;;68789;68441:22;:371::i;:::-;68421:391;;;;-1:-1:-1;68421:391:0;;-1:-1:-1;68421:391:0;-1:-1:-1;68421:391:0;;-1:-1:-1;67822:998:0;-1:-1:-1;;;;;;;67822:998:0:o;87829:1768::-;88073:19;88103;88133:25;88169:18;88232:27;88278:29;88325:230;88380:10;88409:29;88457;88505:4;88528:12;88325:36;:230::i;:::-;88584:8;;88649:14;;-1:-1:-1;;;;;;;;88584:8:0;;;;;:30;;;;-1:-1:-1;88584:8:0;88649:14;;;;;;:38;;-1:-1:-1;88752:230:0;;-1:-1:-1;88807:10:0;;-1:-1:-1;88836:29:0;88884;88932:4;88649:14;88752:36;:230::i;:::-;89025:8;;-1:-1:-1;;;;;89025:8:0;89011:22;;;;-1:-1:-1;88724:258:0;-1:-1:-1;89025:8:0;89102:150;35462:19;89102:90;89141:50;89163:27;89011:22;88724:258;89163:27;:15;:27;:::i;:::-;89141:11;;:50;:21;:50;:::i;:::-;89102:10;;:90;:38;:90;:::i;:::-;:118;:150;:118;:150;:::i;:::-;89334:33;;;;;89281:24;;;;89402:39;;;;;-1:-1:-1;89463:64:0;89478:23;89334:33;89478:21;:23::i;:::-;89503;:11;:21;:23::i;89463:64::-;89538:51;89559:29;:17;:27;:29::i;:::-;-1:-1:-1;;;;;89538:51:0;:20;:51::i;58743:1250::-;58953:14;58970:17;:7;:15;;;;;;;;;:17::i;:::-;58953:34;-1:-1:-1;59047:20:0;59070:30;:8;59089:10;59070:30;:18;:30;:::i;:::-;59047:53;-1:-1:-1;59199:38:0;59240:112;59305:46;35462:19;59340:10;59305:46;:34;:46;:::i;:::-;59240:40;:8;59267:12;59240:40;:26;:40;:::i;:112::-;59199:153;;59499:17;59519:120;59557:7;59579:30;59624:4;59519:23;:120::i;:::-;59499:140;;59650:55;59672:7;59681:9;59692:12;59650:21;:55::i;:::-;59716:53;59738:8;59748:9;59759;59716:21;:53::i;:::-;59891:9;-1:-1:-1;;;;;59785:200:0;59856:19;:17;:19::i;:::-;59785:200;;59821:12;59810:7;:23;;;;;;;;59785:200;;;;;;;;;;;;;;;;;;;;59810:23;;;;;59785:200;;;;;;;;;58743:1250;;;;;;;;;;:::o;97771:228::-;97818:7;97838:30;:18;:28;:30::i;:::-;97881:17;97901:28;:18;:26;:28::i;:::-;97945:19;;;;;;;;97881:48;;-1:-1:-1;97945:19:0;;;;;;;;;;97982:9;-1:-1:-1;97771:228:0;:::o;101349:146::-;-1:-1:-1;;;;;101433:33:0;;;;;;:24;:33;;;;;101417:70;;101468:18;101458:7;101468:9;:18::i;:::-;101417:15;:70::i;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;99229:202::-;99313:31;99336:7;99313:22;:31::i;:::-;99355:28;:26;:28::i;:::-;99396:27;99408:7;99417:5;99396:11;:27::i;87119:133::-;87166:7;87193:10;-1:-1:-1;;;;;87193:43:0;;87237:6;87193:51;;;;;;;;;;;;;-1:-1:-1;;;;;87193:51:0;-1:-1:-1;;;;;87193:51:0;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87193:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;37824:211:0;37933:15;;:::i;:::-;-1:-1:-1;37973:54:0;;;;;;;;;-1:-1:-1;;;;;37973:54:0;;;;;;;;;;;;37824:211::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;;99439:202:0;99523:31;99546:7;99523:22;:31::i;:::-;99565:28;:26;:28::i;:::-;99606:27;99618:7;99627:5;99606:11;:27::i;65028:877::-;65367:12;65394:20;65429:27;65471:24;65510;65562:22;;:::i;:::-;65587:247;;;-1:-1:-1;;;65587:247:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;65587:9:0;:24;;;;:247;;;;;;;;;;;;;;:24;:247;;;2:2:-1;;;;27:1;24;17:12;2:2;65587:247:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65587: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;65587:247:0;-1:-1:-1;65587:247:0;65858:1;65853:7;;;;65862:4;65867:1;65862:7;;;;65871:4;65876:1;65871:7;;;;65880:4;65885:1;65880:7;;;;65889:4;65894:1;65889:7;;;;65845:52;;;;;;;;;;;65028:877;;;;;;;;;;;;:::o;72359:763::-;72609:7;;;72660:74;:28;72713:10;72660:74;:38;:74;:::i;:::-;72638:96;-1:-1:-1;72745:17:0;72765:38;72638:96;39231:18;72765:38;:21;:38;:::i;:::-;72745:58;;72814:18;72920:153;72962:19;:9;:17;;;;;;;:19;73000:35;73054:4;72920:23;:153::i;:::-;72880:23;;;;72835:69;;:238;;;;;-1:-1:-1;72894:9:0;-1:-1:-1;;72359:763:0;;;;;;;;:::o;35825:178::-;35922:7;35954:41;35462:19;35954:14;:4;35963;35954:14;:8;:14;:::i;89650:131::-;89744:29;:17;:27;:29::i;:::-;89727:14;;:46;;;;;-1:-1:-1;;;;;89727:46:0;;;;;-1:-1:-1;;;;;89727:46:0;;;;;;89650:131;:::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;;65996:320;66134:7;;66158:5;:21;;;;;;;;;66154:155;;;66203:27;:6;66220:9;66203:27;:16;:27;:::i;:::-;66196:34;;;;66154:155;66270:27;:6;66287:9;66270:27;:16;:27;:::i;93493:181::-;93647:19;;93665:1;93647:19;;;93493:181::o;101629:315::-;101724:17;101744:28;:18;:26;:28::i;:::-;101724:48;-1:-1:-1;101724:48:0;101787:30;101803:9;101787:15;:30::i;:::-;:42;101783:154;;;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;101846:29:0;;;;;;;;;;;;;;101890:16;;;27:10:-1;;23:18;;;45:23;;101890:35:0;;;;;;;;101629:315::o;101503:118::-;101560:53;101576:21;101599:13;:11;:13::i;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;10058:619::-;10118:4;10586:20;;10429:66;10626:23;;;;;;:42;;-1:-1:-1;;10653:15:0;;;10058:619;-1:-1:-1;;10058:619:0:o;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;101952:212::-;102046:10;;102022:7;;102042:115;;-1:-1:-1;102085:1:0;102078:8;;102042:115;102130:10;;102126:3;;-1:-1:-1;;102130:14:0;;;102126:19;;;;;;;;;;;;;;102119:26;;;;112231:1446;;;;;;;;;;;-1:-1:-1;112231:1446:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;112231:1446:0;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;112231:1446:0;;;-1:-1:-1;;112231:1446:0:o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
ipfs://3c590c87bd38dd085d6955877b99a555774bfae076e5428f7abd4b10ff0f7248
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.337738 | 0.7309 | $0.2468 |
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.