Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 44 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer | 13619668 | 1167 days ago | IN | 0 ETH | 0.01617648 | ||||
Transfer | 12469795 | 1346 days ago | IN | 0 ETH | 0.007 | ||||
Transfer | 11695810 | 1465 days ago | IN | 0 ETH | 0.00675785 | ||||
Transfer | 11667922 | 1469 days ago | IN | 0 ETH | 0.00551818 | ||||
Transfer | 11663212 | 1470 days ago | IN | 0 ETH | 0.00507664 | ||||
Transfer | 11576617 | 1483 days ago | IN | 0 ETH | 0.00588786 | ||||
Transfer | 11572115 | 1484 days ago | IN | 0 ETH | 0.00446345 | ||||
Approve | 11570252 | 1484 days ago | IN | 0 ETH | 0.00381883 | ||||
Transfer | 11554130 | 1487 days ago | IN | 0 ETH | 0.00848898 | ||||
Transfer | 11554091 | 1487 days ago | IN | 0.5 ETH | 0.009622 | ||||
Transfer | 11550398 | 1487 days ago | IN | 0.2 ETH | 0.001092 | ||||
Transfer | 11550351 | 1487 days ago | IN | 0.1 ETH | 0.00565505 | ||||
Transfer | 11514673 | 1493 days ago | IN | 0.2 ETH | 0.00973085 | ||||
Transfer | 11514657 | 1493 days ago | IN | 0.2 ETH | 0.00955956 | ||||
Transfer | 11514614 | 1493 days ago | IN | 0.2 ETH | 0.00904808 | ||||
Transfer | 11484902 | 1497 days ago | IN | 0 ETH | 0.00572088 | ||||
Transfer | 11473756 | 1499 days ago | IN | 0.1 ETH | 0.00632755 | ||||
Transfer | 11470710 | 1500 days ago | IN | 0.1 ETH | 0.00734766 | ||||
Mint | 11470635 | 1500 days ago | IN | 0.1 ETH | 0.01130015 | ||||
Approve | 11467346 | 1500 days ago | IN | 0 ETH | 0.00598357 | ||||
Approve | 11467304 | 1500 days ago | IN | 0 ETH | 0.00441829 | ||||
Approve | 11467194 | 1500 days ago | IN | 0 ETH | 0.00168739 | ||||
Transfer | 11467156 | 1500 days ago | IN | 0 ETH | 0.00882181 | ||||
Approve | 11466804 | 1500 days ago | IN | 0 ETH | 0.00399645 | ||||
Transfer | 11466797 | 1500 days ago | IN | 0.2 ETH | 0.01017369 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
13619668 | 1167 days ago | 0.06378059 ETH | ||||
13619637 | 1167 days ago | 2.07253433 ETH | ||||
11878169 | 1437 days ago | 0.24760111 ETH | ||||
11699884 | 1464 days ago | 0.37105851 ETH | ||||
11697015 | 1465 days ago | 0.52980644 ETH | ||||
11695810 | 1465 days ago | 0.13094799 ETH | ||||
11667922 | 1469 days ago | 0.00405006 ETH | ||||
11663361 | 1470 days ago | 0.12003521 ETH | ||||
11663212 | 1470 days ago | 0.05174139 ETH | ||||
11661771 | 1470 days ago | 0.1 ETH | ||||
11661770 | 1470 days ago | 0.52645311 ETH | ||||
11661765 | 1470 days ago | 0.1 ETH | ||||
11655381 | 1471 days ago | 0.21873174 ETH | ||||
11655166 | 1471 days ago | 0.22024829 ETH | ||||
11654802 | 1471 days ago | 0.35060084 ETH | ||||
11591077 | 1481 days ago | 0.71195937 ETH | ||||
11591031 | 1481 days ago | 0.3036371 ETH | ||||
11588576 | 1482 days ago | 0.10422262 ETH | ||||
11582389 | 1482 days ago | 0.2323137 ETH | ||||
11576681 | 1483 days ago | 1.42599854 ETH | ||||
11576617 | 1483 days ago | 0.13131928 ETH | ||||
11572115 | 1484 days ago | 0.09175804 ETH | ||||
11570767 | 1484 days ago | 0.88628516 ETH | ||||
11570632 | 1484 days ago | 0.0719489 ETH | ||||
11568613 | 1485 days ago | 0.65032892 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
USM
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-12-16 */ // SPDX-License-Identifier: GPL-3.0-or-later // File: @openzeppelin/contracts/utils/Address.sol 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/math/SafeMath.sol 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/GSN/Context.sol 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 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/token/ERC20/ERC20.sol 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: erc20permit/contracts/IERC2612.sol // Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/ pragma solidity ^0.6.0; /** * @dev Interface of the ERC2612 standard as defined in the EIP. * * Adds the {permit} method, which can be used to change one's * {IERC20-allowance} without having to send a transaction, by signing a * message. This allows users to spend tokens without having to hold Ether. * * See https://eips.ethereum.org/EIPS/eip-2612. */ interface IERC2612 { /** * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens, * given `owner`'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @dev Returns the current ERC2612 nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); } // File: erc20permit/contracts/ERC20Permit.sol // Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/53516bc555a454862470e7860a9b5254db4d00f5/contracts/token/ERC20/ERC20Permit.sol pragma solidity ^0.6.0; /** * @author Georgios Konstantopoulos * @dev Extension of {ERC20} that allows token holders to use their tokens * without sending any transactions by setting {IERC20-allowance} with a * signature using the {permit} method, and then spend them via * {IERC20-transferFrom}. * * The {permit} signature mechanism conforms to the {IERC2612} interface. */ abstract contract ERC20Permit is ERC20, IERC2612 { mapping (address => uint256) public override nonces; bytes32 public immutable PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public immutable DOMAIN_SEPARATOR; constructor(string memory name_, string memory symbol_) internal ERC20(name_, symbol_) { uint256 chainId; assembly { chainId := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name_)), keccak256(bytes("1")), chainId, address(this) ) ); } /** * @dev See {IERC2612-permit}. * * In cases where the free option is not a concern, deadline can simply be * set to uint(-1), so it should be seen as an optional parameter */ function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override { require(deadline >= block.timestamp, "ERC20Permit: expired deadline"); bytes32 hashStruct = keccak256( abi.encode( PERMIT_TYPEHASH, owner, spender, amount, nonces[owner]++, deadline ) ); bytes32 hash = keccak256( abi.encodePacked( '\x19\x01', DOMAIN_SEPARATOR, hashStruct ) ); address signer = ecrecover(hash, v, r, s); require( signer != address(0) && signer == owner, "ERC20Permit: invalid signature" ); _approve(owner, spender, amount); } } // File: contracts/IUSM.sol pragma solidity ^0.6.6; interface IUSM { function mint(address to, uint minUsmOut) external payable returns (uint); function burn(address from, address payable to, uint usmToBurn, uint minEthOut) external returns (uint); function fund(address to, uint minFumOut) external payable returns (uint); function defund(address from, address payable to, uint fumToBurn, uint minEthOut) external returns (uint); function defundFromFUM(address from, address payable to, uint fumToBurn, uint minEthOut) external returns (uint); } // File: contracts/Delegable.sol pragma solidity ^0.6.6; /// @dev Delegable enables users to delegate their account management to other users. /// Delegable implements addDelegateBySignature, to add delegates using a signature instead of a separate transaction. contract Delegable { event Delegate(address indexed user, address indexed delegate, bool enabled); // keccak256("Signature(address user,address delegate,uint256 nonce,uint256 deadline)"); bytes32 public immutable SIGNATURE_TYPEHASH = 0x0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb7; bytes32 public immutable DELEGABLE_DOMAIN; mapping(address => uint) public signatureCount; mapping(address => mapping(address => bool)) public delegated; constructor () public { uint256 chainId; assembly { chainId := chainid() } DELEGABLE_DOMAIN = keccak256( abi.encode( keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), keccak256(bytes('USMFUM')), keccak256(bytes('1')), chainId, address(this) ) ); } /// @dev Require that msg.sender is the account holder or a delegate modifier onlyHolderOrDelegate(address holder, string memory errorMessage) { require( msg.sender == holder || delegated[holder][msg.sender], errorMessage ); _; } /// @dev Enable a delegate to act on the behalf of caller function addDelegate(address delegate) public { _addDelegate(msg.sender, delegate); } /// @dev Stop a delegate from acting on the behalf of caller function revokeDelegate(address delegate) public { _revokeDelegate(msg.sender, delegate); } /// @dev Add a delegate through an encoded signature function addDelegateBySignature(address user, address delegate, uint deadline, uint8 v, bytes32 r, bytes32 s) public { require(deadline >= block.timestamp, 'Delegable: Signature expired'); bytes32 hashStruct = keccak256( abi.encode( SIGNATURE_TYPEHASH, user, delegate, signatureCount[user]++, deadline ) ); bytes32 digest = keccak256( abi.encodePacked( '\x19\x01', DELEGABLE_DOMAIN, hashStruct ) ); address signer = ecrecover(digest, v, r, s); require( signer != address(0) && signer == user, 'Delegable: Invalid signature' ); _addDelegate(user, delegate); } /// @dev Enable a delegate to act on the behalf of an user function _addDelegate(address user, address delegate) internal { require(!delegated[user][delegate], "Delegable: Already delegated"); delegated[user][delegate] = true; emit Delegate(user, delegate, true); } /// @dev Stop a delegate from acting on the behalf of an user function _revokeDelegate(address user, address delegate) internal { require(delegated[user][delegate], "Delegable: Already undelegated"); delegated[user][delegate] = false; emit Delegate(user, delegate, false); } } // File: contracts/WadMath.sol pragma solidity ^0.6.6; /** * @title Fixed point arithmetic library * @author Alberto Cuesta Cañada, Jacob Eliosoff, Alex Roan */ library WadMath { using SafeMath for uint; enum Round {Down, Up} uint private constant WAD = 10 ** 18; uint private constant WAD_MINUS_1 = WAD - 1; uint private constant WAD_SQUARED = WAD * WAD; uint private constant WAD_SQUARED_MINUS_1 = WAD_SQUARED - 1; uint private constant WAD_OVER_10 = WAD / 10; uint private constant WAD_OVER_20 = WAD / 20; uint private constant HALF_TO_THE_ONE_TENTH = 933032991536807416; uint private constant TWO_WAD = 2 * WAD; function wadMul(uint x, uint y, Round upOrDown) internal pure returns (uint) { return upOrDown == Round.Down ? wadMulDown(x, y) : wadMulUp(x, y); } function wadMulDown(uint x, uint y) internal pure returns (uint) { return x.mul(y) / WAD; } function wadMulUp(uint x, uint y) internal pure returns (uint) { return (x.mul(y)).add(WAD_MINUS_1) / WAD; } function wadSquaredDown(uint x) internal pure returns (uint) { return (x.mul(x)) / WAD; } function wadSquaredUp(uint x) internal pure returns (uint) { return (x.mul(x)).add(WAD_MINUS_1) / WAD; } function wadCubedDown(uint x) internal pure returns (uint) { return (x.mul(x)).mul(x) / WAD_SQUARED; } function wadCubedUp(uint x) internal pure returns (uint) { return ((x.mul(x)).mul(x)).add(WAD_SQUARED_MINUS_1) / WAD_SQUARED; } function wadDiv(uint x, uint y, Round upOrDown) internal pure returns (uint) { return upOrDown == Round.Down ? wadDivDown(x, y) : wadDivUp(x, y); } function wadDivDown(uint x, uint y) internal pure returns (uint) { return (x.mul(WAD)).div(y); } function wadDivUp(uint x, uint y) internal pure returns (uint) { return ((x.mul(WAD)).add(y - 1)).div(y); // Can use "-" instead of sub() since div(y) will catch y = 0 case anyway } function wadHalfExp(uint power) internal pure returns (uint) { return wadHalfExp(power, uint(-1)); } // Returns a loose but "gas-efficient" approximation of 0.5**power, where power is rounded to the nearest 0.1, and is // capped at maxPower. Note power is WAD-scaled (eg, 2.7364 * WAD), but maxPower is just a plain unscaled uint (eg, 10). // Negative powers are not handled (as implied by power being a uint). function wadHalfExp(uint power, uint maxPower) internal pure returns (uint) { uint powerInTenthsUnscaled = power.add(WAD_OVER_20) / WAD_OVER_10; if (powerInTenthsUnscaled / 10 > maxPower) { return 0; } return wadPow(HALF_TO_THE_ONE_TENTH, powerInTenthsUnscaled); } // Adapted from rpow() in https://github.com/dapphub/ds-math/blob/master/src/math.sol - thank you! // // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wadPow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wadSquaredDown(x); if (n % 2 != 0) { z = wadMulDown(z, x); } } } // Using Newton's method (see eg https://stackoverflow.com/a/8827111/3996653), but with WAD fixed-point math. function wadCbrtDown(uint y) internal pure returns (uint root) { if (y > 0 ) { uint newRoot = y.add(TWO_WAD) / 3; uint yTimesWadSquared = y.mul(WAD_SQUARED); do { root = newRoot; newRoot = (root + root + (yTimesWadSquared / (root * root))) / 3; } while (newRoot < root); } //require(root**3 <= y.mul(WAD_SQUARED) && y.mul(WAD_SQUARED) < (root + 1)**3); } function wadCbrtUp(uint y) internal pure returns (uint root) { root = wadCbrtDown(y); // The only case where wadCbrtUp(y) *isn't* equal to wadCbrtDown(y) + 1 is when y is a perfect cube; so check for that. // These "*"s are safe because: 1. root**3 <= y.mul(WAD_SQUARED), and 2. y.mul(WAD_SQUARED) is calculated (safely) above. if (root * root * root != y * WAD_SQUARED ) { ++root; } //require((root - 1)**3 < y.mul(WAD_SQUARED) && y.mul(WAD_SQUARED) <= root**3); } } // File: @openzeppelin/contracts/access/Ownable.sol pragma solidity ^0.6.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/MinOut.sol pragma solidity ^0.6.6; library MinOut { function parseMinTokenOut(uint ethIn) internal pure returns (uint minTokenOut) { uint minPrice = ethIn % 100000000000; if (minPrice != 0 && minPrice < 10000000) { minTokenOut = ethIn * minPrice / 100; } } function parseMinEthOut(uint tokenIn) internal pure returns (uint minEthOut) { uint maxPrice = tokenIn % 100000000000; if (maxPrice != 0 && maxPrice < 10000000) { minEthOut = tokenIn * 100 / maxPrice; } } } // File: contracts/FUM.sol pragma solidity ^0.6.6; /** * @title FUM Token * @author Alberto Cuesta Cañada, Jacob Eliosoff, Alex Roan * * @notice This should be owned by the stablecoin. */ contract FUM is ERC20Permit, Ownable { IUSM public immutable usm; constructor(IUSM usm_) public ERC20Permit("Minimal Funding", "FUM") { usm = usm_; } /** * @notice If anyone sends ETH here, assume they intend it as a `fund`. * If decimals 8 to 11 (included) of the amount of Ether received are `0000` then the next 7 will * be parsed as the minimum Ether price accepted, with 2 digits before and 5 digits after the comma. */ receive() external payable { usm.fund{ value: msg.value }(msg.sender, MinOut.parseMinTokenOut(msg.value)); } /** * @notice If a user sends FUM tokens directly to this contract (or to the USM contract), assume they intend it as a `defund`. * If using `transfer`/`transferFrom` as `defund`, and if decimals 8 to 11 (included) of the amount transferred received * are `0000` then the next 7 will be parsed as the maximum FUM price accepted, with 5 digits before and 2 digits after the comma. */ function _transfer(address sender, address recipient, uint256 amount) internal override { if (recipient == address(this) || recipient == address(usm) || recipient == address(0)) { usm.defundFromFUM(sender, payable(sender), amount, MinOut.parseMinEthOut(amount)); } else { super._transfer(sender, recipient, amount); } } /** * @notice Mint new FUM to the _recipient * * @param _recipient address to mint to * @param _amount amount to mint */ function mint(address _recipient, uint _amount) external onlyOwner { _mint(_recipient, _amount); } /** * @notice Burn FUM from _holder * * @param _holder address to burn from * @param _amount amount to burn */ function burn(address _holder, uint _amount) external onlyOwner { _burn(_holder, _amount); } } // File: contracts/oracles/Oracle.sol pragma solidity ^0.6.6; abstract contract Oracle { function latestPrice() public virtual view returns (uint price); // Prices must be WAD-scaled - 18 decimal places /** * @dev This pure virtual implementation, which is intended to be (optionally) overridden by stateful implementations, * confuses solhint into giving a "Function state mutability can be restricted to view" warning. Unfortunately there seems * to be no elegant/gas-free workaround as yet: see https://github.com/ethereum/solidity/issues/3529. */ function cacheLatestPrice() public virtual returns (uint price) { price = latestPrice(); // Default implementation doesn't do any cacheing, just returns price. But override as needed } } // File: contracts/USMTemplate.sol pragma solidity ^0.6.6; // import "@nomiclabs/buidler/console.sol"; /** * @title USMTemplate * @author Alberto Cuesta Cañada, Jacob Eliosoff, Alex Roan * @notice Concept by Jacob Eliosoff (@jacob-eliosoff). * * This abstract USM contract must be inherited by a concrete implementation, that also adds an Oracle implementation - eg, by * also inheriting a concrete Oracle implementation. See USM (and MockUSM) for an example. * * We use this inheritance-based design (rather than the more natural, and frankly normally more correct, composition-based design * of storing the Oracle here as a variable), because inheriting the Oracle makes all the latestPrice() calls *internal* rather * than calls to a separate oracle contract (or multiple contracts) - which leads to a significant saving in gas. */ abstract contract USMTemplate is IUSM, Oracle, ERC20Permit, Delegable { using Address for address payable; using SafeMath for uint; using WadMath for uint; enum Side {Buy, Sell} event MinFumBuyPriceChanged(uint previous, uint latest); event BuySellAdjustmentChanged(uint previous, uint latest); uint public constant WAD = 10 ** 18; uint public constant MAX_DEBT_RATIO = WAD * 8 / 10; // 80% uint public constant MIN_FUM_BUY_PRICE_HALF_LIFE = 1 days; // Solidity for 1 * 24 * 60 * 60 uint public constant BUY_SELL_ADJUSTMENT_HALF_LIFE = 1 minutes; // Solidity for 1 * 60 FUM public immutable fum; uint256 deadline; // Second at which the trial expires and `mint` and `fund` get disabled. struct TimedValue { uint32 timestamp; uint224 value; } TimedValue public minFumBuyPriceStored; TimedValue public buySellAdjustmentStored = TimedValue({ timestamp: 0, value: uint224(WAD) }); constructor() public ERC20Permit("Minimal USD", "USM") { fum = new FUM(this); deadline = now + (60 * 60 * 24 * 28); // Four weeks into the future } /** EXTERNAL TRANSACTIONAL FUNCTIONS **/ /** * @notice Mint new USM, sending it to the given address, and only if the amount minted >= minUsmOut. The amount of ETH is * passed in as msg.value. * @param to address to send the USM to. * @param minUsmOut Minimum accepted USM for a successful mint. */ function mint(address to, uint minUsmOut) external payable override returns (uint usmOut) { usmOut = _mintUsm(to, minUsmOut); } /** * @dev Burn USM in exchange for ETH. * @param from address to deduct the USM from. * @param to address to send the ETH to. * @param usmToBurn Amount of USM to burn. * @param minEthOut Minimum accepted ETH for a successful burn. */ function burn(address from, address payable to, uint usmToBurn, uint minEthOut) external override onlyHolderOrDelegate(from, "Only holder or delegate") returns (uint ethOut) { ethOut = _burnUsm(from, to, usmToBurn, minEthOut); } /** * @notice Funds the pool with ETH, minting new FUM and sending it to the given address, but only if the amount minted >= * minFumOut. The amount of ETH is passed in as msg.value. * @param to address to send the FUM to. * @param minFumOut Minimum accepted FUM for a successful fund. */ function fund(address to, uint minFumOut) external payable override returns (uint fumOut) { fumOut = _fundFum(to, minFumOut); } /** * @notice Defunds the pool by redeeming FUM in exchange for equivalent ETH from the pool. * @param from address to deduct the FUM from. * @param to address to send the ETH to. * @param fumToBurn Amount of FUM to burn. * @param minEthOut Minimum accepted ETH for a successful defund. */ function defund(address from, address payable to, uint fumToBurn, uint minEthOut) external override onlyHolderOrDelegate(from, "Only holder or delegate") returns (uint ethOut) { ethOut = _defundFum(from, to, fumToBurn, minEthOut); } /** * @notice Defunds the pool by redeeming FUM from an arbitrary address in exchange for equivalent ETH from the pool. * Called only by the FUM contract, when FUM is sent to it. * @param from address to deduct the FUM from. * @param to address to send the ETH to. * @param fumToBurn Amount of FUM to burn. * @param minEthOut Minimum accepted ETH for a successful defund. */ function defundFromFUM(address from, address payable to, uint fumToBurn, uint minEthOut) external override returns (uint ethOut) { require(msg.sender == address(fum), "Restricted to FUM"); ethOut = _defundFum(from, to, fumToBurn, minEthOut); } /** * @notice If anyone sends ETH here, assume they intend it as a `mint`. * If decimals 8 to 11 (included) of the amount of Ether received are `0000` then the next 7 will * be parsed as the minimum Ether price accepted, with 2 digits before and 5 digits after the comma. */ receive() external payable { _mintUsm(msg.sender, MinOut.parseMinTokenOut(msg.value)); } /** * @notice If a user sends USM tokens directly to this contract (or to the FUM contract), assume they intend it as a `burn`. * If using `transfer`/`transferFrom` as `burn`, and if decimals 8 to 11 (included) of the amount transferred received * are `0000` then the next 7 will be parsed as the maximum USM price accepted, with 5 digits before and 2 digits after the comma. */ function _transfer(address sender, address recipient, uint256 amount) internal override { if (recipient == address(this) || recipient == address(fum) || recipient == address(0)) { _burnUsm(sender, payable(sender), amount, MinOut.parseMinEthOut(amount)); } else { super._transfer(sender, recipient, amount); } } /** INTERNAL TRANSACTIONAL FUNCTIONS */ function _mintUsm(address to, uint minUsmOut) internal returns (uint usmOut) { // 1. Check that fund() has been called first - no minting before funding: uint rawEthInPool = ethPool(); uint ethInPool = rawEthInPool.sub(msg.value); // Backing out the ETH just received, which our calculations should ignore require(ethInPool > 0, "Fund before minting"); // 2. Calculate usmOut: uint ethUsmPrice = cacheLatestPrice(); uint usmTotalSupply = totalSupply(); uint oldDebtRatio = debtRatio(ethUsmPrice, ethInPool, usmTotalSupply); usmOut = usmFromMint(ethUsmPrice, msg.value, ethInPool, usmTotalSupply, oldDebtRatio); require(usmOut >= minUsmOut, "Limit not reached"); // 3. Update buySellAdjustmentStored and mint the user's new USM: uint newDebtRatio = debtRatio(ethUsmPrice, rawEthInPool, usmTotalSupply.add(usmOut)); _updateBuySellAdjustment(oldDebtRatio, newDebtRatio, buySellAdjustment()); _mint(to, usmOut); require(now <= deadline, "Trial expired, remove assets"); require(msg.value <= 1e18, "Capped at 1 ETH per tx"); require(ethPool() <= 1e20, "Capped at 100 pooled ETH"); } function _burnUsm(address from, address payable to, uint usmToBurn, uint minEthOut) internal returns (uint ethOut) { // 1. Calculate ethOut: uint ethUsmPrice = cacheLatestPrice(); uint ethInPool = ethPool(); uint usmTotalSupply = totalSupply(); uint oldDebtRatio = debtRatio(ethUsmPrice, ethInPool, usmTotalSupply); ethOut = ethFromBurn(ethUsmPrice, usmToBurn, ethInPool, usmTotalSupply, oldDebtRatio); require(ethOut >= minEthOut, "Limit not reached"); // 2. Burn the input USM, update buySellAdjustmentStored, and return the user's ETH: uint newDebtRatio = debtRatio(ethUsmPrice, ethInPool.sub(ethOut), usmTotalSupply.sub(usmToBurn)); require(newDebtRatio <= WAD, "Debt ratio > 100%"); _burn(from, usmToBurn); _updateBuySellAdjustment(oldDebtRatio, newDebtRatio, buySellAdjustment()); to.sendValue(ethOut); } function _fundFum(address to, uint minFumOut) internal returns (uint fumOut) { // 1. Refresh mfbp: uint ethUsmPrice = cacheLatestPrice(); uint rawEthInPool = ethPool(); uint ethInPool = rawEthInPool.sub(msg.value); // Backing out the ETH just received, which our calculations should ignore uint usmTotalSupply = totalSupply(); uint oldDebtRatio = debtRatio(ethUsmPrice, ethInPool, usmTotalSupply); uint fumTotalSupply = fum.totalSupply(); _updateMinFumBuyPrice(oldDebtRatio, ethInPool, fumTotalSupply); // 2. Calculate fumOut: uint adjustment = buySellAdjustment(); fumOut = fumFromFund(ethUsmPrice, msg.value, ethInPool, usmTotalSupply, fumTotalSupply, adjustment); require(fumOut >= minFumOut, "Limit not reached"); // 3. Update buySellAdjustmentStored and mint the user's new FUM: uint newDebtRatio = debtRatio(ethUsmPrice, rawEthInPool, usmTotalSupply); _updateBuySellAdjustment(oldDebtRatio, newDebtRatio, adjustment); fum.mint(to, fumOut); require(now <= deadline, "Trial expired, remove assets"); require(msg.value <= 1e18, "Capped at 1 ETH per tx"); require(ethPool() <= 1e20, "Capped at 100 pooled ETH"); } function _defundFum(address from, address payable to, uint fumToBurn, uint minEthOut) internal returns (uint ethOut) { // 1. Calculate ethOut: uint ethUsmPrice = cacheLatestPrice(); uint ethInPool = ethPool(); uint usmTotalSupply = totalSupply(); uint oldDebtRatio = debtRatio(ethUsmPrice, ethInPool, usmTotalSupply); ethOut = ethFromDefund(ethUsmPrice, fumToBurn, ethInPool, usmTotalSupply); require(ethOut >= minEthOut, "Limit not reached"); // 2. Burn the input FUM, update buySellAdjustmentStored, and return the user's ETH: uint newDebtRatio = debtRatio(ethUsmPrice, ethInPool.sub(ethOut), usmTotalSupply); require(newDebtRatio <= MAX_DEBT_RATIO, "Debt ratio > max"); fum.burn(from, fumToBurn); _updateBuySellAdjustment(oldDebtRatio, newDebtRatio, buySellAdjustment()); to.sendValue(ethOut); } /** * @notice Set the min FUM price, based on the current oracle price and debt ratio. Emits a MinFumBuyPriceChanged event. * @dev The logic for calculating a new minFumBuyPrice is as follows. We want to set it to the FUM price, in ETH terms, at * which debt ratio was exactly MAX_DEBT_RATIO. So we can assume: * * usmToEth(totalSupply()) / ethPool() = MAX_DEBT_RATIO, or in other words: * usmToEth(totalSupply()) = MAX_DEBT_RATIO * ethPool() * * And with this assumption, we calculate the FUM price (buffer / FUM qty) like so: * * minFumBuyPrice = ethBuffer() / fum.totalSupply() * = (ethPool() - usmToEth(totalSupply())) / fum.totalSupply() * = (ethPool() - (MAX_DEBT_RATIO * ethPool())) / fum.totalSupply() * = (1 - MAX_DEBT_RATIO) * ethPool() / fum.totalSupply() */ function _updateMinFumBuyPrice(uint debtRatio_, uint ethInPool, uint fumTotalSupply) internal { uint previous = minFumBuyPriceStored.value; if (debtRatio_ <= MAX_DEBT_RATIO) { // We've dropped below (or were already below, whatev) max debt ratio if (previous != 0) { minFumBuyPriceStored.timestamp = 0; // Clear mfbp minFumBuyPriceStored.value = 0; emit MinFumBuyPriceChanged(previous, 0); } } else if (previous == 0) { // We were < max debt ratio, but have now crossed above - so set mfbp // See reasoning in @dev comment above minFumBuyPriceStored.timestamp = uint32(block.timestamp); minFumBuyPriceStored.value = uint224((WAD - MAX_DEBT_RATIO).wadMulUp(ethInPool).wadDivUp(fumTotalSupply)); emit MinFumBuyPriceChanged(previous, minFumBuyPriceStored.value); } } /** * @notice Update the buy/sell adjustment factor, as of the current block time, after a price-moving operation. * @param oldDebtRatio The debt ratio before the operation (eg, mint()) was done * @param newDebtRatio The current, post-op debt ratio */ function _updateBuySellAdjustment(uint oldDebtRatio, uint newDebtRatio, uint oldAdjustment) internal { // Skip this if either the old or new debt ratio == 0. Normally this will only happen on the system's first couple of // calls, but in principle it could happen later if every single USM holder burns all their USM. This seems // vanishingly unlikely though if the system gets any uptake at all, and anyway if it does happen it will just mean a // couple of skipped updates to the buySellAdjustment - no big deal. if (oldDebtRatio != 0 && newDebtRatio != 0) { uint previous = buySellAdjustmentStored.value; // Not nec the same as oldAdjustment, because of the time decay! // Eg: if a user operation reduced debt ratio from 70% to 50%, it was either a fund() or a burn(). These are both // "long-ETH" operations. So we can take (old / new)**2 = (70% / 50%)**2 = 1.4**2 = 1.96 as the ratio by which to // increase buySellAdjustment, which is intended as a measure of "how long-ETH recent user activity has been": uint newAdjustment = (oldAdjustment.mul(oldDebtRatio).mul(oldDebtRatio) / newDebtRatio) / newDebtRatio; buySellAdjustmentStored.timestamp = uint32(block.timestamp); buySellAdjustmentStored.value = uint224(newAdjustment); emit BuySellAdjustmentChanged(previous, newAdjustment); } } /** PUBLIC AND INTERNAL VIEW FUNCTIONS **/ /** * @notice Total amount of ETH in the pool (ie, in the contract). * @return pool ETH pool */ function ethPool() public view returns (uint pool) { pool = address(this).balance; } /** * @notice Calculate the amount of ETH in the buffer. * @return buffer ETH buffer */ function ethBuffer(uint ethUsmPrice, uint ethInPool, uint usmTotalSupply, WadMath.Round upOrDown) internal pure returns (int buffer) { // Reverse the input upOrDown, since we're using it for usmToEth(), which will be *subtracted* from ethInPool below: WadMath.Round downOrUp = (upOrDown == WadMath.Round.Down ? WadMath.Round.Up : WadMath.Round.Down); buffer = int(ethInPool) - int(usmToEth(ethUsmPrice, usmTotalSupply, downOrUp)); require(buffer <= int(ethInPool), "Underflow error"); } /** * @notice Calculate debt ratio for a given eth to USM price: ratio of the outstanding USM (amount of USM in total supply), to * the current ETH pool amount. * @return ratio Debt ratio */ function debtRatio(uint ethUsmPrice, uint ethInPool, uint usmTotalSupply) internal pure returns (uint ratio) { uint ethPoolValueInUsd = ethInPool.wadMulDown(ethUsmPrice); ratio = (ethInPool == 0 ? 0 : usmTotalSupply.wadDivUp(ethPoolValueInUsd)); } /** * @notice Convert ETH amount to USM using a ETH/USD price. * @param ethAmount The amount of ETH to convert * @return usmOut The amount of USM */ function ethToUsm(uint ethUsmPrice, uint ethAmount, WadMath.Round upOrDown) internal pure returns (uint usmOut) { usmOut = ethAmount.wadMul(ethUsmPrice, upOrDown); } /** * @notice Convert USM amount to ETH using a ETH/USD price. * @param usmAmount The amount of USM to convert * @return ethOut The amount of ETH */ function usmToEth(uint ethUsmPrice, uint usmAmount, WadMath.Round upOrDown) internal pure returns (uint ethOut) { ethOut = usmAmount.wadDiv(ethUsmPrice, upOrDown); } /** * @notice Calculate the *marginal* price of USM (in ETH terms) - that is, of the next unit, before the price start sliding. * @return price USM price in ETH terms */ function usmPrice(Side side, uint ethUsmPrice, uint debtRatio_) internal view returns (uint price) { WadMath.Round upOrDown = (side == Side.Buy ? WadMath.Round.Up : WadMath.Round.Down); price = usmToEth(ethUsmPrice, WAD, upOrDown); uint adjustment = buySellAdjustment(); if (debtRatio_ <= WAD) { if ((side == Side.Buy && adjustment < WAD) || (side == Side.Sell && adjustment > WAD)) { price = price.wadDiv(adjustment, upOrDown); } } else { // See comment at the bottom of usmFromMint() explaining this special case where debtRatio > 100% if ((side == Side.Buy && adjustment > WAD) || (side == Side.Sell && adjustment < WAD)) { price = price.wadMul(adjustment, upOrDown); } } } /** * @notice Calculate the *marginal* price of FUM (in ETH terms) - that is, of the next unit, before the price start sliding. * @return price FUM price in ETH terms */ function fumPrice(Side side, uint ethUsmPrice, uint ethInPool, uint usmTotalSupply, uint fumTotalSupply, uint adjustment) internal view returns (uint price) { WadMath.Round upOrDown = (side == Side.Buy ? WadMath.Round.Up : WadMath.Round.Down); if (fumTotalSupply == 0) { return usmToEth(ethUsmPrice, WAD, upOrDown); // if no FUM issued yet, default fumPrice to 1 USD (in ETH terms) } int buffer = ethBuffer(ethUsmPrice, ethInPool, usmTotalSupply, upOrDown); price = (buffer <= 0 ? 0 : uint(buffer).wadDiv(fumTotalSupply, upOrDown)); if (side == Side.Buy) { if (adjustment > WAD) { price = price.wadMulUp(adjustment); } // Floor the buy price at minFumBuyPrice: uint mfbp = minFumBuyPrice(); if (price < mfbp) { price = mfbp; } } else { if (adjustment < WAD) { price = price.wadMulDown(adjustment); } } } /** * @notice How much USM a minter currently gets back for ethIn ETH, accounting for adjustment and sliding prices. * @param ethIn The amount of ETH passed to mint() * @return usmOut The amount of USM to receive in exchange */ function usmFromMint(uint ethUsmPrice, uint ethIn, uint ethQty0, uint usmQty0, uint debtRatio0) internal view returns (uint usmOut) { uint usmPrice0 = usmPrice(Side.Buy, ethUsmPrice, debtRatio0); uint ethQty1 = ethQty0.add(ethIn); if (usmQty0 == 0) { // No USM in the system, so debtRatio() == 0 which breaks the integral below - skip sliding-prices this time: usmOut = ethIn.wadDivDown(usmPrice0); } else if (debtRatio0 <= WAD) { // Mint USM at a sliding-up USM price (ie, at a sliding-down ETH price). **BASIC RULE:** anytime debtRatio() // changes by factor k (here > 1), ETH price changes by factor 1/k**2 (ie, USM price, in ETH terms, changes by // factor k**2). (Earlier versions of this logic scaled ETH price based on change in ethPool(), or change in // ethPool()**2: the latter gives simpler math - no cbrt() - but doesn't let mint/burn offset fund/defund, which // debtRatio()**2 nicely does.) // Math: this is an integral - sum of all USM minted at a sliding-down ETH price: // u - u_0 = ((((e / e_0)**3 - 1) * e_0 / ubp_0 + u_0) * u_0**2)**(1/3) - u_0 uint integralFirstPart = (ethQty1.wadDivDown(ethQty0).wadCubedDown().sub(WAD)).mul(ethQty0).div(usmPrice0); usmOut = (integralFirstPart.add(usmQty0)).wadMulDown(usmQty0.wadSquaredDown()).wadCbrtDown().sub(usmQty0); } else { // Here we have the special, unusual case where we're minting while debt ratio > 100%. In this case (only), // minting will actually *reduce* debt ratio, whereas normally it increases it. (In short: minting always pushes // debt ratio closer to 100%.) Because debt ratio is decreasing as we buy, and USM buy price must *increase* as we // buy, we need to make USM price grow proportionally to (1 / change in debt ratio)**2, rather than the usual // (1 / change in debt ratio)**2 above. This gives the following different integral: // x = e0 * (e - e0) / (u0 * pu0) // u - u_0 = u0 * x / (e - x) uint integralFirstPart = ethQty0.mul(ethIn).div(usmQty0.wadMulUp(usmPrice0)); usmOut = usmQty0.mul(integralFirstPart).div(ethQty1.sub(integralFirstPart)); } } /** * @notice How much ETH a burner currently gets from burning usmIn USM, accounting for adjustment and sliding prices. * @param usmIn The amount of USM passed to burn() * @return ethOut The amount of ETH to receive in exchange */ function ethFromBurn(uint ethUsmPrice, uint usmIn, uint ethQty0, uint usmQty0, uint debtRatio0) internal view returns (uint ethOut) { // Burn USM at a sliding-down USM price (ie, a sliding-up ETH price): uint usmPrice0 = usmPrice(Side.Sell, ethUsmPrice, debtRatio0); uint usmQty1 = usmQty0.sub(usmIn); // Math: this is an integral - sum of all USM burned at a sliding price. Follows the same mathematical invariant as // above: if debtRatio() *= k (here, k < 1), ETH price *= 1/k**2, ie, USM price in ETH terms *= k**2. // e_0 - e = e_0 - (e_0**2 * (e_0 - usp_0 * u_0 * (1 - (u / u_0)**3)))**(1/3) uint integralFirstPart = usmPrice0.wadMulDown(usmQty0).wadMulDown(WAD.sub(usmQty1.wadDivUp(usmQty0).wadCubedUp())); ethOut = ethQty0.sub(ethQty0.wadSquaredUp().wadMulUp(ethQty0.sub(integralFirstPart)).wadCbrtUp()); } /** * @notice How much FUM a funder currently gets back for ethIn ETH, accounting for adjustment and sliding prices. * @param ethIn The amount of ETH passed to fund() * @return fumOut The amount of FUM to receive in exchange */ function fumFromFund(uint ethUsmPrice, uint ethIn, uint ethQty0, uint usmQty0, uint fumQty0, uint adjustment) internal view returns (uint fumOut) { // Create FUM at a sliding-up FUM price: uint fumPrice0 = fumPrice(Side.Buy, ethUsmPrice, ethQty0, usmQty0, fumQty0, adjustment); if (usmQty0 == 0) { // No USM in the system - skip sliding-prices: fumOut = ethIn.wadDivDown(fumPrice0); } else { // Math: f - f_0 = e_0 * (e - e_0) / (e * fbp_0) uint ethQty1 = ethQty0.add(ethIn); fumOut = ethQty0.mul(ethIn).div(ethQty1.wadMulUp(fumPrice0)); } } /** * @notice How much ETH a defunder currently gets back for fumIn FUM, accounting for adjustment and sliding prices. * @param fumIn The amount of FUM passed to defund() * @return ethOut The amount of ETH to receive in exchange */ function ethFromDefund(uint ethUsmPrice, uint fumIn, uint ethQty0, uint usmQty0) internal view returns (uint ethOut) { // Burn FUM at a sliding-down FUM price: uint fumQty0 = fum.totalSupply(); uint fumPrice0 = fumPrice(Side.Sell, ethUsmPrice, ethQty0, usmQty0, fumQty0, buySellAdjustment()); if (usmQty0 == 0) { // No USM in the system - skip sliding-prices: ethOut = fumIn.wadMulDown(fumPrice0); } else { // Math: e_0 - e = e_0 * (f_0 - f) * fsp_0 / (e_0 + (f_0 - f) * fsp_0) ethOut = ethQty0.mul(fumIn.wadMulDown(fumPrice0)).div(ethQty0.add(fumIn.wadMulUp(fumPrice0))); } } /** * @notice The current min FUM buy price, equal to the stored value decayed by time since minFumBuyPriceTimestamp. * @return mfbp The minFumBuyPrice, in ETH terms */ function minFumBuyPrice() public view returns (uint mfbp) { if (minFumBuyPriceStored.value != 0) { uint numHalvings = block.timestamp.sub(minFumBuyPriceStored.timestamp).wadDivDown(MIN_FUM_BUY_PRICE_HALF_LIFE); uint decayFactor = numHalvings.wadHalfExp(); mfbp = uint256(minFumBuyPriceStored.value).wadMulUp(decayFactor); } // Otherwise just returns 0 } /** * @notice The current buy/sell adjustment, equal to the stored value decayed by time since buySellAdjustmentTimestamp. This * adjustment is intended as a measure of "how long-ETH recent user activity has been", so that we can slide price * accordingly: if recent activity was mostly long-ETH (fund() and burn()), raise FUM buy price/reduce USM sell price; if * recent activity was short-ETH (defund() and mint()), reduce FUM sell price/raise USM buy price. We use "it reduced debt * ratio" as a rough proxy for "the operation was long-ETH". * * (There is one odd case: when debt ratio > 100%, a *short*-ETH mint() will actually reduce debt ratio. This does no real * harm except to make fast-succession mint()s and fund()s in such > 100% cases a little more expensive than they would be.) * * @return adjustment The sliding-price buy/sell adjustment */ function buySellAdjustment() public view returns (uint adjustment) { uint numHalvings = block.timestamp.sub(buySellAdjustmentStored.timestamp).wadDivDown(BUY_SELL_ADJUSTMENT_HALF_LIFE); uint decayFactor = numHalvings.wadHalfExp(10); // Here we use the idea that for any b and 0 <= p <= 1, we can crudely approximate b**p by 1 + (b-1)p = 1 + bp - p. // Eg: 0.6**0.5 pulls 0.6 "about halfway" to 1 (0.8); 0.6**0.25 pulls 0.6 "about 3/4 of the way" to 1 (0.9). // So b**p =~ b + (1-p)(1-b) = b + 1 - b - p + bp = 1 + bp - p. // (Don't calculate it as 1 + (b-1)p because we're using uints, b-1 can be negative!) adjustment = WAD.add(uint256(buySellAdjustmentStored.value).wadMulDown(decayFactor)).sub(decayFactor); } /** EXTERNAL VIEW FUNCTIONS */ /** * @notice Calculate the amount of ETH in the buffer. * @return buffer ETH buffer */ function ethBuffer(WadMath.Round upOrDown) external view returns (int buffer) { buffer = ethBuffer(latestPrice(), ethPool(), totalSupply(), upOrDown); } /** * @notice Convert ETH amount to USM using the latest oracle ETH/USD price. * @param ethAmount The amount of ETH to convert * @return usmOut The amount of USM */ function ethToUsm(uint ethAmount, WadMath.Round upOrDown) external view returns (uint usmOut) { usmOut = ethToUsm(latestPrice(), ethAmount, upOrDown); } /** * @notice Convert USM amount to ETH using the latest oracle ETH/USD price. * @param usmAmount The amount of USM to convert * @return ethOut The amount of ETH */ function usmToEth(uint usmAmount, WadMath.Round upOrDown) external view returns (uint ethOut) { ethOut = usmToEth(latestPrice(), usmAmount, upOrDown); } /** * @notice Calculate debt ratio. * @return ratio Debt ratio */ function debtRatio() external view returns (uint ratio) { ratio = debtRatio(latestPrice(), ethPool(), totalSupply()); } /** * @notice Calculate the *marginal* price of USM (in ETH terms) - that is, of the next unit, before the price start sliding. * @return price USM price in ETH terms */ function usmPrice(Side side) external view returns (uint price) { uint ethUsdPrice = latestPrice(); price = usmPrice(side, ethUsdPrice, debtRatio(ethUsdPrice, ethPool(), totalSupply())); } /** * @notice Calculate the *marginal* price of FUM (in ETH terms) - that is, of the next unit, before the price start sliding. * @return price FUM price in ETH terms */ function fumPrice(Side side) external view returns (uint price) { price = fumPrice(side, latestPrice(), ethPool(), totalSupply(), fum.totalSupply(), buySellAdjustment()); } } // File: @chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol pragma solidity >=0.6.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File: contracts/oracles/ChainlinkOracle.sol pragma solidity ^0.6.6; /** * @title ChainlinkOracle */ contract ChainlinkOracle is Oracle { using SafeMath for uint; uint private constant SCALE_FACTOR = 10 ** 10; // Since Chainlink has 8 dec places, and latestPrice() needs 18 AggregatorV3Interface private aggregator; constructor(AggregatorV3Interface aggregator_) public { aggregator = aggregator_; } /** * @notice Retrieve the latest price of the price oracle. * @return price */ function latestPrice() public virtual override view returns (uint price) { price = latestChainlinkPrice(); } function latestChainlinkPrice() public view returns (uint price) { (, int rawPrice,,,) = aggregator.latestRoundData(); price = uint(rawPrice).mul(SCALE_FACTOR); // TODO: Cast safely } } // File: contracts/oracles/CompoundOpenOracle.sol pragma solidity ^0.6.6; interface UniswapAnchoredView { function price(string calldata symbol) external view returns (uint); } /** * @title CompoundOpenOracle */ contract CompoundOpenOracle is Oracle { using SafeMath for uint; uint private constant SCALE_FACTOR = 10 ** 12; // Since Compound has 6 dec places, and latestPrice() needs 18 UniswapAnchoredView private anchoredView; constructor(UniswapAnchoredView anchoredView_) public { anchoredView = anchoredView_; } /** * @notice Retrieve the latest price of the price oracle. * @return price */ function latestPrice() public virtual override view returns (uint price) { price = latestCompoundPrice(); } function latestCompoundPrice() public view returns (uint price) { price = anchoredView.price("ETH").mul(SCALE_FACTOR); } } // File: @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } // File: contracts/oracles/OurUniswapV2TWAPOracle.sol pragma solidity ^0.6.6; contract OurUniswapV2TWAPOracle is Oracle { using SafeMath for uint; /** * MIN_TWAP_PERIOD plays two roles: * * 1. Minimum age of the stored CumulativePrice we calculate our current TWAP vs. Eg, if one of our stored prices is from * 5 secs ago, and the other from 10 min ago, we should calculate TWAP vs the 10-min-old one, since a 5-second TWAP is too * short - relatively easy to manipulate. * * 2. Minimum time gap between stored CumulativePrices. Eg, if we stored one 5 seconds ago, we don't need to store another * one now - and shouldn't, since then if someone else made a TWAP call a few seconds later, both stored prices would be * too recent to calculate a robust TWAP. * * These roles could in principle be separated, eg: "Require the stored price we calculate TWAP from to be >= 2 minutes * old, but leave >= 10 minutes before storing a new price." But for simplicity we keep them the same. */ uint public constant MIN_TWAP_PERIOD = 2 minutes; // Uniswap stores its cumulative prices in "FixedPoint.uq112x112" format - 112-bit fixed point: uint public constant UNISWAP_CUM_PRICE_SCALE_FACTOR = 2 ** 112; uint private constant UINT32_MAX = 2 ** 32 - 1; // Should really be type(uint32).max, but that needs Solidity 0.6.8... uint private constant UINT224_MAX = 2 ** 224 - 1; // Ditto, type(uint224).max IUniswapV2Pair immutable uniswapPair; uint immutable token0Decimals; uint immutable token1Decimals; bool immutable tokensInReverseOrder; uint immutable scaleFactor; struct CumulativePrice { uint32 timestamp; uint224 priceSeconds; // See cumulativePrice() below for an explanation of "priceSeconds" } /** * We store two CumulativePrices, A and B, without specifying which is more recent. This is so that we only need to do one * SSTORE each time we save a new one: we can inspect them later to figure out which is newer - see orderedStoredPrices(). */ CumulativePrice private storedPriceA; CumulativePrice private storedPriceB; /** * Example pairs to pass in: * ETH/USDT: 0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852, false, 18, 6 (WETH reserve is stored w/ 18 dec places, USDT w/ 18) * USDC/ETH: 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc, true, 6, 18 (USDC reserve is stored w/ 6 dec places, WETH w/ 18) * DAI/ETH: 0xa478c2975ab1ea89e8196811f51a7b7ade33eb11, true, 18, 18 (DAI reserve is stored w/ 18 dec places, WETH w/ 18) */ constructor(IUniswapV2Pair uniswapPair_, uint token0Decimals_, uint token1Decimals_, bool tokensInReverseOrder_) public { uniswapPair = uniswapPair_; token0Decimals = token0Decimals_; token1Decimals = token1Decimals_; tokensInReverseOrder = tokensInReverseOrder_; (uint aDecimals, uint bDecimals) = tokensInReverseOrder_ ? (token1Decimals_, token0Decimals_) : (token0Decimals_, token1Decimals_); scaleFactor = 10 ** aDecimals.add(18).sub(bDecimals); } function cacheLatestPrice() public virtual override returns (uint price) { (CumulativePrice storage olderStoredPrice, CumulativePrice storage newerStoredPrice) = orderedStoredPrices(); uint timestamp; uint priceSeconds; (price, timestamp, priceSeconds) = _latestPrice(newerStoredPrice); // Store the latest cumulative price, if it's been long enough since the latest stored price: if (areNewAndStoredPriceFarEnoughApart(timestamp, newerStoredPrice)) { storeCumulativePrice(timestamp, priceSeconds, olderStoredPrice); } } function latestPrice() public virtual override view returns (uint price) { price = latestUniswapTWAPPrice(); } function latestUniswapTWAPPrice() public view returns (uint price) { (, CumulativePrice storage newerStoredPrice) = orderedStoredPrices(); (price, , ) = _latestPrice(newerStoredPrice); } function _latestPrice(CumulativePrice storage newerStoredPrice) internal view returns (uint price, uint timestamp, uint priceSeconds) { (timestamp, priceSeconds) = cumulativePrice(); // Now that we have the current cum price, subtract-&-divide the stored one, to get the TWAP price: CumulativePrice storage refPrice = storedPriceToCompareVs(timestamp, newerStoredPrice); price = calculateTWAP(timestamp, priceSeconds, uint(refPrice.timestamp), uint(refPrice.priceSeconds)); } function storeCumulativePrice(uint timestamp, uint priceSeconds, CumulativePrice storage olderStoredPrice) internal { require(timestamp <= UINT32_MAX, "timestamp overflow"); require(priceSeconds <= UINT224_MAX, "priceSeconds overflow"); // (Note: this assignment only stores because olderStoredPrice has modifier "storage" - ie, store by reference!) (olderStoredPrice.timestamp, olderStoredPrice.priceSeconds) = (uint32(timestamp), uint224(priceSeconds)); } function storedPriceToCompareVs(uint newTimestamp, CumulativePrice storage newerStoredPrice) internal view returns (CumulativePrice storage refPrice) { bool aAcceptable = areNewAndStoredPriceFarEnoughApart(newTimestamp, storedPriceA); bool bAcceptable = areNewAndStoredPriceFarEnoughApart(newTimestamp, storedPriceB); if (aAcceptable) { if (bAcceptable) { refPrice = newerStoredPrice; // Neither is *too* recent, so return the fresher of the two } else { refPrice = storedPriceA; // Only A is acceptable } } else if (bAcceptable) { refPrice = storedPriceB; // Only B is acceptable } else { revert("Both stored prices too recent"); } } function orderedStoredPrices() internal view returns (CumulativePrice storage olderStoredPrice, CumulativePrice storage newerStoredPrice) { (olderStoredPrice, newerStoredPrice) = storedPriceB.timestamp > storedPriceA.timestamp ? (storedPriceA, storedPriceB) : (storedPriceB, storedPriceA); } function areNewAndStoredPriceFarEnoughApart(uint newTimestamp, CumulativePrice storage storedPrice) internal view returns (bool farEnough) { farEnough = newTimestamp >= storedPrice.timestamp + MIN_TWAP_PERIOD; // No risk of overflow on a uint32 } /** * @return timestamp Timestamp at which Uniswap stored the priceSeconds. * @return priceSeconds Our pair's cumulative "price-seconds", using Uniswap's TWAP logic. Eg, if at time t0 * priceSeconds = 10,000,000 (returned here as 10,000,000 * 10**18, ie, in WAD fixed-point format), and during the 30 * seconds between t0 and t1 = t0 + 30, the price is $45.67, then at time t1, priceSeconds = 10,000,000 + 30 * 45.67 = * 10,001,370.1 (stored as 10,001,370.1 * 10**18). */ function cumulativePrice() private view returns (uint timestamp, uint priceSeconds) { (, , timestamp) = uniswapPair.getReserves(); // Retrieve the current Uniswap cumulative price. Modeled off of Uniswap's own example: // https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/examples/ExampleOracleSimple.sol uint uniswapCumPrice = tokensInReverseOrder ? uniswapPair.price1CumulativeLast() : uniswapPair.price0CumulativeLast(); priceSeconds = uniswapCumPrice.mul(scaleFactor) / UNISWAP_CUM_PRICE_SCALE_FACTOR; } /** * @param newTimestamp in seconds (eg, 1606764888) - not WAD-scaled! * @param newPriceSeconds WAD-scaled. * @param oldTimestamp in raw seconds again. * @param oldPriceSeconds WAD-scaled. * @return price WAD-scaled. */ function calculateTWAP(uint newTimestamp, uint newPriceSeconds, uint oldTimestamp, uint oldPriceSeconds) private pure returns (uint price) { price = (newPriceSeconds.sub(oldPriceSeconds)).div(newTimestamp.sub(oldTimestamp)); } } // File: contracts/oracles/MedianOracle.sol pragma solidity ^0.6.6; contract MedianOracle is ChainlinkOracle, CompoundOpenOracle, OurUniswapV2TWAPOracle { using SafeMath for uint; constructor( AggregatorV3Interface chainlinkAggregator, UniswapAnchoredView compoundView, IUniswapV2Pair uniswapPair, uint uniswapToken0Decimals, uint uniswapToken1Decimals, bool uniswapTokensInReverseOrder ) public ChainlinkOracle(chainlinkAggregator) CompoundOpenOracle(compoundView) OurUniswapV2TWAPOracle(uniswapPair, uniswapToken0Decimals, uniswapToken1Decimals, uniswapTokensInReverseOrder) {} function latestPrice() public override(ChainlinkOracle, CompoundOpenOracle, OurUniswapV2TWAPOracle) view returns (uint price) { price = median(ChainlinkOracle.latestPrice(), CompoundOpenOracle.latestPrice(), OurUniswapV2TWAPOracle.latestPrice()); } function cacheLatestPrice() public virtual override(Oracle, OurUniswapV2TWAPOracle) returns (uint price) { price = median(ChainlinkOracle.latestPrice(), // Not ideal to call latestPrice() on two of these CompoundOpenOracle.latestPrice(), // and cacheLatestPrice() on one... But works, and OurUniswapV2TWAPOracle.cacheLatestPrice()); // inheriting them like this saves significant gas } /** * @notice Currently only supports three inputs * @return median value */ function median(uint a, uint b, uint c) private pure returns (uint) { bool ab = a > b; bool bc = b > c; bool ca = c > a; return (ca == ab ? a : (ab == bc ? b : c)); } } // File: contracts/USM.sol pragma solidity ^0.6.6; contract USM is USMTemplate, MedianOracle { constructor( AggregatorV3Interface chainlinkAggregator, UniswapAnchoredView compoundView, IUniswapV2Pair uniswapPair, uint uniswapToken0Decimals, uint uniswapToken1Decimals, bool uniswapTokensInReverseOrder ) public USMTemplate() MedianOracle(chainlinkAggregator, compoundView, uniswapPair, uniswapToken0Decimals, uniswapToken1Decimals, uniswapTokensInReverseOrder) {} function cacheLatestPrice() public virtual override(Oracle, MedianOracle) returns (uint price) { price = super.cacheLatestPrice(); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract AggregatorV3Interface","name":"chainlinkAggregator","type":"address"},{"internalType":"contract UniswapAnchoredView","name":"compoundView","type":"address"},{"internalType":"contract IUniswapV2Pair","name":"uniswapPair","type":"address"},{"internalType":"uint256","name":"uniswapToken0Decimals","type":"uint256"},{"internalType":"uint256","name":"uniswapToken1Decimals","type":"uint256"},{"internalType":"bool","name":"uniswapTokensInReverseOrder","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"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":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"latest","type":"uint256"}],"name":"BuySellAdjustmentChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"Delegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"latest","type":"uint256"}],"name":"MinFumBuyPriceChanged","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"},{"inputs":[],"name":"BUY_SELL_ADJUSTMENT_HALF_LIFE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGABLE_DOMAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_DEBT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FUM_BUY_PRICE_HALF_LIFE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TWAP_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNATURE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNISWAP_CUM_PRICE_SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WAD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"addDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"addDelegateBySignature","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":"from","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"usmToBurn","type":"uint256"},{"internalType":"uint256","name":"minEthOut","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"ethOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buySellAdjustment","outputs":[{"internalType":"uint256","name":"adjustment","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buySellAdjustmentStored","outputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint224","name":"value","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cacheLatestPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"debtRatio","outputs":[{"internalType":"uint256","name":"ratio","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":"from","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"fumToBurn","type":"uint256"},{"internalType":"uint256","name":"minEthOut","type":"uint256"}],"name":"defund","outputs":[{"internalType":"uint256","name":"ethOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"fumToBurn","type":"uint256"},{"internalType":"uint256","name":"minEthOut","type":"uint256"}],"name":"defundFromFUM","outputs":[{"internalType":"uint256","name":"ethOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"delegated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum WadMath.Round","name":"upOrDown","type":"uint8"}],"name":"ethBuffer","outputs":[{"internalType":"int256","name":"buffer","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethPool","outputs":[{"internalType":"uint256","name":"pool","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"enum WadMath.Round","name":"upOrDown","type":"uint8"}],"name":"ethToUsm","outputs":[{"internalType":"uint256","name":"usmOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fum","outputs":[{"internalType":"contract FUM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum USMTemplate.Side","name":"side","type":"uint8"}],"name":"fumPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minFumOut","type":"uint256"}],"name":"fund","outputs":[{"internalType":"uint256","name":"fumOut","type":"uint256"}],"stateMutability":"payable","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":[],"name":"latestChainlinkPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestCompoundPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestUniswapTWAPPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minFumBuyPrice","outputs":[{"internalType":"uint256","name":"mfbp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minFumBuyPriceStored","outputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint224","name":"value","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minUsmOut","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"usmOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"revokeDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signatureCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum USMTemplate.Side","name":"side","type":"uint8"}],"name":"usmPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"usmAmount","type":"uint256"},{"internalType":"enum WadMath.Round","name":"upOrDown","type":"uint8"}],"name":"usmToEth","outputs":[{"internalType":"uint256","name":"ethOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101c0604081905280605262006d988239604080519182900360520182206080527f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb760c052818101905260008152670de0b6b3a7640000602090910152506b0de0b6b3a764000000000000600b553480156200007a57600080fd5b5060405162006e3c38038062006e3c833981810160405260c0811015620000a057600080fd5b5080516020808301516040808501516060860151608087015160a09097015183518085018552600b81526a135a5b9a5b585b081554d160aa1b818801908152855180870190965260038087526255534d60e81b98870198909852815198999698949793969592948a948a948a948a948a948a9488948894889488948d948f94928492849262000131929091620004ff565b50805162000147906004906020840190620004ff565b50506005805460ff1916601217905550604051469080605262006dea82396040805191829003605290810183208751602098890120848401845260018552603160f81b948901949094528251808901919091528083019390935260008051602062006d78833981519152606084015260808301949094523060a08084019190915281518084038201815260c090930191829052825192909601919091209094525046929150819062006dea8239604080519182900360520182208282018252600683526555534d46554d60d01b6020938401528151808301835260018152603160f81b908401528151808401919091527f1ffee17c90b10b2d9e9bbd98a237e331a138c1264fe23f3a536813ba5c9e56938183015260008051602062006d78833981519152606082015260808101949094523060a08086018290528251808703909101815260c0909501918290528451949092019390932060e05291620002af915062000584565b6001600160a01b03909116815260405190819003602001906000f080158015620002dd573d6000803e3d6000fd5b506001600160601b0319606091821b8116610100526224ea004201600955600c80546001600160a01b039485166001600160a01b031991821617909155600d80549590941694169390931790915585901b166101205261014083905261016082905280151560f81b61018052600080826200035a5784846200035d565b83855b91509150620003958162000381601285620003b860201b6200231e1790919060201c565b6200041a60201b620021741790919060201c565b600a0a6101a08181525050505050505050505050505050505050505050620005b2565b60008282018381101562000413576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60006200041383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506200046460201b60201c565b60008184841115620004f75760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620004bb578181015183820152602001620004a1565b50505050905090810190601f168015620004e95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200054257805160ff191683800117855562000572565b8280016001018555821562000572579182015b828111156200057257825182559160200191906001019062000555565b506200058092915062000592565b5090565b61205b8062004d1d83390190565b620005af91905b8082111562000580576000815560010162000599565b90565b60805160a05160c05160e0516101005160601c6101205160601c61014051610160516101805160f81c6101a0516146b9620006646000398061417352508061400e5250505080613f6f528061403352806140ca5250806116695280611a2d52806120dc52806127fc5280612b6e5280612c985280612f905280613b8052508061116552806116025250806110e552806119c852508061153d5280611bf35250806115105280611b6b52506146b96000f3fe60806040526004361061032d5760003560e01c806395d89b41116101a5578063d505accf116100ec578063ec0c2beb11610095578063f6bcbd311161006f578063f6bcbd3114610bfd578063f99b1bdb14610c45578063fa352c0014610c9b578063faddc92914610cdb57610347565b8063ec0c2beb14610bbe578063f16673a414610bd3578063f2fe0b4214610be857610347565b8063e6a3c053116100c6578063e6a3c05314610b54578063e71bdf4114610b69578063e833091f14610ba957610347565b8063d505accf14610a4b578063d7020d0a14610ab6578063dd62ed3e14610b0c57610347565b8063a9059cbb1161014e578063c2eebdcf11610128578063c2eebdcf146109dc578063c560ce9a14610a09578063cea55f5714610a3657610347565b8063a9059cbb14610941578063b5d832fe14610987578063c0bd65d7146109c757610347565b8063a0c8ee961161017f578063a0c8ee96146108b3578063a3e6ba94146108e6578063a457c2d7146108fb57610347565b806395d89b41146108335780639670393d146108485780639a4c6a9a1461085d57610347565b80633e1028a0116102745780636ea51d081161021d5780637b1837de116101f75780637b1837de146107905780637ecebe00146107c95780638382f4ee1461080957806393b11ebe1461081e57610347565b80636ea51d08146106fd57806370a082311461073b57806371b0a1541461077b57610347565b806349f3bb961161024e57806349f3bb96146106a657806361fbccb5146106d35780636a146024146106e857610347565b80633e1028a01461060657806340c10f1914610658578063459e414f1461069157610347565b80632db1187f116102d6578063313ce567116102b0578063313ce567146105805780633644e515146105ab57806339509351146105c057610347565b80632db1187f146105235780633098e2791461055657806330adf81f1461056b57610347565b80631a28ff05116103075780631a28ff051461045757806323b872dd146104be5780632c23183d1461050e57610347565b806306fdde031461034c578063095ea7b3146103d657806318160ddd1461043057610347565b36610347576103443361033f34610cf0565b610d20565b50005b600080fd5b34801561035857600080fd5b50610361610f80565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561039b578181015183820152602001610383565b50505050905090810190601f1680156103c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103e257600080fd5b5061041c600480360360408110156103f957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611035565b604080519115158252519081900360200190f35b34801561043c57600080fd5b50610445611053565b60408051918252519081900360200190f35b34801561046357600080fd5b506104bc600480360360c081101561047a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060ff6060820135169060808101359060a00135611059565b005b3480156104ca57600080fd5b5061041c600480360360608110156104e157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611307565b34801561051a57600080fd5b506104456113ae565b34801561052f57600080fd5b506104456004803603604081101561054657600080fd5b508035906020013560ff1661145b565b34801561056257600080fd5b50610445611476565b34801561057757600080fd5b5061044561150e565b34801561058c57600080fd5b50610595611532565b6040805160ff9092168252519081900360200190f35b3480156105b757600080fd5b5061044561153b565b3480156105cc57600080fd5b5061041c600480360360408110156105e357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561155f565b34801561061257600080fd5b5061061b6115c0565b6040805163ffffffff90931683527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911660208301528051918290030190f35b6104456004803603604081101561066e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356115f4565b34801561069d57600080fd5b50610445611600565b3480156106b257600080fd5b50610445600480360360208110156106c957600080fd5b503560ff16611624565b3480156106df57600080fd5b5061044561164f565b3480156106f457600080fd5b5061044561165b565b34801561070957600080fd5b50610712611667565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561074757600080fd5b506104456004803603602081101561075e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661168b565b34801561078757600080fd5b506104456116b7565b610445600480360360408110156107a657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356116bc565b3480156107d557600080fd5b50610445600480360360208110156107ec57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166116c8565b34801561081557600080fd5b506104456116da565b34801561082a57600080fd5b506104456116df565b34801561083f57600080fd5b506103616116f2565b34801561085457600080fd5b5061061b611771565b34801561086957600080fd5b506104456004803603608081101561088057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604081013590606001356117a5565b3480156108bf57600080fd5b50610445600480360360408110156108d657600080fd5b508035906020013560ff166118ea565b3480156108f257600080fd5b506104456118fe565b34801561090757600080fd5b5061041c6004803603604081101561091e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611925565b34801561094d57600080fd5b5061041c6004803603604081101561096457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356119a0565b34801561099357600080fd5b50610445600480360360208110156109aa57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119b4565b3480156109d357600080fd5b506104456119c6565b3480156109e857600080fd5b50610445600480360360208110156109ff57600080fd5b503560ff166119ea565b348015610a1557600080fd5b5061044560048036036020811015610a2c57600080fd5b503560ff16611a0d565b348015610a4257600080fd5b50610445611aca565b348015610a5757600080fd5b506104bc600480360360e0811015610a6e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135611adf565b348015610ac257600080fd5b5061044560048036036080811015610ad957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060600135611d98565b348015610b1857600080fd5b5061044560048036036040811015610b2f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611e95565b348015610b6057600080fd5b50610445611ecd565b348015610b7557600080fd5b506104bc60048036036020811015610b8c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611eed565b348015610bb557600080fd5b50610445611efa565b348015610bca57600080fd5b50610445611f04565b348015610bdf57600080fd5b50610445611fe7565b348015610bf457600080fd5b50610445611feb565b348015610c0957600080fd5b5061041c60048036036040811015610c2057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166120a2565b348015610c5157600080fd5b5061044560048036036080811015610c6857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604081013590606001356120c2565b348015610ca757600080fd5b506104bc60048036036020811015610cbe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612163565b348015610ce757600080fd5b5061044561216d565b600064174876e80082068015801590610d0b57506298968081105b15610d1a5760648382025b0491505b50919050565b600080610d2b611fe7565b90506000610d3f823463ffffffff61217416565b905060008111610d96576040805162461bcd60e51b815260206004820152601360248201527f46756e64206265666f7265206d696e74696e6700000000000000000000000000604482015290519081900360640190fd5b6000610da0611efa565b90506000610dac611053565b90506000610dbb8385846121b6565b9050610dca83348685856121f1565b955086861015610e21576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b6000610e3d8487610e38868b63ffffffff61231e16565b6121b6565b9050610e518282610e4c6113ae565b612378565b610e5b8988612482565b600954421115610eb2576040805162461bcd60e51b815260206004820152601c60248201527f547269616c20657870697265642c2072656d6f76652061737365747300000000604482015290519081900360640190fd5b670de0b6b3a7640000341115610f0f576040805162461bcd60e51b815260206004820152601660248201527f4361707065642061742031204554482070657220747800000000000000000000604482015290519081900360640190fd5b68056bc75e2d63100000610f21611fe7565b1115610f74576040805162461bcd60e51b815260206004820152601860248201527f4361707065642061742031303020706f6f6c6564204554480000000000000000604482015290519081900360640190fd5b50505050505092915050565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561102a5780601f10610fff5761010080835404028352916020019161102a565b820191906000526020600020905b81548152906001019060200180831161100d57829003601f168201915b505050505090505b90565b60006110496110426125a5565b84846125a9565b5060015b92915050565b60025490565b428410156110ae576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a205369676e6174757265206578706972656400000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80871660008181526007602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958b166060860152608085019590955260a08085018a90528151808603909101815260c0850182528051908301207f190100000000000000000000000000000000000000000000000000000000000060e08601527f000000000000000000000000000000000000000000000000000000000000000060e286015261010280860182905282518087039091018152610122860180845281519185019190912090859052610142860180845281905260ff8a1661016287015261018286018990526101a2860188905291519095919491926101c28084019391927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015611226573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906112a157508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6112f2576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20496e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b6112fc89896126bc565b505050505050505050565b60006113148484846127db565b6113a4846113206125a5565b61139f856040518060600160405280602881526020016145cd6028913973ffffffffffffffffffffffffffffffffffffffff8a1660009081526001602052604081209061136b6125a5565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054919063ffffffff61289316565b6125a9565b5060019392505050565b600b5460009081906113de90603c906113d290429063ffffffff9081169061217416565b9063ffffffff6128ed16565b905060006113f382600a63ffffffff61290b16565b600b54909150611454908290611448906114339064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683612961565b670de0b6b3a76400009063ffffffff61231e16565b9063ffffffff61217416565b9250505090565b600061146f6114686118fe565b848461298b565b9392505050565b600a5460009064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161561103257600a546000906114cb9062015180906113d290429063ffffffff9081169061217416565b905060006114d88261299e565b600a549091506114549064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16826129ca565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061104961156c6125a5565b8461139f856001600061157d6125a5565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff61231e16565b600b5463ffffffff81169064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682565b600061146f8383610d20565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008061162f6118fe565b905061146f838261164a84611642611fe7565b610e38611053565b6129fd565b670b1a2bc2ec50000081565b670de0b6b3a764000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b603c81565b600061146f8383612b22565b60066020526000908152604090205481565b607881565b6e01000000000000000000000000000081565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561102a5780601f10610fff5761010080835404028352916020019161102a565b600a5463ffffffff81169064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682565b6000846040518060400160405280601781526020017f4f6e6c7920686f6c646572206f722064656c65676174650000000000000000008152508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611848575073ffffffffffffffffffffffffffffffffffffffff8216600090815260086020908152604080832033845290915290205460ff165b81906118d25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561189757818101518382015260200161187f565b50505050905090810190601f1680156118c45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506118df87878787612e7c565b979650505050505050565b600061146f6118f76118fe565b848461308d565b600061192061190b6130a0565b6119136130aa565b61191b6130b4565b6130be565b905090565b60006110496119326125a5565b8461139f8560405180606001604052806025815260200161465f602591396001600061195c6125a5565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61289316565b60006110496119ad6125a5565b84846127db565b60076020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061104d6119f76118fe565b6119ff611fe7565b611a07611053565b856130f3565b600061104d82611a1b6118fe565b611a23611fe7565b611a2b611053565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a9157600080fd5b505afa158015611aa5573d6000803e3d6000fd5b505050506040513d6020811015611abb57600080fd5b5051611ac56113ae565b613181565b6000611920611ad76118fe565b611642611fe7565b42841015611b34576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80881660008181526006602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601527f000000000000000000000000000000000000000000000000000000000000000061010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e28084019391927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015611cb5573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611d3057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611d81576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b611d8c8a8a8a6125a9565b50505050505050505050565b6000846040518060400160405280601781526020017f4f6e6c7920686f6c646572206f722064656c65676174650000000000000000008152508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611e3b575073ffffffffffffffffffffffffffffffffffffffff8216600090815260086020908152604080832033845290915290205460ff165b8190611e885760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561189757818101518382015260200161187f565b506118df8787878761327b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b600080611ed86133af565b915050611ee4816133e0565b50909392505050565b611ef733826126bc565b50565b6000611920613448565b600d54604080517ffe2c6198000000000000000000000000000000000000000000000000000000008152602060048201819052600360248301527f4554480000000000000000000000000000000000000000000000000000000000604483015291516000936119209364e8d4a510009373ffffffffffffffffffffffffffffffffffffffff9092169263fe2c6198926064808201939291829003018186803b158015611faf57600080fd5b505afa158015611fc3573d6000803e3d6000fd5b505050506040513d6020811015611fd957600080fd5b50519063ffffffff61346516565b4790565b600080600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561205657600080fd5b505afa15801561206a573d6000803e3d6000fd5b505050506040513d60a081101561208057600080fd5b5060200151905061209c816402540be40063ffffffff61346516565b91505090565b600860209081526000928352604080842090915290825290205460ff1681565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461214e576040805162461bcd60e51b815260206004820152601160248201527f5265737472696374656420746f2046554d000000000000000000000000000000604482015290519081900360640190fd5b61215a85858585612e7c565b95945050505050565b611ef733826134be565b6201518081565b600061146f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612893565b6000806121c9848663ffffffff61296116565b905083156121e6576121e1838263ffffffff6135d416565b61215a565b600095945050505050565b600080612200600088856129fd565b90506000612214868863ffffffff61231e16565b9050846122325761222b878363ffffffff6128ed16565b9250612313565b670de0b6b3a764000084116122c55760006122878361227b8961226f670de0b6b3a764000061144861226a898563ffffffff6128ed16565b613618565b9063ffffffff61346516565b9063ffffffff61364c16565b90506122bd866114486122b861229c8a61368e565b6122ac868c63ffffffff61231e16565b9063ffffffff61296116565b6136a9565b935050612313565b60006122ea6122da878563ffffffff6129ca16565b61227b898b63ffffffff61346516565b905061230f6122ff838363ffffffff61217416565b61227b888463ffffffff61346516565b9350505b505095945050505050565b60008282018381101561146f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b821580159061238657508115155b1561247d57600b5464010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600083806123c68761226f8782613465565b816123cd57fe5b04816123d557fe5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000164263ffffffff9081169190911716640100000000939092047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811693909302919091179055604080518481526020810183905281519293507f3af9fe9b92def18e94efef4175b9165aa71c2b1f8e3339bf1f23872922019733929081900390910190a150505b505050565b73ffffffffffffffffffffffffffffffffffffffff82166124ea576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6124f66000838361247d565b600254612509908263ffffffff61231e16565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054612542908263ffffffff61231e16565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b3390565b73ffffffffffffffffffffffffffffffffffffffff83166125fb5760405162461bcd60e51b815260040180806020018281038252602481526020018061463b6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661264d5760405162461bcd60e51b815260040180806020018281038252602281526020018061452a6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526008602090815260408083209385168352929052205460ff1615612744576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20416c72656164792064656c65676174656400000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80831660008181526008602090815260408083209486168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155825190815291517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b73ffffffffffffffffffffffffffffffffffffffff821630148061284a57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80612869575073ffffffffffffffffffffffffffffffffffffffff8216155b156128885761288283848361287d85613728565b61327b565b5061247d565b61247d838383613754565b600081848411156128e55760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561189757818101518382015260200161187f565b505050900390565b600061146f8261227b85670de0b6b3a764000063ffffffff61346516565b60008067016345785d8a00006129288566b1a2bc2ec5000061231e565b8161292f57fe5b04905082600a8204111561294757600091505061104d565b612959670cf2cc8ff8457df8826138fc565b949350505050565b6000670de0b6b3a764000061297c848463ffffffff61346516565b8161298357fe5b049392505050565b600061295983858463ffffffff61395116565b600061104d827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61290b565b6000670de0b6b3a764000061297c670de0b6b3a763ffff6129f1868663ffffffff61346516565b9063ffffffff61231e16565b60008080856001811115612a0d57fe5b14612a19576000612a1c565b60015b9050612a3184670de0b6b3a76400008361308d565b91506000612a3d6113ae565b9050670de0b6b3a76400008411612ab6576000866001811115612a5c57fe5b148015612a705750670de0b6b3a764000081105b80612a9857506001866001811115612a8457fe5b148015612a985750670de0b6b3a764000081115b15612ab157612aae83828463ffffffff61397e16565b92505b612b19565b6000866001811115612ac457fe5b148015612ad85750670de0b6b3a764000081115b80612b0057506001866001811115612aec57fe5b148015612b005750670de0b6b3a764000081105b15612b1957612b1683828463ffffffff61395116565b92505b50509392505050565b600080612b2d611efa565b90506000612b39611fe7565b90506000612b4d823463ffffffff61217416565b90506000612b59611053565b90506000612b688584846121b6565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612bd257600080fd5b505afa158015612be6573d6000803e3d6000fd5b505050506040513d6020811015612bfc57600080fd5b50519050612c0b8285836139a6565b6000612c156113ae565b9050612c25873487878686613b19565b975088881015612c7c576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b6000612c898888876121b6565b9050612c96848284612378565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166340c10f198c8b6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015612d3d57600080fd5b505af1158015612d51573d6000803e3d6000fd5b50505050600954421115612dac576040805162461bcd60e51b815260206004820152601c60248201527f547269616c20657870697265642c2072656d6f76652061737365747300000000604482015290519081900360640190fd5b670de0b6b3a7640000341115612e09576040805162461bcd60e51b815260206004820152601660248201527f4361707065642061742031204554482070657220747800000000000000000000604482015290519081900360640190fd5b68056bc75e2d63100000612e1b611fe7565b1115612e6e576040805162461bcd60e51b815260206004820152601860248201527f4361707065642061742031303020706f6f6c6564204554480000000000000000604482015290519081900360640190fd5b505050505050505092915050565b600080612e87611efa565b90506000612e93611fe7565b90506000612e9f611053565b90506000612eae8484846121b6565b9050612ebc84888585613b7b565b945085851015612f13576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b6000612f2f85612f29868963ffffffff61217416565b856121b6565b9050670b1a2bc2ec500000811115612f8e576040805162461bcd60e51b815260206004820152601060248201527f4465627420726174696f203e206d617800000000000000000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639dc29fac8b8a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561303557600080fd5b505af1158015613049573d6000803e3d6000fd5b5050505061305a8282610e4c6113ae565b61308073ffffffffffffffffffffffffffffffffffffffff8a168763ffffffff613c9016565b5050505050949350505050565b600061295983858463ffffffff61397e16565b6000611920611feb565b6000611920611f04565b6000611920611ecd565b60008284118284118584118083146130e857811515831515146130e157846130e3565b855b6118df565b509495945050505050565b6000808083600181111561310357fe5b1461310f576000613112565b60015b905061311f86858361308d565b8503915084821315613178576040805162461bcd60e51b815260206004820152600f60248201527f556e646572666c6f77206572726f720000000000000000000000000000000000604482015290519081900360640190fd5b50949350505050565b6000808088600181111561319157fe5b1461319d5760006131a0565b60015b9050836131c2576131ba87670de0b6b3a76400008361308d565b915050613271565b60006131d0888888856130f3565b905060008113156131f1576131ec81868463ffffffff61397e16565b6131f4565b60005b9250600089600181111561320457fe5b141561324b57670de0b6b3a764000084111561322d5761322a838563ffffffff6129ca16565b92505b6000613237611476565b905080841015613245578093505b5061326e565b670de0b6b3a764000084101561326e5761326b838563ffffffff61296116565b92505b50505b9695505050505050565b600080613286611efa565b90506000613292611fe7565b9050600061329e611053565b905060006132ad8484846121b6565b90506132bc8488858585613d82565b945085851015613313576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b600061333985613329868963ffffffff61217416565b610e38868c63ffffffff61217416565b9050670de0b6b3a7640000811115613398576040805162461bcd60e51b815260206004820152601160248201527f4465627420726174696f203e2031303025000000000000000000000000000000604482015290519081900360640190fd5b6133a28a89613e2e565b61305a8282610e4c6113ae565b600e54600f54600091829163ffffffff9182169116116133d257600f600e6133d7565b600e600f5b90939092509050565b60008060006133ed613f6a565b909250905060006133fe83866141ac565b805490915061343e908490849063ffffffff81169064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661424d565b9350509193909250565b60006119206134556130a0565b61345d6130aa565b61191b614272565b6000826134745750600061104d565b8282028284828161348157fe5b041461146f5760405162461bcd60e51b81526004018080602001828103825260218152602001806145ac6021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff80831660009081526008602090815260408083209385168352929052205460ff16613545576040805162461bcd60e51b815260206004820152601e60248201527f44656c656761626c653a20416c726561647920756e64656c6567617465640000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff808316600081815260086020908152604080832094861680845294825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051928352517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b600061146f8261227b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82016129f187670de0b6b3a764000063ffffffff61346516565b60006ec097ce7bc90715b34b9f100000000061363e8361226f818063ffffffff61346516565b8161364557fe5b0492915050565b600061146f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506142b7565b6000670de0b6b3a764000061363e838063ffffffff61346516565b600081156116b257600060036136cd84671bc16d674ec8000063ffffffff61231e16565b816136d457fe5b04905060006136f8846ec097ce7bc90715b34b9f100000000063ffffffff61346516565b90505b8192506003838402828161370b57fe5b04848501018161371757fe5b0491508282106136fb575050919050565b600064174876e8008206801580159061374357506298968081105b15610d1a57808360640281610d1657fe5b73ffffffffffffffffffffffffffffffffffffffff83166137a65760405162461bcd60e51b81526004018080602001828103825260258152602001806146166025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166137f85760405162461bcd60e51b81526004018080602001828103825260238152602001806144e56023913960400191505060405180910390fd5b61380383838361247d565b6138538160405180606001604052806026815260200161454c6026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff61289316565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054613895908263ffffffff61231e16565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60006002820661391457670de0b6b3a7640000613916565b825b90506002820491505b811561104d5761392e8361368e565b92506002820615613946576139438184612961565b90505b60028204915061391f565b60008082600181111561396057fe5b146139745761396f84846129ca565b612959565b6129598484612961565b60008082600181111561398d57fe5b1461399c5761396f84846135d4565b61295984846128ed565b600a5464010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16670b1a2bc2ec5000008411613a2c578015613a27576000600a81905560408051838152602081019290925280517f05ddb88d20c718baf5e5231bd021d330d7e31a9e676417079f0d0f518e2fde559281900390910190a15b613b13565b80613b1357600a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000164263ffffffff16178155613a99908390613a8d908690676f05b59d3b20000004670de0b6b3a7640000039063ffffffff6129ca16565b9063ffffffff6135d416565b600a805463ffffffff166401000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416810291909117918290556040805185815291909204909216602083015280517f05ddb88d20c718baf5e5231bd021d330d7e31a9e676417079f0d0f518e2fde559281900390910190a15b50505050565b600080613b2b60008988888888613181565b905084613b4957613b42878263ffffffff6128ed16565b9150613b70565b6000613b5b878963ffffffff61231e16565b905061326b6122da828463ffffffff6129ca16565b509695505050505050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613be457600080fd5b505afa158015613bf8573d6000803e3d6000fd5b505050506040513d6020811015613c0e57600080fd5b505190506000613c25600188878786611ac56113ae565b905083613c4357613c3c868263ffffffff61296116565b9250613c86565b6118df613c66613c59888463ffffffff6129ca16565b879063ffffffff61231e16565b61227b613c79898563ffffffff61296116565b889063ffffffff61346516565b5050949350505050565b80471015613ce5576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b60405160009073ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d8060008114613d3d576040519150601f19603f3d011682016040523d82523d6000602084013e613d42565b606091505b505090508061247d5760405162461bcd60e51b815260040180806020018281038252603a815260200180614572603a913960400191505060405180910390fd5b600080613d91600188856129fd565b90506000613da5858863ffffffff61217416565b90506000613dec613ddc613dc7613dc2858a63ffffffff6135d416565b61431c565b670de0b6b3a76400009063ffffffff61217416565b6122ac858963ffffffff61296116565b905061230f613e21613e1c613e078a8563ffffffff61217416565b613e108b614355565b9063ffffffff6129ca16565b61437c565b889063ffffffff61217416565b73ffffffffffffffffffffffffffffffffffffffff8216613e805760405162461bcd60e51b81526004018080602001828103825260218152602001806145f56021913960400191505060405180910390fd5b613e8c8260008361247d565b613edc816040518060600160405280602281526020016145086022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff61289316565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902055600254613f15908263ffffffff61217416565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015613fd357600080fd5b505afa158015613fe7573d6000803e3d6000fd5b505050506040513d6060811015613ffd57600080fd5b506040015163ffffffff16915060007f00000000000000000000000000000000000000000000000000000000000000006140c8577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561409757600080fd5b505afa1580156140ab573d6000803e3d6000fd5b505050506040513d60208110156140c157600080fd5b505161415b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635a3d54936040518163ffffffff1660e01b815260040160206040518083038186803b15801561412e57600080fd5b505afa158015614142573d6000803e3d6000fd5b505050506040513d602081101561415857600080fd5b50515b90506e01000000000000000000000000000061419d827f000000000000000000000000000000000000000000000000000000000000000063ffffffff61346516565b816141a457fe5b049150509091565b6000806141ba84600e6143ad565b905060006141c985600f6143ad565b905081156141e95780156141df578392506141e4565b600e92505b614245565b80156141f857600f9250614245565b6040805162461bcd60e51b815260206004820152601d60248201527f426f74682073746f7265642070726963657320746f6f20726563656e74000000604482015290519081900360640190fd5b505092915050565b600061215a614262868563ffffffff61217416565b61227b868563ffffffff61217416565b600080600061427f6133af565b9150915060008061428f836133e0565b919650925090506142a082846143ad565b156142b0576142b08282866143bc565b5050505090565b600081836143065760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561189757818101518382015260200161187f565b50600083858161431257fe5b0495945050505050565b60006ec097ce7bc90715b34b9f100000000061363e6ec097ce7bc90715b34b9f0fffffffff6129f18561226f818063ffffffff61346516565b6000670de0b6b3a764000061363e670de0b6b3a763ffff6129f1858063ffffffff61346516565b6000614387826136a9565b905080800281026ec097ce7bc90715b34b9f10000000008302146116b257600101919050565b5463ffffffff16607801111590565b63ffffffff831115614415576040805162461bcd60e51b815260206004820152601260248201527f74696d657374616d70206f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff821115614486576040805162461bcd60e51b815260206004820152601560248201527f70726963655365636f6e6473206f766572666c6f770000000000000000000000604482015290519081900360640190fd5b805463ffffffff9384167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316640100000000029316929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001617905556fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122064627c1b8491319e4adf03479b1eb26789acb90feebba45a03f61eec762db93564736f6c6343000606003360e0604081905280605262001fb78239604051908190036052019020608052503480156200002c57600080fd5b506040516200205b3803806200205b833981810160405260208110156200005257600080fd5b5051604080518082018252600f81526e4d696e696d616c2046756e64696e6760881b6020828101918252835180850190945260038085526246554d60e81b91850191909152825192939284928492620000ae92909190620001f0565b508051620000c4906004906020840190620001f0565b50506005805460ff19166012179055506040514690806052620020098239604080519182900360520182208651602097880120838301835260018452603160f81b93880193909352815180880191909152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606083015260808201939093523060a08083019190915283518083038201815260c0909201909352805194019390932090525060009050620001876001600160e01b03620001eb16565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060601b6001600160601b03191660c05262000292565b335b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200023357805160ff191683800117855562000263565b8280016001018555821562000263579182015b828111156200026357825182559160200191906001019062000246565b506200027192915062000275565b5090565b620001ed91905b808211156200027157600081556001016200027c565b60805160a05160c05160601c611cdc620002db600039806101755280610d42528061139452806114085250806109335280610ea65250806109065280610e1e5250611cdc6000f3fe60806040526004361061016e5760003560e01c8063715018a6116100cb578063a457c2d71161007f578063d505accf11610059578063d505accf14610663578063dd62ed3e146106ce578063f2fde38b1461071657610251565b8063a457c2d7146105c2578063a4800a7514610608578063a9059cbb1461061d57610251565b80638da5cb5b116100b05780638da5cb5b1461052957806395d89b41146105675780639dc29fac1461057c57610251565b8063715018a6146104d45780637ecebe00146104e957610251565b8063313ce567116101225780633950935111610107578063395093511461040657806340c10f191461044c57806370a082311461049457610251565b8063313ce567146103c65780633644e515146103f157610251565b806318160ddd1161015357806318160ddd1461033a57806323b872dd1461036157806330adf81f146103b157610251565b806306fdde0314610256578063095ea7b3146102e057610251565b36610251577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637b1837de34336101ba34610756565b6040518463ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506020604051808303818588803b15801561022257600080fd5b505af1158015610236573d6000803e3d6000fd5b50505050506040513d602081101561024d57600080fd5b5050005b600080fd5b34801561026257600080fd5b5061026b610786565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102a557818101518382015260200161028d565b50505050905090810190601f1680156102d25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102ec57600080fd5b506103266004803603604081101561030357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561083a565b604080519115158252519081900360200190f35b34801561034657600080fd5b5061034f610857565b60408051918252519081900360200190f35b34801561036d57600080fd5b506103266004803603606081101561038457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135909116906040013561085d565b3480156103bd57600080fd5b5061034f610904565b3480156103d257600080fd5b506103db610928565b6040805160ff9092168252519081900360200190f35b3480156103fd57600080fd5b5061034f610931565b34801561041257600080fd5b506103266004803603604081101561042957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610955565b34801561045857600080fd5b506104926004803603604081101561046f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356109b6565b005b3480156104a057600080fd5b5061034f600480360360208110156104b757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610a55565b3480156104e057600080fd5b50610492610a7d565b3480156104f557600080fd5b5061034f6004803603602081101561050c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b7d565b34801561053557600080fd5b5061053e610b8f565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561057357600080fd5b5061026b610bab565b34801561058857600080fd5b506104926004803603604081101561059f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610c2a565b3480156105ce57600080fd5b50610326600480360360408110156105e557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610cc5565b34801561061457600080fd5b5061053e610d40565b34801561062957600080fd5b506103266004803603604081101561064057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610d64565b34801561066f57600080fd5b50610492600480360360e081101561068657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610d78565b3480156106da57600080fd5b5061034f600480360360408110156106f157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611065565b34801561072257600080fd5b506104926004803603602081101561073957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661109d565b600064174876e8008206801580159061077157506298968081105b156107805760648382025b0491505b50919050565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108305780601f1061080557610100808354040283529160200191610830565b820191906000526020600020905b81548152906001019060200180831161081357829003601f168201915b5050505050905090565b600061084e610847611228565b848461122c565b50600192915050565b60025490565b600061086a848484611373565b6108fa84610876611228565b6108f585604051806060016040528060288152602001611bf06028913973ffffffffffffffffffffffffffffffffffffffff8a166000908152600160205260408120906108c1611228565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054919063ffffffff61153316565b61122c565b5060019392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061084e610962611228565b846108f58560016000610973611228565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6115e416565b6109be611228565b60075473ffffffffffffffffffffffffffffffffffffffff908116911614610a4757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610a51828261165f565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b610a85611228565b60075473ffffffffffffffffffffffffffffffffffffffff908116911614610b0e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60075460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60066020526000908152604090205481565b60075473ffffffffffffffffffffffffffffffffffffffff1690565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108305780601f1061080557610100808354040283529160200191610830565b610c32611228565b60075473ffffffffffffffffffffffffffffffffffffffff908116911614610cbb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610a51828261179c565b600061084e610cd2611228565b846108f585604051806060016040528060258152602001611c826025913960016000610cfc611228565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61153316565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061084e610d71611228565b8484611373565b42841015610de757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80881660008181526006602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601527f000000000000000000000000000000000000000000000000000000000000000061010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e28084019391927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015610f68573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610fe357508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61104e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6110598a8a8a61122c565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6110a5611228565b60075473ffffffffffffffffffffffffffffffffffffffff90811691161461112e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661119a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180611b826026913960400191505060405180910390fd5b60075460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b73ffffffffffffffffffffffffffffffffffffffff8316611298576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611c5e6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611304576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611ba86022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff82163014806113e257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80611401575073ffffffffffffffffffffffffffffffffffffffff8216155b15611523577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f99b1bdb84858461144e866118f2565b6040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001945050505050602060405180830381600087803b1580156114f157600080fd5b505af1158015611505573d6000803e3d6000fd5b505050506040513d602081101561151b57600080fd5b5061152e9050565b61152e83838361191e565b505050565b600081848411156115dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115a1578181015183820152602001611589565b50505050905090810190601f1680156115ce5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008282018381101561165857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b73ffffffffffffffffffffffffffffffffffffffff82166116e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6116ed6000838361152e565b600254611700908263ffffffff6115e416565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054611739908263ffffffff6115e416565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b73ffffffffffffffffffffffffffffffffffffffff8216611808576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611c186021913960400191505060405180910390fd5b6118148260008361152e565b61186481604051806060016040528060228152602001611b606022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff61153316565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205560025461189d908263ffffffff611afa16565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600064174876e8008206801580159061190d57506298968081105b156107805780836064028161077c57fe5b73ffffffffffffffffffffffffffffffffffffffff831661198a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180611c396025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166119f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611b3d6023913960400191505060405180910390fd5b611a0183838361152e565b611a5181604051806060016040528060268152602001611bca6026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff61153316565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054611a93908263ffffffff6115e416565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600061165883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061153356fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220fd245a8c7efcaae4a65f2731cc7c0b6ef0618a52b60ff0bd544639bc84dba51564736f6c634300060600335065726d69742861646472657373206f776e65722c61646472657373207370656e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63652c75696e7432353620646561646c696e6529454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc65065726d69742861646472657373206f776e65722c61646472657373207370656e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63652c75696e7432353620646561646c696e6529454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374290000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419000000000000000000000000922018674c12a7f0d394ebeef9b58f186cde13c1000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x60806040526004361061032d5760003560e01c806395d89b41116101a5578063d505accf116100ec578063ec0c2beb11610095578063f6bcbd311161006f578063f6bcbd3114610bfd578063f99b1bdb14610c45578063fa352c0014610c9b578063faddc92914610cdb57610347565b8063ec0c2beb14610bbe578063f16673a414610bd3578063f2fe0b4214610be857610347565b8063e6a3c053116100c6578063e6a3c05314610b54578063e71bdf4114610b69578063e833091f14610ba957610347565b8063d505accf14610a4b578063d7020d0a14610ab6578063dd62ed3e14610b0c57610347565b8063a9059cbb1161014e578063c2eebdcf11610128578063c2eebdcf146109dc578063c560ce9a14610a09578063cea55f5714610a3657610347565b8063a9059cbb14610941578063b5d832fe14610987578063c0bd65d7146109c757610347565b8063a0c8ee961161017f578063a0c8ee96146108b3578063a3e6ba94146108e6578063a457c2d7146108fb57610347565b806395d89b41146108335780639670393d146108485780639a4c6a9a1461085d57610347565b80633e1028a0116102745780636ea51d081161021d5780637b1837de116101f75780637b1837de146107905780637ecebe00146107c95780638382f4ee1461080957806393b11ebe1461081e57610347565b80636ea51d08146106fd57806370a082311461073b57806371b0a1541461077b57610347565b806349f3bb961161024e57806349f3bb96146106a657806361fbccb5146106d35780636a146024146106e857610347565b80633e1028a01461060657806340c10f1914610658578063459e414f1461069157610347565b80632db1187f116102d6578063313ce567116102b0578063313ce567146105805780633644e515146105ab57806339509351146105c057610347565b80632db1187f146105235780633098e2791461055657806330adf81f1461056b57610347565b80631a28ff05116103075780631a28ff051461045757806323b872dd146104be5780632c23183d1461050e57610347565b806306fdde031461034c578063095ea7b3146103d657806318160ddd1461043057610347565b36610347576103443361033f34610cf0565b610d20565b50005b600080fd5b34801561035857600080fd5b50610361610f80565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561039b578181015183820152602001610383565b50505050905090810190601f1680156103c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103e257600080fd5b5061041c600480360360408110156103f957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611035565b604080519115158252519081900360200190f35b34801561043c57600080fd5b50610445611053565b60408051918252519081900360200190f35b34801561046357600080fd5b506104bc600480360360c081101561047a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060ff6060820135169060808101359060a00135611059565b005b3480156104ca57600080fd5b5061041c600480360360608110156104e157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611307565b34801561051a57600080fd5b506104456113ae565b34801561052f57600080fd5b506104456004803603604081101561054657600080fd5b508035906020013560ff1661145b565b34801561056257600080fd5b50610445611476565b34801561057757600080fd5b5061044561150e565b34801561058c57600080fd5b50610595611532565b6040805160ff9092168252519081900360200190f35b3480156105b757600080fd5b5061044561153b565b3480156105cc57600080fd5b5061041c600480360360408110156105e357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561155f565b34801561061257600080fd5b5061061b6115c0565b6040805163ffffffff90931683527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911660208301528051918290030190f35b6104456004803603604081101561066e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356115f4565b34801561069d57600080fd5b50610445611600565b3480156106b257600080fd5b50610445600480360360208110156106c957600080fd5b503560ff16611624565b3480156106df57600080fd5b5061044561164f565b3480156106f457600080fd5b5061044561165b565b34801561070957600080fd5b50610712611667565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561074757600080fd5b506104456004803603602081101561075e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661168b565b34801561078757600080fd5b506104456116b7565b610445600480360360408110156107a657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356116bc565b3480156107d557600080fd5b50610445600480360360208110156107ec57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166116c8565b34801561081557600080fd5b506104456116da565b34801561082a57600080fd5b506104456116df565b34801561083f57600080fd5b506103616116f2565b34801561085457600080fd5b5061061b611771565b34801561086957600080fd5b506104456004803603608081101561088057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604081013590606001356117a5565b3480156108bf57600080fd5b50610445600480360360408110156108d657600080fd5b508035906020013560ff166118ea565b3480156108f257600080fd5b506104456118fe565b34801561090757600080fd5b5061041c6004803603604081101561091e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611925565b34801561094d57600080fd5b5061041c6004803603604081101561096457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356119a0565b34801561099357600080fd5b50610445600480360360208110156109aa57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119b4565b3480156109d357600080fd5b506104456119c6565b3480156109e857600080fd5b50610445600480360360208110156109ff57600080fd5b503560ff166119ea565b348015610a1557600080fd5b5061044560048036036020811015610a2c57600080fd5b503560ff16611a0d565b348015610a4257600080fd5b50610445611aca565b348015610a5757600080fd5b506104bc600480360360e0811015610a6e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135611adf565b348015610ac257600080fd5b5061044560048036036080811015610ad957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060600135611d98565b348015610b1857600080fd5b5061044560048036036040811015610b2f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611e95565b348015610b6057600080fd5b50610445611ecd565b348015610b7557600080fd5b506104bc60048036036020811015610b8c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611eed565b348015610bb557600080fd5b50610445611efa565b348015610bca57600080fd5b50610445611f04565b348015610bdf57600080fd5b50610445611fe7565b348015610bf457600080fd5b50610445611feb565b348015610c0957600080fd5b5061041c60048036036040811015610c2057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166120a2565b348015610c5157600080fd5b5061044560048036036080811015610c6857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604081013590606001356120c2565b348015610ca757600080fd5b506104bc60048036036020811015610cbe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612163565b348015610ce757600080fd5b5061044561216d565b600064174876e80082068015801590610d0b57506298968081105b15610d1a5760648382025b0491505b50919050565b600080610d2b611fe7565b90506000610d3f823463ffffffff61217416565b905060008111610d96576040805162461bcd60e51b815260206004820152601360248201527f46756e64206265666f7265206d696e74696e6700000000000000000000000000604482015290519081900360640190fd5b6000610da0611efa565b90506000610dac611053565b90506000610dbb8385846121b6565b9050610dca83348685856121f1565b955086861015610e21576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b6000610e3d8487610e38868b63ffffffff61231e16565b6121b6565b9050610e518282610e4c6113ae565b612378565b610e5b8988612482565b600954421115610eb2576040805162461bcd60e51b815260206004820152601c60248201527f547269616c20657870697265642c2072656d6f76652061737365747300000000604482015290519081900360640190fd5b670de0b6b3a7640000341115610f0f576040805162461bcd60e51b815260206004820152601660248201527f4361707065642061742031204554482070657220747800000000000000000000604482015290519081900360640190fd5b68056bc75e2d63100000610f21611fe7565b1115610f74576040805162461bcd60e51b815260206004820152601860248201527f4361707065642061742031303020706f6f6c6564204554480000000000000000604482015290519081900360640190fd5b50505050505092915050565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561102a5780601f10610fff5761010080835404028352916020019161102a565b820191906000526020600020905b81548152906001019060200180831161100d57829003601f168201915b505050505090505b90565b60006110496110426125a5565b84846125a9565b5060015b92915050565b60025490565b428410156110ae576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a205369676e6174757265206578706972656400000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80871660008181526007602090815260408083208054600180820190925582517f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb78186015280840196909652958b166060860152608085019590955260a08085018a90528151808603909101815260c0850182528051908301207f190100000000000000000000000000000000000000000000000000000000000060e08601527fe659cd4b84ab11547a2df5648508538aab5ccd2f05c3d74fc65eb7c947de23e260e286015261010280860182905282518087039091018152610122860180845281519185019190912090859052610142860180845281905260ff8a1661016287015261018286018990526101a2860188905291519095919491926101c28084019391927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015611226573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906112a157508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6112f2576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20496e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b6112fc89896126bc565b505050505050505050565b60006113148484846127db565b6113a4846113206125a5565b61139f856040518060600160405280602881526020016145cd6028913973ffffffffffffffffffffffffffffffffffffffff8a1660009081526001602052604081209061136b6125a5565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054919063ffffffff61289316565b6125a9565b5060019392505050565b600b5460009081906113de90603c906113d290429063ffffffff9081169061217416565b9063ffffffff6128ed16565b905060006113f382600a63ffffffff61290b16565b600b54909150611454908290611448906114339064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683612961565b670de0b6b3a76400009063ffffffff61231e16565b9063ffffffff61217416565b9250505090565b600061146f6114686118fe565b848461298b565b9392505050565b600a5460009064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161561103257600a546000906114cb9062015180906113d290429063ffffffff9081169061217416565b905060006114d88261299e565b600a549091506114549064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16826129ca565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b7f262df23ae4f55eabdf69a193d74d500359aa82bb242237b2c2c5759f968a259781565b600061104961156c6125a5565b8461139f856001600061157d6125a5565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff61231e16565b600b5463ffffffff81169064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682565b600061146f8383610d20565b7fe659cd4b84ab11547a2df5648508538aab5ccd2f05c3d74fc65eb7c947de23e281565b60008061162f6118fe565b905061146f838261164a84611642611fe7565b610e38611053565b6129fd565b670b1a2bc2ec50000081565b670de0b6b3a764000081565b7f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39481565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b603c81565b600061146f8383612b22565b60066020526000908152604090205481565b607881565b6e01000000000000000000000000000081565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561102a5780601f10610fff5761010080835404028352916020019161102a565b600a5463ffffffff81169064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682565b6000846040518060400160405280601781526020017f4f6e6c7920686f6c646572206f722064656c65676174650000000000000000008152508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611848575073ffffffffffffffffffffffffffffffffffffffff8216600090815260086020908152604080832033845290915290205460ff165b81906118d25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561189757818101518382015260200161187f565b50505050905090810190601f1680156118c45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506118df87878787612e7c565b979650505050505050565b600061146f6118f76118fe565b848461308d565b600061192061190b6130a0565b6119136130aa565b61191b6130b4565b6130be565b905090565b60006110496119326125a5565b8461139f8560405180606001604052806025815260200161465f602591396001600061195c6125a5565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61289316565b60006110496119ad6125a5565b84846127db565b60076020526000908152604090205481565b7f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb781565b600061104d6119f76118fe565b6119ff611fe7565b611a07611053565b856130f3565b600061104d82611a1b6118fe565b611a23611fe7565b611a2b611053565b7f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a9157600080fd5b505afa158015611aa5573d6000803e3d6000fd5b505050506040513d6020811015611abb57600080fd5b5051611ac56113ae565b613181565b6000611920611ad76118fe565b611642611fe7565b42841015611b34576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80881660008181526006602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601527f262df23ae4f55eabdf69a193d74d500359aa82bb242237b2c2c5759f968a259761010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e28084019391927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015611cb5573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611d3057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611d81576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b611d8c8a8a8a6125a9565b50505050505050505050565b6000846040518060400160405280601781526020017f4f6e6c7920686f6c646572206f722064656c65676174650000000000000000008152508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611e3b575073ffffffffffffffffffffffffffffffffffffffff8216600090815260086020908152604080832033845290915290205460ff165b8190611e885760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561189757818101518382015260200161187f565b506118df8787878761327b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b600080611ed86133af565b915050611ee4816133e0565b50909392505050565b611ef733826126bc565b50565b6000611920613448565b600d54604080517ffe2c6198000000000000000000000000000000000000000000000000000000008152602060048201819052600360248301527f4554480000000000000000000000000000000000000000000000000000000000604483015291516000936119209364e8d4a510009373ffffffffffffffffffffffffffffffffffffffff9092169263fe2c6198926064808201939291829003018186803b158015611faf57600080fd5b505afa158015611fc3573d6000803e3d6000fd5b505050506040513d6020811015611fd957600080fd5b50519063ffffffff61346516565b4790565b600080600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561205657600080fd5b505afa15801561206a573d6000803e3d6000fd5b505050506040513d60a081101561208057600080fd5b5060200151905061209c816402540be40063ffffffff61346516565b91505090565b600860209081526000928352604080842090915290825290205460ff1681565b60003373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a394161461214e576040805162461bcd60e51b815260206004820152601160248201527f5265737472696374656420746f2046554d000000000000000000000000000000604482015290519081900360640190fd5b61215a85858585612e7c565b95945050505050565b611ef733826134be565b6201518081565b600061146f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612893565b6000806121c9848663ffffffff61296116565b905083156121e6576121e1838263ffffffff6135d416565b61215a565b600095945050505050565b600080612200600088856129fd565b90506000612214868863ffffffff61231e16565b9050846122325761222b878363ffffffff6128ed16565b9250612313565b670de0b6b3a764000084116122c55760006122878361227b8961226f670de0b6b3a764000061144861226a898563ffffffff6128ed16565b613618565b9063ffffffff61346516565b9063ffffffff61364c16565b90506122bd866114486122b861229c8a61368e565b6122ac868c63ffffffff61231e16565b9063ffffffff61296116565b6136a9565b935050612313565b60006122ea6122da878563ffffffff6129ca16565b61227b898b63ffffffff61346516565b905061230f6122ff838363ffffffff61217416565b61227b888463ffffffff61346516565b9350505b505095945050505050565b60008282018381101561146f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b821580159061238657508115155b1561247d57600b5464010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600083806123c68761226f8782613465565b816123cd57fe5b04816123d557fe5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000164263ffffffff9081169190911716640100000000939092047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811693909302919091179055604080518481526020810183905281519293507f3af9fe9b92def18e94efef4175b9165aa71c2b1f8e3339bf1f23872922019733929081900390910190a150505b505050565b73ffffffffffffffffffffffffffffffffffffffff82166124ea576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6124f66000838361247d565b600254612509908263ffffffff61231e16565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054612542908263ffffffff61231e16565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b3390565b73ffffffffffffffffffffffffffffffffffffffff83166125fb5760405162461bcd60e51b815260040180806020018281038252602481526020018061463b6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661264d5760405162461bcd60e51b815260040180806020018281038252602281526020018061452a6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526008602090815260408083209385168352929052205460ff1615612744576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20416c72656164792064656c65676174656400000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80831660008181526008602090815260408083209486168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155825190815291517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b73ffffffffffffffffffffffffffffffffffffffff821630148061284a57507f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80612869575073ffffffffffffffffffffffffffffffffffffffff8216155b156128885761288283848361287d85613728565b61327b565b5061247d565b61247d838383613754565b600081848411156128e55760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561189757818101518382015260200161187f565b505050900390565b600061146f8261227b85670de0b6b3a764000063ffffffff61346516565b60008067016345785d8a00006129288566b1a2bc2ec5000061231e565b8161292f57fe5b04905082600a8204111561294757600091505061104d565b612959670cf2cc8ff8457df8826138fc565b949350505050565b6000670de0b6b3a764000061297c848463ffffffff61346516565b8161298357fe5b049392505050565b600061295983858463ffffffff61395116565b600061104d827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61290b565b6000670de0b6b3a764000061297c670de0b6b3a763ffff6129f1868663ffffffff61346516565b9063ffffffff61231e16565b60008080856001811115612a0d57fe5b14612a19576000612a1c565b60015b9050612a3184670de0b6b3a76400008361308d565b91506000612a3d6113ae565b9050670de0b6b3a76400008411612ab6576000866001811115612a5c57fe5b148015612a705750670de0b6b3a764000081105b80612a9857506001866001811115612a8457fe5b148015612a985750670de0b6b3a764000081115b15612ab157612aae83828463ffffffff61397e16565b92505b612b19565b6000866001811115612ac457fe5b148015612ad85750670de0b6b3a764000081115b80612b0057506001866001811115612aec57fe5b148015612b005750670de0b6b3a764000081105b15612b1957612b1683828463ffffffff61395116565b92505b50509392505050565b600080612b2d611efa565b90506000612b39611fe7565b90506000612b4d823463ffffffff61217416565b90506000612b59611053565b90506000612b688584846121b6565b905060007f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612bd257600080fd5b505afa158015612be6573d6000803e3d6000fd5b505050506040513d6020811015612bfc57600080fd5b50519050612c0b8285836139a6565b6000612c156113ae565b9050612c25873487878686613b19565b975088881015612c7c576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b6000612c898888876121b6565b9050612c96848284612378565b7f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39473ffffffffffffffffffffffffffffffffffffffff166340c10f198c8b6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015612d3d57600080fd5b505af1158015612d51573d6000803e3d6000fd5b50505050600954421115612dac576040805162461bcd60e51b815260206004820152601c60248201527f547269616c20657870697265642c2072656d6f76652061737365747300000000604482015290519081900360640190fd5b670de0b6b3a7640000341115612e09576040805162461bcd60e51b815260206004820152601660248201527f4361707065642061742031204554482070657220747800000000000000000000604482015290519081900360640190fd5b68056bc75e2d63100000612e1b611fe7565b1115612e6e576040805162461bcd60e51b815260206004820152601860248201527f4361707065642061742031303020706f6f6c6564204554480000000000000000604482015290519081900360640190fd5b505050505050505092915050565b600080612e87611efa565b90506000612e93611fe7565b90506000612e9f611053565b90506000612eae8484846121b6565b9050612ebc84888585613b7b565b945085851015612f13576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b6000612f2f85612f29868963ffffffff61217416565b856121b6565b9050670b1a2bc2ec500000811115612f8e576040805162461bcd60e51b815260206004820152601060248201527f4465627420726174696f203e206d617800000000000000000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39473ffffffffffffffffffffffffffffffffffffffff16639dc29fac8b8a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561303557600080fd5b505af1158015613049573d6000803e3d6000fd5b5050505061305a8282610e4c6113ae565b61308073ffffffffffffffffffffffffffffffffffffffff8a168763ffffffff613c9016565b5050505050949350505050565b600061295983858463ffffffff61397e16565b6000611920611feb565b6000611920611f04565b6000611920611ecd565b60008284118284118584118083146130e857811515831515146130e157846130e3565b855b6118df565b509495945050505050565b6000808083600181111561310357fe5b1461310f576000613112565b60015b905061311f86858361308d565b8503915084821315613178576040805162461bcd60e51b815260206004820152600f60248201527f556e646572666c6f77206572726f720000000000000000000000000000000000604482015290519081900360640190fd5b50949350505050565b6000808088600181111561319157fe5b1461319d5760006131a0565b60015b9050836131c2576131ba87670de0b6b3a76400008361308d565b915050613271565b60006131d0888888856130f3565b905060008113156131f1576131ec81868463ffffffff61397e16565b6131f4565b60005b9250600089600181111561320457fe5b141561324b57670de0b6b3a764000084111561322d5761322a838563ffffffff6129ca16565b92505b6000613237611476565b905080841015613245578093505b5061326e565b670de0b6b3a764000084101561326e5761326b838563ffffffff61296116565b92505b50505b9695505050505050565b600080613286611efa565b90506000613292611fe7565b9050600061329e611053565b905060006132ad8484846121b6565b90506132bc8488858585613d82565b945085851015613313576040805162461bcd60e51b815260206004820152601160248201527f4c696d6974206e6f742072656163686564000000000000000000000000000000604482015290519081900360640190fd5b600061333985613329868963ffffffff61217416565b610e38868c63ffffffff61217416565b9050670de0b6b3a7640000811115613398576040805162461bcd60e51b815260206004820152601160248201527f4465627420726174696f203e2031303025000000000000000000000000000000604482015290519081900360640190fd5b6133a28a89613e2e565b61305a8282610e4c6113ae565b600e54600f54600091829163ffffffff9182169116116133d257600f600e6133d7565b600e600f5b90939092509050565b60008060006133ed613f6a565b909250905060006133fe83866141ac565b805490915061343e908490849063ffffffff81169064010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661424d565b9350509193909250565b60006119206134556130a0565b61345d6130aa565b61191b614272565b6000826134745750600061104d565b8282028284828161348157fe5b041461146f5760405162461bcd60e51b81526004018080602001828103825260218152602001806145ac6021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff80831660009081526008602090815260408083209385168352929052205460ff16613545576040805162461bcd60e51b815260206004820152601e60248201527f44656c656761626c653a20416c726561647920756e64656c6567617465640000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff808316600081815260086020908152604080832094861680845294825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051928352517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b600061146f8261227b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82016129f187670de0b6b3a764000063ffffffff61346516565b60006ec097ce7bc90715b34b9f100000000061363e8361226f818063ffffffff61346516565b8161364557fe5b0492915050565b600061146f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506142b7565b6000670de0b6b3a764000061363e838063ffffffff61346516565b600081156116b257600060036136cd84671bc16d674ec8000063ffffffff61231e16565b816136d457fe5b04905060006136f8846ec097ce7bc90715b34b9f100000000063ffffffff61346516565b90505b8192506003838402828161370b57fe5b04848501018161371757fe5b0491508282106136fb575050919050565b600064174876e8008206801580159061374357506298968081105b15610d1a57808360640281610d1657fe5b73ffffffffffffffffffffffffffffffffffffffff83166137a65760405162461bcd60e51b81526004018080602001828103825260258152602001806146166025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166137f85760405162461bcd60e51b81526004018080602001828103825260238152602001806144e56023913960400191505060405180910390fd5b61380383838361247d565b6138538160405180606001604052806026815260200161454c6026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff61289316565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054613895908263ffffffff61231e16565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60006002820661391457670de0b6b3a7640000613916565b825b90506002820491505b811561104d5761392e8361368e565b92506002820615613946576139438184612961565b90505b60028204915061391f565b60008082600181111561396057fe5b146139745761396f84846129ca565b612959565b6129598484612961565b60008082600181111561398d57fe5b1461399c5761396f84846135d4565b61295984846128ed565b600a5464010000000090047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16670b1a2bc2ec5000008411613a2c578015613a27576000600a81905560408051838152602081019290925280517f05ddb88d20c718baf5e5231bd021d330d7e31a9e676417079f0d0f518e2fde559281900390910190a15b613b13565b80613b1357600a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000164263ffffffff16178155613a99908390613a8d908690676f05b59d3b20000004670de0b6b3a7640000039063ffffffff6129ca16565b9063ffffffff6135d416565b600a805463ffffffff166401000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416810291909117918290556040805185815291909204909216602083015280517f05ddb88d20c718baf5e5231bd021d330d7e31a9e676417079f0d0f518e2fde559281900390910190a15b50505050565b600080613b2b60008988888888613181565b905084613b4957613b42878263ffffffff6128ed16565b9150613b70565b6000613b5b878963ffffffff61231e16565b905061326b6122da828463ffffffff6129ca16565b509695505050505050565b6000807f000000000000000000000000f04a5d82ff8a801f7d45e9c14cdcf73deff1a39473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613be457600080fd5b505afa158015613bf8573d6000803e3d6000fd5b505050506040513d6020811015613c0e57600080fd5b505190506000613c25600188878786611ac56113ae565b905083613c4357613c3c868263ffffffff61296116565b9250613c86565b6118df613c66613c59888463ffffffff6129ca16565b879063ffffffff61231e16565b61227b613c79898563ffffffff61296116565b889063ffffffff61346516565b5050949350505050565b80471015613ce5576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b60405160009073ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d8060008114613d3d576040519150601f19603f3d011682016040523d82523d6000602084013e613d42565b606091505b505090508061247d5760405162461bcd60e51b815260040180806020018281038252603a815260200180614572603a913960400191505060405180910390fd5b600080613d91600188856129fd565b90506000613da5858863ffffffff61217416565b90506000613dec613ddc613dc7613dc2858a63ffffffff6135d416565b61431c565b670de0b6b3a76400009063ffffffff61217416565b6122ac858963ffffffff61296116565b905061230f613e21613e1c613e078a8563ffffffff61217416565b613e108b614355565b9063ffffffff6129ca16565b61437c565b889063ffffffff61217416565b73ffffffffffffffffffffffffffffffffffffffff8216613e805760405162461bcd60e51b81526004018080602001828103825260218152602001806145f56021913960400191505060405180910390fd5b613e8c8260008361247d565b613edc816040518060600160405280602281526020016145086022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff61289316565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902055600254613f15908263ffffffff61217416565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000807f000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015613fd357600080fd5b505afa158015613fe7573d6000803e3d6000fd5b505050506040513d6060811015613ffd57600080fd5b506040015163ffffffff16915060007f00000000000000000000000000000000000000000000000000000000000000016140c8577f000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc73ffffffffffffffffffffffffffffffffffffffff16635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561409757600080fd5b505afa1580156140ab573d6000803e3d6000fd5b505050506040513d60208110156140c157600080fd5b505161415b565b7f000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc73ffffffffffffffffffffffffffffffffffffffff16635a3d54936040518163ffffffff1660e01b815260040160206040518083038186803b15801561412e57600080fd5b505afa158015614142573d6000803e3d6000fd5b505050506040513d602081101561415857600080fd5b50515b90506e01000000000000000000000000000061419d827f000000000000000000000000000000000000000c9f2c9cd04674edea4000000063ffffffff61346516565b816141a457fe5b049150509091565b6000806141ba84600e6143ad565b905060006141c985600f6143ad565b905081156141e95780156141df578392506141e4565b600e92505b614245565b80156141f857600f9250614245565b6040805162461bcd60e51b815260206004820152601d60248201527f426f74682073746f7265642070726963657320746f6f20726563656e74000000604482015290519081900360640190fd5b505092915050565b600061215a614262868563ffffffff61217416565b61227b868563ffffffff61217416565b600080600061427f6133af565b9150915060008061428f836133e0565b919650925090506142a082846143ad565b156142b0576142b08282866143bc565b5050505090565b600081836143065760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561189757818101518382015260200161187f565b50600083858161431257fe5b0495945050505050565b60006ec097ce7bc90715b34b9f100000000061363e6ec097ce7bc90715b34b9f0fffffffff6129f18561226f818063ffffffff61346516565b6000670de0b6b3a764000061363e670de0b6b3a763ffff6129f1858063ffffffff61346516565b6000614387826136a9565b905080800281026ec097ce7bc90715b34b9f10000000008302146116b257600101919050565b5463ffffffff16607801111590565b63ffffffff831115614415576040805162461bcd60e51b815260206004820152601260248201527f74696d657374616d70206f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff821115614486576040805162461bcd60e51b815260206004820152601560248201527f70726963655365636f6e6473206f766572666c6f770000000000000000000000604482015290519081900360640190fd5b805463ffffffff9384167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316640100000000029316929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001617905556fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122064627c1b8491319e4adf03479b1eb26789acb90feebba45a03f61eec762db93564736f6c63430006060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419000000000000000000000000922018674c12a7f0d394ebeef9b58f186cde13c1000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : chainlinkAggregator (address): 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
Arg [1] : compoundView (address): 0x922018674c12a7F0D394ebEEf9B58F186CdE13c1
Arg [2] : uniswapPair (address): 0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc
Arg [3] : uniswapToken0Decimals (uint256): 6
Arg [4] : uniswapToken1Decimals (uint256): 18
Arg [5] : uniswapTokensInReverseOrder (bool): True
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419
Arg [1] : 000000000000000000000000922018674c12a7f0d394ebeef9b58f186cde13c1
Arg [2] : 000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
90356:646:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51087:56;51096:10;51108:34;51132:9;51108:23;:34::i;:::-;51087:8;:56::i;:::-;;90356:646;;12:1:-1;9;2:12;17624:83:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17624: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;17624:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19730:169;;5:9:-1;2:2;;;27:1;24;17:12;2:2;19730:169:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;19730:169:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;18699:100;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18699:100:0;;;:::i;:::-;;;;;;;;;;;;;;;;33463:864;;5:9:-1;2:2;;;27:1;24;17:12;2:2;33463:864:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;33463:864:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;20373:321;;5:9:-1;2:2;;;27:1;24;17:12;2:2;20373:321:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;20373:321:0;;;;;;;;;;;;;;;;;;:::i;71846:780::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71846:780:0;;;:::i;73151:166::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;73151:166:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;73151:166:0;;;;;;;;;:::i;70490:417::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70490:417:0;;;:::i;29069:138::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;29069:138:0;;;:::i;18551:83::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18551:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;29214:41;;5:9:-1;2:2;;;27:1;24;17:12;2:2;29214:41:0;;;:::i;21103:218::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;21103:218:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;21103:218:0;;;;;;;;;:::i;47601:93::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47601:93:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;48228:141;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;48228:141:0;;;;;;;;;:::i;32105:41::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;32105:41:0;;;:::i;74116:211::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74116:211:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74116:211:0;;;;:::i;47056:50::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47056:50:0;;;:::i;47014:35::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47014:35:0;;;:::i;47340:24::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47340:24:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;18862:119;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18862:119:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;18862:119:0;;;;:::i;47242:62::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47242:62:0;;;:::i;49260:141::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;49260:141:0;;;;;;;;;:::i;29009:51::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;29009:51:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;29009:51:0;;;;:::i;81195:48::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81195:48:0;;;:::i;81353:62::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;81353:62:0;;;:::i;17826:87::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17826:87:0;;;:::i;47556:38::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47556:38:0;;;:::i;49740:278::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;49740:278:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;49740:278:0;;;;;;;;;;;;;;;;;;;;;;;:::i;73519:166::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;73519:166:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;73519:166:0;;;;;;;;;:::i;89158:324::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;89158:324:0;;;:::i;21824:269::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;21824:269:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;21824:269:0;;;;;;;;;:::i;19194:175::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;19194:175:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;19194:175:0;;;;;;;;;:::i;32153:46::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;32153:46:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;32153:46:0;;;;:::i;31986:112::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;31986:112:0;;;:::i;72783:166::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;72783:166:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;72783:166:0;;;;:::i;74528:186::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74528:186:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74528:186:0;;;;:::i;73782:133::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;73782:133:0;;;:::i;30017:905::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;30017:905:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;30017:905:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;48653:274::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;48653:274:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;48653:274:0;;;;;;;;;;;;;;;;;;;;;;;:::i;19432:151::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;19432:151:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;19432:151:0;;;;;;;;;;;:::i;84087:209::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84087:209:0;;;:::i;33119:99::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;33119:99:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;33119:99:0;;;;:::i;90853:146::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;90853:146:0;;;:::i;77418:134::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;77418:134:0;;;:::i;60279:98::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;60279:98:0;;;:::i;76383:206::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;76383:206:0;;;:::i;32208:61::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;32208:61:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;32208:61:0;;;;;;;;;;;:::i;50448:289::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;50448:289:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;50448:289:0;;;;;;;;;;;;;;;;;;;;;;;:::i;33292:105::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;33292:105:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;33292:105:0;;;;:::i;47136:57::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47136:57:0;;;:::i;42324:249::-;42385:16;42438:12;42430:20;;42465:13;;;;;:36;;;42493:8;42482;:19;42465:36;42461:105;;;42551:3;42532:16;;;:22;;42518:36;;42461:105;42324:249;;;;:::o;51990:1248::-;52054:11;52167:17;52187:9;:7;:9::i;:::-;52167:29;-1:-1:-1;52207:14:0;52224:27;52167:29;52241:9;52224:27;:16;:27;:::i;:::-;52207:44;;52359:1;52347:9;:13;52339:45;;;;;-1:-1:-1;;;52339:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52430:16;52449:18;:16;:18::i;:::-;52430:37;;52478:19;52500:13;:11;:13::i;:::-;52478:35;;52524:17;52544:49;52554:11;52567:9;52578:14;52544:9;:49::i;:::-;52524:69;;52613:76;52625:11;52638:9;52649;52660:14;52676:12;52613:11;:76::i;:::-;52604:85;;52718:9;52708:6;:19;;52700:49;;;;;-1:-1:-1;;;52700:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52837:17;52857:64;52867:11;52880:12;52894:26;:14;52913:6;52894:26;:18;:26;:::i;:::-;52857:9;:64::i;:::-;52837:84;;52932:73;52957:12;52971;52985:19;:17;:19::i;:::-;52932:24;:73::i;:::-;53016:17;53022:2;53026:6;53016:5;:17::i;:::-;53061:8;;53054:3;:15;;53046:56;;;;;-1:-1:-1;;;53046:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;53134:4;53121:9;:17;;53113:52;;;;;-1:-1:-1;;;53113:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;53197:4;53184:9;:7;:9::i;:::-;:17;;53176:54;;;;;-1:-1:-1;;;53176:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;51990:1248;;;;;;;;;;:::o;17624:83::-;17694:5;17687:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17661:13;;17687:12;;17694:5;;17687:12;;17694:5;17687:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17624:83;;:::o;19730:169::-;19813:4;19830:39;19839:12;:10;:12::i;:::-;19853:7;19862:6;19830:8;:39::i;:::-;-1:-1:-1;19887:4:0;19730:169;;;;;:::o;18699:100::-;18779:12;;18699:100;:::o;33463:864::-;33611:15;33599:8;:27;;33591:68;;;;;-1:-1:-1;;;33591:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;33833:20;;;;33672:18;33833:20;;;:14;:20;;;;;;;;:22;;;;;;;;;33717:180;;33746:18;33717:180;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;33717:180:0;;;;;33693:215;;;;;;33962:124;;;;;34026:16;33962:124;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;33962:124:0;;;;;;33938:159;;;;;;;;;34125:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33693:215;;33938:159;;33833:22;;34125:26;;;;;33833:20;;-1:-1:-1;34125:26:0;;;;;;;;;;33833:22;34125:26;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;34125:26:0;;;;;;-1:-1:-1;;34184:20:0;;;;;;;:38;;;34218:4;34208:14;;:6;:14;;;34184:38;34162:116;;;;;-1:-1:-1;;;34162:116:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;34291:28;34304:4;34310:8;34291:12;:28::i;:::-;33463:864;;;;;;;;;:::o;20373:321::-;20479:4;20496:36;20506:6;20514:9;20525:6;20496:9;:36::i;:::-;20543:121;20552:6;20560:12;:10;:12::i;:::-;20574:89;20612:6;20574:89;;;;;;;;;;;;;;;;;:19;;;;;;;:11;:19;;;;;;20594:12;:10;:12::i;:::-;20574:33;;;;;;;;;;;;;-1:-1:-1;20574:33:0;;;:89;;:37;:89;:::i;:::-;20543:8;:121::i;:::-;-1:-1:-1;20682:4:0;20373:321;;;;;:::o;71846:780::-;71963:23;:33;71896:15;;;;71943:96;;47295:9;;71943:54;;:15;;71963:33;;;;;71943:19;:54;:::i;:::-;:65;:96;:65;:96;:::i;:::-;71924:115;-1:-1:-1;72050:16:0;72069:26;71924:115;72092:2;72069:26;:22;:26;:::i;:::-;72546:23;:29;72050:45;;-1:-1:-1;72530:88:0;;72050:45;;72530:71;;72538:62;;72546:29;;;;;72050:45;72538:49;:62::i;:::-;47041:8;;72530:71;:7;:71;:::i;:::-;:75;:88;:75;:88;:::i;:::-;72517:101;;71846:780;;;:::o;73151:166::-;73232:11;73265:44;73274:13;:11;:13::i;:::-;73289:9;73300:8;73265;:44::i;:::-;73256:53;73151:166;-1:-1:-1;;;73151:166:0:o;70490:417::-;70563:20;:26;70537:9;;70563:26;;;;;:31;70559:311;;70650:20;:30;70611:16;;70630:91;;47187:6;;70630:51;;:15;;70650:30;;;;;70630:19;:51;:::i;:91::-;70611:110;;70736:16;70755:24;:11;:22;:24::i;:::-;70809:20;:26;70736:43;;-1:-1:-1;70801:57:0;;70809:26;;;;;70736:43;70801:44;:57::i;29069:138::-;;;:::o;18551:83::-;18617:9;;;;18551:83;:::o;29214:41::-;;;:::o;21103:218::-;21191:4;21208:83;21217:12;:10;:12::i;:::-;21231:7;21240:50;21279:10;21240:11;:25;21252:12;:10;:12::i;:::-;21240:25;;;;;;;;;;;;;;;;;;-1:-1:-1;21240:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;47601:93::-;;;;;;;;;;;;;:::o;48228:141::-;48305:11;48338:23;48347:2;48351:9;48338:8;:23::i;32105:41::-;;;:::o;74116:211::-;74168:10;74191:16;74210:13;:11;:13::i;:::-;74191:32;;74242:77;74251:4;74257:11;74270:48;74280:11;74293:9;:7;:9::i;:::-;74304:13;:11;:13::i;74270:48::-;74242:8;:77::i;47056:50::-;47094:12;47056:50;:::o;47014:35::-;47041:8;47014:35;:::o;47340:24::-;;;:::o;18862:119::-;18955:18;;;18928:7;18955:18;;;;;;;;;;;18862:119;;;;:::o;47242:62::-;47295:9;47242:62;:::o;49260:141::-;49337:11;49370:23;49379:2;49383:9;49370:8;:23::i;29009:51::-;;;;;;;;;;;;;:::o;81195:48::-;81234:9;81195:48;:::o;81353:62::-;81407:8;81353:62;:::o;17826:87::-;17898:7;17891:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17865:13;;17891:14;;17898:7;;17891:14;;17898:7;17891:14;;;;;;;;;;;;;;;;;;;;;;;;47556:38;;;;;;;;;;;;;:::o;49740:278::-;49930:11;49879:4;32830:218;;;;;;;;;;;;;;;;;32951:6;32937:20;;:10;:20;;;:53;;;-1:-1:-1;32961:17:0;;;;;;;:9;:17;;;;;;;;32979:10;32961:29;;;;;;;;;;32937:53;33005:12;32915:113;;;;;-1:-1:-1;;;32915:113: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;32915:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49968:42:::1;49979:4;49985:2;49989:9;50000;49968:10;:42::i;:::-;49959:51:::0;49740:278;-1:-1:-1;;;;;;;49740:278:0:o;73519:166::-;73600:11;73633:44;73642:13;:11;:13::i;:::-;73657:9;73668:8;73633;:44::i;89158:324::-;89281:10;89317:157;89324:29;:27;:29::i;:::-;89379:32;:30;:32::i;:::-;89437:36;:34;:36::i;:::-;89317:6;:157::i;:::-;89309:165;;89158:324;:::o;21824:269::-;21917:4;21934:129;21943:12;:10;:12::i;:::-;21957:7;21966:96;22005:15;21966:96;;;;;;;;;;;;;;;;;:11;:25;21978:12;:10;:12::i;:::-;21966:25;;;;;;;;;;;;;;;;;;-1:-1:-1;21966:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;19194:175::-;19280:4;19297:42;19307:12;:10;:12::i;:::-;19321:9;19332:6;19297:9;:42::i;32153:46::-;;;;;;;;;;;;;:::o;31986:112::-;;;:::o;72783:166::-;72849:10;72881:60;72891:13;:11;:13::i;:::-;72906:9;:7;:9::i;:::-;72917:13;:11;:13::i;:::-;72932:8;72881:9;:60::i;74528:186::-;74580:10;74611:95;74620:4;74626:13;:11;:13::i;:::-;74641:9;:7;:9::i;:::-;74652:13;:11;:13::i;:::-;74667:3;:15;;;:17;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74667:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;74667:17:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74667:17:0;74686:19;:17;:19::i;:::-;74611:8;:95::i;73782:133::-;73826:10;73857:50;73867:13;:11;:13::i;:::-;73882:9;:7;:9::i;30017:905::-;30185:15;30173:8;:27;;30165:69;;;;;-1:-1:-1;;;30165:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30430:13;;;;30247:18;30430:13;;;:6;:13;;;;;;;;:15;;;;;;;;;30292:195;;30321:15;30292:195;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;30292:195:0;;;;;30268:230;;;;;;30550:124;;;;;30614:16;30550:124;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;30550:124:0;;;;;;30526:159;;;;;;;;;30715:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30268:230;;30526:159;;30430:15;;30715:24;;;;;30430:13;;-1:-1:-1;30715:24:0;;;;;;;;;;30430:15;30715:24;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;30715:24:0;;;;;;-1:-1:-1;;30772:20:0;;;;;;;:39;;;30806:5;30796:15;;:6;:15;;;30772:39;30750:119;;;;;-1:-1:-1;;;30750:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30882:32;30891:5;30898:7;30907:6;30882:8;:32::i;:::-;30017:905;;;;;;;;;;:::o;48653:274::-;48841:11;48790:4;32830:218;;;;;;;;;;;;;;;;;32951:6;32937:20;;:10;:20;;;:53;;;-1:-1:-1;32961:17:0;;;;;;;:9;:17;;;;;;;;32979:10;32961:29;;;;;;;;;;32937:53;33005:12;32915:113;;;;;-1:-1:-1;;;32915:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;32915:113:0;;48879:40:::1;48888:4;48894:2;48898:9;48909;48879:8;:40::i;19432:151::-:0;19548:18;;;;19521:7;19548:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;19432:151::o;84087:209::-;84142:10;84168:40;84212:21;:19;:21::i;:::-;84165:68;;;84258:30;84271:16;84258:12;:30::i;:::-;-1:-1:-1;84244:44:0;;84087:209;-1:-1:-1;;;84087:209:0:o;33119:99::-;33176:34;33189:10;33201:8;33176:12;:34::i;:::-;33119:99;:::o;90853:146::-;90936:10;90967:24;:22;:24::i;77418:134::-;77501:12;;:25;;;;;;;;;;;;;;;;;;;;;;;;;77470:10;;77501:43;;76942:8;;77501:12;;;;;:18;;:25;;;;;;;;;;;;:12;:25;;;2:2:-1;;;;27:1;24;17:12;2:2;77501:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77501:25:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;77501:25:0;;:43;:29;:43;:::i;60279:98::-;60348:21;;60279:98::o;76383:206::-;76436:10;76462:12;76481:10;;;;;;;;;;;:26;;;:28;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;76481:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;76481:28:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;76481:28:0;;;;-1:-1:-1;76528:32:0;76481:28;75909:8;76528:32;:18;:32;:::i;:::-;76520:40;;76383:206;;:::o;32208:61::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;50448:289::-;50582:11;50619:10;:26;50641:3;50619:26;;50611:56;;;;;-1:-1:-1;;;50611:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;50687:42;50698:4;50704:2;50708:9;50719;50687:10;:42::i;:::-;50678:51;50448:289;-1:-1:-1;;;;;50448:289:0:o;33292:105::-;33352:37;33368:10;33380:8;33352:15;:37::i;47136:57::-;47187:6;47136:57;:::o;7673:136::-;7731:7;7758:43;7762:1;7765;7758:43;;;;;;;;;;;;;;;;;:3;:43::i;61265:270::-;61362:10;;61410:33;:9;61431:11;61410:33;:20;:33;:::i;:::-;61385:58;-1:-1:-1;61463:14:0;;:63;;61484:42;:14;61508:17;61484:42;:23;:42;:::i;:::-;61463:63;;;61480:1;61454:73;61265:270;-1:-1:-1;;;;;61265:270:0:o;64825:2383::-;64953:11;64982:14;64999:43;65008:8;65018:11;65031:10;64999:8;:43::i;:::-;64982:60;-1:-1:-1;65053:12:0;65068:18;:7;65080:5;65068:18;:11;:18;:::i;:::-;65053:33;-1:-1:-1;65101:12:0;65097:2104;;65262:27;:5;65279:9;65262:27;:16;:27;:::i;:::-;65253:36;;65097:2104;;;47041:8;65311:10;:17;65307:1894;;66074:22;66099:81;66170:9;66099:66;66157:7;66100:51;47041:8;66100:42;:27;:7;66157;66100:27;:18;:27;:::i;:::-;:40;:42::i;:51::-;66099:57;:66;:57;:66;:::i;:::-;:70;:81;:70;:81;:::i;:::-;66074:106;;66204:96;66292:7;66204:83;:69;66248:24;:7;:22;:24::i;:::-;66205:30;:17;66227:7;66205:30;:21;:30;:::i;:::-;66204:43;:69;:43;:69;:::i;:::-;:81;:83::i;:96::-;66195:105;;65307:1894;;;;67023:22;67048:51;67071:27;:7;67088:9;67071:27;:16;:27;:::i;:::-;67048:18;:7;67060:5;67048:18;:11;:18;:::i;:51::-;67023:76;-1:-1:-1;67123:66:0;67158:30;:7;67023:76;67158:30;:11;:30;:::i;:::-;67123;:7;67135:17;67123:30;:11;:30;:::i;:66::-;67114:75;;65307:1894;;64825:2383;;;;;;;;;:::o;7209:181::-;7267:7;7299:5;;;7323:6;;;;7315:46;;;;;-1:-1:-1;;;7315:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;58640:1462;59207:17;;;;;:38;;-1:-1:-1;59228:17:0;;;59207:38;59203:892;;;59278:23;:29;;;;;;59262:13;59859:12;;59791:49;59827:12;59791:31;:13;59827:12;59791:17;:31::i;:49::-;:64;;;;;;59790:81;;;;;59886:23;:59;;;;59929:15;59886:59;;;;;;;;59960:54;;59790:81;;;;59960:54;;;;;;;;;;;;;60034:49;;;;;;;;;;;;;;59790:81;;-1:-1:-1;60034:49:0;;;;;;;;;;;59203:892;;;58640:1462;;;:::o;23403:378::-;23487:21;;;23479:65;;;;;-1:-1:-1;;;23479:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;23557:49;23586:1;23590:7;23599:6;23557:20;:49::i;:::-;23634:12;;:24;;23651:6;23634:24;:16;:24;:::i;:::-;23619:12;:39;23690:18;;;:9;:18;;;;;;;;;;;:30;;23713:6;23690:30;:22;:30;:::i;:::-;23669:18;;;:9;:18;;;;;;;;;;;:51;;;;23736:37;;;;;;;23669:18;;:9;;23736:37;;;;;;;;;;23403:378;;:::o;12291:106::-;12379:10;12291:106;:::o;24971:346::-;25073:19;;;25065:68;;;;-1:-1:-1;;;25065:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25152:21;;;25144:68;;;;-1:-1:-1;;;25144:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25225:18;;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;25277:32;;;;;;;;;;;;;;;;;24971:346;;;:::o;34399:238::-;34482:15;;;;;;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;34481:26;34473:67;;;;;-1:-1:-1;;;34473:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;34551:15;;;;;;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;;:32;;;;34579:4;34551:32;;;;;;34599:30;;;;;;;;;;;;;;;;;34399:238;;:::o;51567:368::-;51670:26;;;51691:4;51670:26;;:55;;;51721:3;51700:25;;:9;:25;;;51670:55;:82;;;-1:-1:-1;51729:23:0;;;;51670:82;51666:262;;;51769:72;51778:6;51794;51803;51811:29;51833:6;51811:21;:29::i;:::-;51769:8;:72::i;:::-;;51666:262;;;51874:42;51890:6;51898:9;51909:6;51874:15;:42::i;8112:192::-;8198:7;8234:12;8226:6;;;;8218:29;;;;-1:-1:-1;;;8218:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;8218:29:0;-1:-1:-1;;;8270:5:0;;;8112:192::o;36745:110::-;36804:4;36828:19;36845:1;36829:10;:1;35250:8;36829:10;:5;:10;:::i;37517:318::-;37587:4;;35469:8;37633:22;:5;35520:8;37633:9;:22::i;:::-;:36;;;;;;;-1:-1:-1;37713:8:0;37708:2;37633:36;37684:26;:37;37680:78;;;37745:1;37738:8;;;;;37680:78;37775:52;35581:18;37805:21;37775:6;:52::i;:::-;37768:59;37517:318;-1:-1:-1;;;;37517:318:0:o;35823:105::-;35882:4;35250:8;35906;:1;35912;35906:8;:5;:8;:::i;:::-;:14;;;;;;;35823:105;-1:-1:-1;;;35823:105:0:o;61721:179::-;61820:11;61853:39;:9;61870:11;61883:8;61853:39;:16;:39;:::i;37069:114::-;37124:4;37148:27;37159:5;37171:2;37148:10;:27::i;35936:122::-;35993:4;35250:8;36017:27;35301:7;36018:8;:1;36024;36018:8;:5;:8;:::i;:::-;36017:14;:27;:14;:27;:::i;62466:826::-;62553:10;;;62602:4;:16;;;;;;;;;:56;;62640:18;62602:56;;;62621:16;62602:56;62576:83;;62678:36;62687:11;47041:8;62705;62678;:36::i;:::-;62670:44;;62727:15;62745:19;:17;:19::i;:::-;62727:37;;47041:8;62779:10;:17;62775:510;;62826:8;62818:4;:16;;;;;;;;;:36;;;;;47041:8;62838:10;:16;62818:36;62817:81;;;-1:-1:-1;62868:9:0;62860:4;:17;;;;;;;;;:37;;;;;47041:8;62881:10;:16;62860:37;62813:164;;;62927:34;:5;62940:10;62952:8;62927:34;:12;:34;:::i;:::-;62919:42;;62813:164;62775:510;;;63123:8;63115:4;:16;;;;;;;;;:36;;;;;47041:8;63135:10;:16;63115:36;63114:81;;;-1:-1:-1;63165:9:0;63157:4;:17;;;;;;;;;:37;;;;;47041:8;63178:10;:16;63157:37;63110:164;;;63224:34;:5;63237:10;63249:8;63224:34;:12;:34;:::i;:::-;63216:42;;63110:164;62466:826;;;;;;;:::o;54193:1304::-;54257:11;54315:16;54334:18;:16;:18::i;:::-;54315:37;;54363:17;54383:9;:7;:9::i;:::-;54363:29;-1:-1:-1;54403:14:0;54420:27;54363:29;54437:9;54420:27;:16;:27;:::i;:::-;54403:44;;54535:19;54557:13;:11;:13::i;:::-;54535:35;;54581:17;54601:49;54611:11;54624:9;54635:14;54601:9;:49::i;:::-;54581:69;;54661:19;54683:3;:15;;;:17;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;54683:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;54683:17:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;54683:17:0;;-1:-1:-1;54711:62:0;54733:12;54747:9;54683:17;54711:21;:62::i;:::-;54819:15;54837:19;:17;:19::i;:::-;54819:37;;54876:90;54888:11;54901:9;54912;54923:14;54939;54955:10;54876:11;:90::i;:::-;54867:99;;54995:9;54985:6;:19;;54977:49;;;;;-1:-1:-1;;;54977:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;55114:17;55134:52;55144:11;55157:12;55171:14;55134:9;:52::i;:::-;55114:72;;55197:64;55222:12;55236;55250:10;55197:24;:64::i;:::-;55272:3;:8;;;55281:2;55285:6;55272:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;55272:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55272:20:0;;;;55320:8;;55313:3;:15;;55305:56;;;;;-1:-1:-1;;;55305:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;55393:4;55380:9;:17;;55372:52;;;;;-1:-1:-1;;;55372:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;55456:4;55443:9;:7;:9::i;:::-;:17;;55435:54;;;;;-1:-1:-1;;;55435:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;54193:1304;;;;;;;;;;;;:::o;55505:927::-;55609:11;55671:16;55690:18;:16;:18::i;:::-;55671:37;;55719:14;55736:9;:7;:9::i;:::-;55719:26;;55756:19;55778:13;:11;:13::i;:::-;55756:35;;55802:17;55822:49;55832:11;55845:9;55856:14;55822:9;:49::i;:::-;55802:69;;55891:64;55905:11;55918:9;55929;55940:14;55891:13;:64::i;:::-;55882:73;;55984:9;55974:6;:19;;55966:49;;;;;-1:-1:-1;;;55966:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56122:17;56142:61;56152:11;56165:21;:9;56179:6;56165:21;:13;:21;:::i;:::-;56188:14;56142:9;:61::i;:::-;56122:81;-1:-1:-1;47094:12:0;56222:30;;;56214:59;;;;;-1:-1:-1;;;56214:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56284:3;:8;;;56293:4;56299:9;56284:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56284:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56284:25:0;;;;56320:73;56345:12;56359;56373:19;:17;:19::i;56320:73::-;56404:20;:12;;;56417:6;56404:20;:12;:20;:::i;:::-;55505:927;;;;;;;;;;;:::o;62086:179::-;62185:11;62218:39;:9;62235:11;62248:8;62218:39;:16;:39;:::i;76253:122::-;76314:10;76345:22;:20;:22::i;77289:121::-;77350:10;77381:21;:19;:21::i;83955:124::-;84016:10;84047:24;:22;:24::i;90069:223::-;90140:4;90172:5;;;90198;;;90224;;;90250:8;;;:33;;90272:2;90266:8;;:2;:8;;;:16;;90281:1;90266:16;;;90277:1;90266:16;90250:33;;;-1:-1:-1;90261:1:0;;90242:42;-1:-1:-1;;;;;90069:223:0:o;60496:541::-;60626:10;;;60806:8;:30;;;;;;;;;:70;;60858:18;60806:70;;;60839:16;60806:70;60780:97;;60918:47;60927:11;60940:14;60956:8;60918;:47::i;:::-;60901:9;60897:69;60888:78;;60999:9;60985:6;:24;;60977:52;;;;;-1:-1:-1;;;60977:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;60496:541;;;;;;;:::o;63493:1067::-;63647:10;;;63701:4;:16;;;;;;;;;:56;;63739:18;63701:56;;;63720:16;63701:56;63675:83;-1:-1:-1;63773:19:0;63769:164;;63816:36;63825:11;47041:8;63843;63816;:36::i;:::-;63809:43;;;;;63769:164;63943:10;63956:59;63966:11;63979:9;63990:14;64006:8;63956:9;:59::i;:::-;63943:72;;64045:1;64035:6;:11;;:63;;64053:45;64058:6;64073:14;64089:8;64053:45;:19;:45;:::i;:::-;64035:63;;;64049:1;64035:63;64026:73;-1:-1:-1;64124:8:0;64116:4;:16;;;;;;;;;64112:441;;;47041:8;64153:10;:16;64149:91;;;64198:26;:5;64213:10;64198:26;:14;:26;:::i;:::-;64190:34;;64149:91;64309:9;64321:16;:14;:16::i;:::-;64309:28;;64364:4;64356:5;:12;64352:65;;;64397:4;64389:12;;64352:65;64112:441;;;;47041:8;64453:10;:16;64449:93;;;64498:28;:5;64515:10;64498:28;:16;:28;:::i;:::-;64490:36;;64449:93;63493:1067;;;;;;;;;;;:::o;53246:939::-;53348:11;53410:16;53429:18;:16;:18::i;:::-;53410:37;;53458:14;53475:9;:7;:9::i;:::-;53458:26;;53495:19;53517:13;:11;:13::i;:::-;53495:35;;53541:17;53561:49;53571:11;53584:9;53595:14;53561:9;:49::i;:::-;53541:69;;53630:76;53642:11;53655:9;53666;53677:14;53693:12;53630:11;:76::i;:::-;53621:85;;53735:9;53725:6;:19;;53717:49;;;;;-1:-1:-1;;;53717:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;53873:17;53893:76;53903:11;53916:21;:9;53930:6;53916:21;:13;:21;:::i;:::-;53939:29;:14;53958:9;53939:29;:18;:29;:::i;53893:76::-;53873:96;;47041:8;53988:12;:19;;53980:49;;;;;-1:-1:-1;;;53980:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;54040:22;54046:4;54052:9;54040:5;:22::i;:::-;54073:73;54098:12;54112;54126:19;:17;:19::i;86202:332::-;86429:12;:22;86404:12;:22;86265:40;;;;86429:22;;;;86404;;:47;:122;;86499:12;86513;86404:122;;;86468:12;86482;86404:122;86365:161;;;;-1:-1:-1;86202:332:0;-1:-1:-1;86202:332:0:o;84304:532::-;84400:10;84412:14;84428:17;84491;:15;:17::i;:::-;84463:45;;-1:-1:-1;84463:45:0;-1:-1:-1;84630:32:0;84665:51;84463:45;84699:16;84665:22;:51::i;:::-;84779:18;;;;-1:-1:-1;84735:93:0;;84749:9;;84760:12;;84779:18;;;;84805:21;;;;;84735:13;:93::i;:::-;84727:101;;84304:532;;;;;;:::o;89490:471::-;89583:10;89614:288;89621:29;:27;:29::i;:::-;89740:32;:30;:32::i;:::-;89860:41;:39;:41::i;8563:471::-;8621:7;8866:6;8862:47;;-1:-1:-1;8896:1:0;8889:8;;8862:47;8933:5;;;8937:1;8933;:5;:1;8957:5;;;;;:10;8949:56;;;;-1:-1:-1;;;8949:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34712:244;34797:15;;;;;;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;34789:68;;;;;-1:-1:-1;;;34789:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;34868:15;;;;34896:5;34868:15;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;:33;;;;;;34917:31;;;;;;;;;;;;;;;;34712:244;;:::o;36863:198::-;36920:4;36944:32;36974:1;36945:23;36962:5;;;36946:10;:1;35250:8;36946:10;:5;:10;:::i;36303:116::-;36356:4;35351:9;36380:17;36395:1;36381:8;36395:1;;36381:8;:5;:8;:::i;36380:17::-;:31;;;;;;;36303:116;-1:-1:-1;;36303:116:0:o;9510:132::-;9568:7;9595:39;9599:1;9602;9595:39;;;;;;;;;;;;;;;;;:3;:39::i;36066:103::-;36121:4;35250:8;36146;36152:1;;36146:8;:5;:8;:::i;38932:472::-;38984:9;39010:5;;39006:302;;39033:12;39065:1;39048:14;:1;35638:7;39048:14;:5;:14;:::i;:::-;:18;;;;;;;-1:-1:-1;39081:21:0;39105:18;:1;35351:9;39105:18;:5;:18;:::i;:::-;39081:42;;39138:159;39167:7;39160:14;;39256:1;39246:4;39239;:11;39219:16;:32;;;;;;39211:4;39204;:11;:48;39203:54;;;;;;39193:64;;39291:4;39281:7;:14;39138:159;;39006:302;;38932:472;;;:::o;42581:249::-;42642:14;42695:12;42685:22;;42722:13;;;;;:36;;;42750:8;42739;:19;42722:36;42718:105;;;42803:8;42787:7;42797:3;42787:13;:24;;;;22583:539;22689:20;;;22681:70;;;;-1:-1:-1;;;22681:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22770:23;;;22762:71;;;;-1:-1:-1;;;22762:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22846:47;22867:6;22875:9;22886:6;22846:20;:47::i;:::-;22926:71;22948:6;22926:71;;;;;;;;;;;;;;;;;:17;;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;22906:17;;;;:9;:17;;;;;;;;;;;:91;;;;23031:20;;;;;;;:32;;23056:6;23031:32;:24;:32;:::i;:::-;23008:20;;;;:9;:20;;;;;;;;;;;;:55;;;;23079:35;;;;;;;23008:20;;23079:35;;;;;;;;;;;;;22583:539;;;:::o;38527:282::-;38582:6;38609:1;38605;:5;:20;;35250:8;38605:20;;;38618:1;38605:20;38601:24;-1:-1:-1;38648:1:0;38643:6;;;;38638:164;38651:6;;38638:164;;38686:17;38701:1;38686:14;:17::i;:::-;38682:21;-1:-1:-1;38728:1:0;38724;:5;:10;38720:71;;38759:16;38770:1;38773;38759:10;:16::i;:::-;38755:20;;38720:71;38664:1;38659:6;;;;38638:164;;35654:161;35725:4;;35749:8;:22;;;;;;;;;:58;;35793:14;35802:1;35805;35793:8;:14::i;:::-;35749:58;;;35774:16;35785:1;35788;35774:10;:16::i;36576:161::-;36647:4;;36671:8;:22;;;;;;;;;:58;;36715:14;36724:1;36727;36715:8;:14::i;36671:58::-;36696:16;36707:1;36710;36696:10;:16::i;57370:981::-;57491:20;:26;;;;;;47094:12;57532:28;;57528:816;;57667:13;;57663:217;;57734:1;57701:20;57776:30;;;57830:34;;;;;;;;;;;;;;;;;;;;;;;;;57663:217;57528:816;;;57901:13;57897:447;;58077:20;:56;;;;58117:15;58077:56;;;;;58185:67;;58237:14;;58185:42;;58217:9;;47094:7;:12;47041:8;58186:20;;58185:42;:31;:42;:::i;:::-;:51;:67;:51;:67;:::i;:::-;58148:20;:105;;;;;;;;;;;;;;;;;;;58273:59;;;;;;58305:26;;;;;;;58273:59;;;;;;;;;;;;;;;;57897:447;57370:981;;;;:::o;68650:670::-;68792:11;68871:14;68888:70;68897:8;68907:11;68920:7;68929;68938;68947:10;68888:8;:70::i;:::-;68871:87;-1:-1:-1;68973:12:0;68969:344;;69071:27;:5;69088:9;69071:27;:16;:27;:::i;:::-;69062:36;;68969:344;;;69193:12;69208:18;:7;69220:5;69208:18;:11;:18;:::i;:::-;69193:33;-1:-1:-1;69250:51:0;69273:27;69193:33;69290:9;69273:27;:16;:27;:::i;68969:344::-;68650:670;;;;;;;;;:::o;69589:701::-;69702:11;69781:12;69796:3;:15;;;:17;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;69796:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;69796:17:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;69796:17:0;;-1:-1:-1;69824:14:0;69841:80;69850:9;69861:11;69874:7;69883;69796:17;69901:19;:17;:19::i;69841:80::-;69824:97;-1:-1:-1;69936:12:0;69932:351;;70034:27;:5;70051:9;70034:27;:16;:27;:::i;:::-;70025:36;;69932:351;;;70187:84;70232:38;70244:25;:5;70259:9;70244:25;:14;:25;:::i;:::-;70232:7;;:38;:11;:38;:::i;:::-;70187:40;70199:27;:5;70216:9;70199:27;:16;:27;:::i;:::-;70187:7;;:40;:11;:40;:::i;69932:351::-;69589:701;;;;;;;;:::o;2364:397::-;2479:6;2454:21;:31;;2446:73;;;;;-1:-1:-1;;;2446:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;2629:35;;2611:12;;2629:14;;;;2652:6;;2611:12;2629:35;2611:12;2629:35;2652:6;2629:14;:35;;;;;;;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;;2610:54:0;;;2683:7;2675:78;;;;-1:-1:-1;;;2675:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67477:908;67605:11;67713:14;67730:44;67739:9;67750:11;67763:10;67730:8;:44::i;:::-;67713:61;-1:-1:-1;67785:12:0;67800:18;:7;67812:5;67800:18;:11;:18;:::i;:::-;67785:33;-1:-1:-1;68155:22:0;68180:89;68221:47;68229:38;:25;67785:33;68246:7;68229:25;:16;:25;:::i;:::-;:36;:38::i;:::-;47041:8;;68221:47;:7;:47;:::i;:::-;68180:29;:9;68201:7;68180:29;:20;:29;:::i;:89::-;68155:114;-1:-1:-1;68289:88:0;68301:75;:63;68333:30;:7;68155:114;68333:30;:11;:30;:::i;:::-;68301:22;:7;:20;:22::i;:::-;:31;:63;:31;:63;:::i;:::-;:73;:75::i;:::-;68289:7;;:88;:11;:88;:::i;24113:418::-;24197:21;;;24189:67;;;;-1:-1:-1;;;24189:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24269:49;24290:7;24307:1;24311:6;24269:20;:49::i;:::-;24352:68;24375:6;24352:68;;;;;;;;;;;;;;;;;:18;;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;24331:18;;;:9;:18;;;;;;;;;;:89;24446:12;;:24;;24463:6;24446:24;:16;:24;:::i;:::-;24431:12;:39;24486:37;;;;;;;;24512:1;;24486:37;;;;;;;;;;;;;24113:418;;:::o;87341:620::-;87399:14;87415:17;87468:11;:23;;;:25;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87468:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87468:25:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87468:25:0;;;87450:43;;;-1:-1:-1;87719:20:0;87742;:120;;87828:11;:32;;;:34;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87828:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87828:34:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87828:34:0;87742:120;;;87778:11;:32;;;:34;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87778:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87778:34:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87778:34:0;87742:120;87719:143;-1:-1:-1;81407:8:0;87888:32;87719:143;87908:11;87888:32;:19;:32;:::i;:::-;:65;;;;;;87873:80;;87341:620;;;:::o;85355:839::-;85480:32;85530:16;85549:62;85584:12;85598;85549:34;:62::i;:::-;85530:81;;85622:16;85641:62;85676:12;85690;85641:34;:62::i;:::-;85622:81;;85718:11;85714:473;;;85750:11;85746:246;;;85793:16;85782:27;;85746:246;;;85929:12;85918:23;;85746:246;85714:473;;;86013:11;86009:178;;;86052:12;86041:23;;86009:178;;;86136:39;;;-1:-1:-1;;;86136:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;86009:178;85355:839;;;;;;:::o;88231:254::-;88367:10;88403:74;88446:30;:12;88463;88446:30;:16;:30;:::i;:::-;88404:36;:15;88424;88404:36;:19;:36;:::i;83342:605::-;83403:10;83427:40;83469;83513:21;:19;:21::i;:::-;83426:108;;;;83547:14;83572:17;83635:30;83648:16;83635:12;:30::i;:::-;83600:65;;-1:-1:-1;83600:65:0;-1:-1:-1;83600:65:0;-1:-1:-1;83785:63:0;83600:65;83831:16;83785:34;:63::i;:::-;83781:159;;;83865:63;83886:9;83897:12;83911:16;83865:20;:63::i;:::-;83342:605;;;;;:::o;10138:278::-;10224:7;10259:12;10252:5;10244:28;;;;-1:-1:-1;;;10244:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;10244:28:0;;10283:9;10299:1;10295;:5;;;;;;;10138:278;-1:-1:-1;;;;;10138:278:0:o;36427:141::-;36478:4;35351:9;36502:44;35411:15;36503:17;36518:1;36504:8;36518:1;;36504:8;:5;:8;:::i;36177:118::-;36230:4;35250:8;36254:27;35301:7;36255:8;36261:1;;36255:8;:5;:8;:::i;39412:537::-;39462:9;39491:14;39503:1;39491:11;:14::i;:::-;39484:21;-1:-1:-1;39780:11:0;;;:18;;35351:9;39802:15;;39780:37;39776:77;;39835:6;;39412:537;;;:::o;86542:277::-;86734:21;;;81234:9;86734:39;-1:-1:-1;86718:55:0;;86542:277::o;84844:503::-;81459:11;84984:9;:23;;84976:54;;;;;-1:-1:-1;;;84976:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;81588:12;85049;:27;;85041:61;;;;;-1:-1:-1;;;85041:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;85235:104;;;;;;;;;;;;;;;;;;;;;;;84844:503::o
Swarm Source
ipfs://fd245a8c7efcaae4a65f2731cc7c0b6ef0618a52b60ff0bd544639bc84dba515
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.