More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 146 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Fill Limit Order... | 55204564 | 13 days ago | IN | 0 AVAX | 0.00137448 | ||||
Fill Limit Order... | 55147741 | 15 days ago | IN | 0 AVAX | 0.00044954 | ||||
Fill Limit Order... | 55139103 | 15 days ago | IN | 0 AVAX | 0.00074813 | ||||
Fill Limit Order... | 55096219 | 16 days ago | IN | 0 AVAX | 0.00316355 | ||||
Fill Limit Order... | 54965027 | 19 days ago | IN | 0 AVAX | 0.00125769 | ||||
Fill Limit Order... | 54687892 | 25 days ago | IN | 0 AVAX | 0.00038436 | ||||
Fill Limit Order... | 54677799 | 25 days ago | IN | 0 AVAX | 0.00047335 | ||||
Fill Limit Order... | 54677621 | 25 days ago | IN | 0 AVAX | 0.0015567 | ||||
Fill Limit Order... | 54677411 | 25 days ago | IN | 0 AVAX | 0.00086656 | ||||
Fill Limit Order... | 54618199 | 26 days ago | IN | 0 AVAX | 0.06220216 | ||||
Fill Limit Order... | 54614873 | 26 days ago | IN | 0 AVAX | 0.00717692 | ||||
Fill Limit Order... | 54614873 | 26 days ago | IN | 0 AVAX | 0.00820861 | ||||
Fill Limit Order... | 54614872 | 26 days ago | IN | 0 AVAX | 0.00772334 | ||||
Fill Limit Order... | 54613298 | 26 days ago | IN | 0 AVAX | 0.00028171 | ||||
Fill Limit Order... | 54582909 | 27 days ago | IN | 0 AVAX | 0.01756081 | ||||
Fill Limit Order... | 54578187 | 27 days ago | IN | 0 AVAX | 0.13189552 | ||||
Fill Limit Order... | 54569901 | 27 days ago | IN | 0 AVAX | 0.0012293 | ||||
Fill Limit Order... | 54539303 | 28 days ago | IN | 0 AVAX | 0.02054429 | ||||
Fill Limit Order... | 54479922 | 29 days ago | IN | 0 AVAX | 0.00130886 | ||||
Fill Limit Order... | 54383284 | 31 days ago | IN | 0 AVAX | 0.00695902 | ||||
Fill Limit Order... | 54364078 | 31 days ago | IN | 0 AVAX | 0.00936082 | ||||
Fill Limit Order... | 54309325 | 33 days ago | IN | 0 AVAX | 0.00899484 | ||||
Fill Limit Order... | 54261026 | 34 days ago | IN | 0 AVAX | 0.01770589 | ||||
Fill Limit Order... | 54260957 | 34 days ago | IN | 0 AVAX | 0.00781632 | ||||
Fill Limit Order... | 54178454 | 36 days ago | IN | 0 AVAX | 0.02094596 |
Loading...
Loading
Contract Name:
OdosLimitOrderRouter
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity)
/** *Submitted for verification at snowscan.xyz on 2024-08-30 */ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool); } // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/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.8.0/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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) /** * @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 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) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // 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 (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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) { return a + b; } /** * @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 a - b; } /** * @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) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting 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 a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting 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) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * 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) { unchecked { require(b > 0, errorMessage); return a % b; } } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } } // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(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"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) /** * @dev Contract module which provides 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} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } } // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` 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: * * - `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]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current 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); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } } // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); } // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _name.toStringWithFallback(_nameFallback), _version.toStringWithFallback(_versionFallback), block.chainid, address(this), bytes32(0), new uint256[](0) ); } } // From https://github.com/AmbireTech/signature-validator/blob/main/contracts/EIP6492.sol // with minimal modifications // From https://eips.ethereum.org/EIPS/eip-6492 // you can use `ValidateSigOffchain` for this library in exactly the same way that the other contract (DeploylessUniversalSigValidator.sol) is used // As per ERC-1271 interface IERC1271Wallet { function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue); } error ERC1271Revert(bytes error); error ERC6492DeployFailed(bytes error); error InvalidSignatureLength(); error InvalidSignatureVValue(); contract UniversalSigValidator { bytes32 private constant ERC6492_DETECTION_SUFFIX = 0x6492649264926492649264926492649264926492649264926492649264926492; bytes4 private constant ERC1271_SUCCESS = 0x1626ba7e; function isValidSigImpl( address _signer, bytes32 _hash, bytes calldata _signature, bool allowSideEffects ) public returns (bool) { uint256 contractCodeLen = address(_signer).code.length; bytes memory sigToValidate; // The order here is strictly defined in https://eips.ethereum.org/EIPS/eip-6492 // - ERC-6492 suffix check and verification first, while being permissive in case the contract is already deployed; if the contract is deployed we will check the sig against the deployed version, this allows 6492 signatures to still be validated while taking into account potential key rotation // - ERC-1271 verification if there's contract code // - finally, ecrecover bool isCounterfactual = _signature.length >= 32 && bytes32(_signature[_signature.length-32:_signature.length]) == ERC6492_DETECTION_SUFFIX; if (isCounterfactual) { address create2Factory; bytes memory factoryCalldata; (create2Factory, factoryCalldata, sigToValidate) = abi.decode(_signature[0:_signature.length-32], (address, bytes, bytes)); if (contractCodeLen == 0) { // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory err) = create2Factory.call(factoryCalldata); if (!success) revert ERC6492DeployFailed(err); } } else { sigToValidate = _signature; } // Try ERC-1271 verification if (isCounterfactual || contractCodeLen > 0) { try IERC1271Wallet(_signer).isValidSignature(_hash, sigToValidate) returns (bytes4 magicValue) { bool isValid = magicValue == ERC1271_SUCCESS; if (contractCodeLen == 0 && isCounterfactual && !allowSideEffects) { // if the call had side effects we need to return the // result using a `revert` (to undo the state changes) assembly { mstore(0, isValid) revert(31, 1) } } return isValid; } catch (bytes memory err) { revert ERC1271Revert(err); } } // ecrecover verification if (_signature.length != 65) { revert InvalidSignatureLength(); } bytes32 r = bytes32(_signature[0:32]); bytes32 s = bytes32(_signature[32:64]); uint8 v = uint8(_signature[64]); if (v != 27 && v != 28) { revert InvalidSignatureVValue(); } return ECDSA.recover(_hash, v, r, s) == _signer; } function isValidSigWithSideEffects(address _signer, bytes32 _hash, bytes calldata _signature) external returns (bool) { return this.isValidSigImpl(_signer, _hash, _signature, true); } function isValidSig(address _signer, bytes32 _hash, bytes calldata _signature) public returns (bool) { try this.isValidSigImpl(_signer, _hash, _signature, false) returns (bool isValid) { return isValid; } catch (bytes memory error) { // in order to avoid side effects from the contract getting deployed, the entire call will revert with a single byte result uint256 len = error.length; if (len == 1) return error[0] == 0x01; // all other errors are simply forwarded, but in custom formats so that nothing else can revert with a single byte in the call else assembly { revert(add(error, 0x20), len) } } } } // this is a helper so we can perform validation in a single eth_call without pre-deploying a singleton contract ValidateSigOffchain { constructor (address _signer, bytes32 _hash, bytes memory _signature) { UniversalSigValidator validator = new UniversalSigValidator(); bool isValidSig = validator.isValidSigWithSideEffects(_signer, _hash, _signature); assembly { mstore(0, isValidSig) return(31, 1) } } } error InvalidEip1271Signature(bytes32 orderHash, address account, bytes signature); error OrderNotPresigned(bytes32 orderHash, address account); error InvalidPresignLength(uint256 expectedLength, uint256 actualLength); /// @notice Limit order signature validator contract SignatureValidator is UniversalSigValidator { /// @dev Storage for keeping pre-signed orders mapping(address account => mapping(bytes32 orderHash => bool preSigned)) public preSignedOrders; /// @dev Keeps the signature and the signature validation method struct Signature { /// Depending on the validationMethod value, the signature format is: /// EIP712 - 65 bytes signature represented as abi.encodePacked(r, s, v) /// EIP1271 - the first 20 bytes contain the order owner address and the remaining part contains the signature /// PreSign - 20 bytes which contain the order owner address bytes signature; SignatureValidationMethod validationMethod; } /// @dev Order signature validation methods /// EIP712 /// EIP1271 /// PreSign - The order hash expected to be added via the setPreSignature() function prior to execution enum SignatureValidationMethod { EIP712, EIP1271, PreSign } /// @dev Event for setting pre-signature for an order hash event OrderPreSigned( bytes32 indexed orderHash, address indexed account, bool preSigned ); /// @dev Validates the signature and decodes the order owner address /// @param orderHash Order hash /// @param encodedSignature order signature or account address or account address and order signature, depending on the validationMethod value /// @return account Order owner address function _getOrderOwnerOrRevert( bytes32 orderHash, bytes calldata encodedSignature, SignatureValidationMethod validationMethod ) internal returns (address account) { if (validationMethod == SignatureValidationMethod.EIP712) { account = ECDSA.recover(orderHash, encodedSignature); } else if (validationMethod == SignatureValidationMethod.EIP1271) { assembly { // account = address(encodedSignature[0:20]) account := shr(96, calldataload(encodedSignature.offset)) } // the first 20 bytes of the encodedSignature contain the account address, // and the remaining part of the bytes array contains the signature. bytes calldata signature = encodedSignature[20:]; if (!isValidSig(account, orderHash, signature)) { revert InvalidEip1271Signature(orderHash, account, signature); } } else { // validationMethod == SignatureValidationMethod.PreSign if (encodedSignature.length != 20) { revert InvalidPresignLength(20, encodedSignature.length); } assembly { // account = address(encodedSignature[0:20]) account := shr(96, calldataload(encodedSignature.offset)) } if (!preSignedOrders[account][orderHash]) { revert OrderNotPresigned(orderHash, account); } } } /// @notice Sets a pre-signature for the specified order hash /// @param orderHash EIP712 encoded order hash of single or multi input limit order /// @param preSigned True to set the order as enabled for filling with pre-sign, false to unset it function setPreSignature( bytes32 orderHash, bool preSigned ) external { preSignedOrders[msg.sender][orderHash] = preSigned; emit OrderPreSigned(orderHash, msg.sender, preSigned); } } /// @title Odos executor interface interface IOdosExecutor { function executePath ( bytes calldata bytecode, uint256[] memory inputAmount, address msgSender ) external payable; } /// @title Odos router v2 interface interface IOdosRouterV2 { /// @dev Holds all information for a given referral // solhint-disable-next-line contract-name-camelcase struct referralInfo { uint64 referralFee; address beneficiary; bool registered; } function referralLookup( uint32 referralCode ) external view returns ( referralInfo memory ri ); function registerReferralCode( uint32 _referralCode, uint64 _referralFee, address _beneficiary ) external; } interface IEIP712 { function DOMAIN_SEPARATOR() external view returns (bytes32); } // From https://github.com/Uniswap/permit2 /// @title SignatureTransfer /// @notice Handles ERC20 token transfers through signature based actions /// @dev Requires user's token approval on the Permit2 contract interface ISignatureTransfer is IEIP712 { /// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount /// @param maxAmount The maximum amount a spender can request to transfer error InvalidAmount(uint256 maxAmount); /// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred /// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred error LengthMismatch(); /// @notice Emits an event when the owner successfully invalidates an unordered nonce. event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask); /// @notice The token and amount details for a transfer signed in the permit transfer signature struct TokenPermissions { // ERC20 token address address token; // the maximum amount that can be spent uint256 amount; } /// @notice The signed permit message for a single token transfer struct PermitTransferFrom { TokenPermissions permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice Specifies the recipient address and amount for batched transfers. /// @dev Recipients and amounts correspond to the index of the signed token permissions array. /// @dev Reverts if the requested amount is greater than the permitted signed amount. struct SignatureTransferDetails { // recipient address address to; // spender requested amount uint256 requestedAmount; } /// @notice Used to reconstruct the signed permit message for multiple token transfers /// @dev Do not need to pass in spender address as it is required that it is msg.sender /// @dev Note that a user still signs over a spender address struct PermitBatchTransferFrom { // the tokens and corresponding amounts permitted for a transfer TokenPermissions[] permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce /// @dev It returns a uint256 bitmap /// @dev The index, or wordPosition is capped at type(uint248).max function nonceBitmap(address, uint256) external view returns (uint256); /// @notice Transfers a token using a signed permit message /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param signature The signature to verify function permitTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes calldata signature ) external; /// @notice Transfers a token using a signed permit message /// @notice Includes extra data provided by the caller to verify signature over /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param signature The signature to verify function permitTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @notice Includes extra data provided by the caller to verify signature over /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Invalidates the bits specified in mask for the bitmap at the word position /// @dev The wordPos is maxed at type(uint248).max /// @param wordPos A number to index the nonceBitmap at /// @param mask A bitmap masked against msg.sender's current bitmap at the word position function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external; } /// @dev Registration interface for Mode SFS contract IModeRegister { function register(address _recipient) public returns (uint256 tokenId) {} } using SafeERC20 for IERC20; error AddressNotAllowed(address account); error OrderExpired(uint256 orderExpiry, uint256 currentTimestamp); error CurrentAmountMismatch(address tokenAddress, uint256 orderAmount, uint256 filledAmount, uint256 currentAmount); error SlippageLimitExceeded(address tokenAddress, uint256 expectedAmount, uint256 actualAmount); error ArbitrageNotAllowed(address tokenAddress); error TransferFailed(address destination, uint256 amount); error OrderCancelled(bytes32 orderHash); error InvalidArguments(); error MinSurplusCheckFailed(address tokenAddress, uint256 expectedValue, uint256 actualValue); error InvalidAddress(address _address); error FunctionIsDisabled(); /// @title Routing contract for Odos Limit Orders with single and multi input and output tokens contract OdosLimitOrderRouter is EIP712, Ownable2Step, SignatureValidator { /// @dev SCALE is required for fractional proportion calculation uint256 private constant SCALE = 1e18; /// @dev The zero address is used to represent ETH due to its gas efficiency address private constant _ETH = address(0); /// @dev Constants for managing referrals and fees uint256 private constant REFERRAL_WITH_FEE_THRESHOLD = 1 << 31; uint256 private constant FEE_DENOM = 1e18; /// @dev OdosRouterV2 address address immutable private ODOS_ROUTER_V2; /// @dev Address which allowed to call `swapRouterFunds()` besides the owner address public liquidatorAddress; /// @dev Event emitted on successful single input limit order execution event LimitOrderFilled( bytes32 indexed orderHash, address indexed orderOwner, address inputToken, address outputToken, uint256 orderInputAmount, uint256 orderOutputAmount, uint256 filledInputAmount, // filled by this execution uint256 filledOutputAmount, // filled by this execution uint256 surplus, uint32 referralCode, uint256 orderType ); /// @dev Event emitted on successful multi input limit order execution event MultiLimitOrderFilled( bytes32 indexed orderHash, address indexed orderOwner, address[] inputTokens, address[] outputTokens, uint256[] orderInputAmounts, uint256[] orderOutputAmounts, uint256[] filledInputAmounts, // filled by this execution uint256[] filledOutputAmounts, // filled by this execution uint256[] surplus, uint32 referralCode, uint256 orderType ); /// @dev Event emitted on single input limit order cancellation event LimitOrderCancelled( bytes32 indexed orderHash, address indexed orderOwner ); /// @dev Event emitted on multi input limit order cancellation event MultiLimitOrderCancelled( bytes32 indexed orderHash, address indexed orderOwner ); /// @dev Event emitted on adding allowed order filler event AllowedFillerAdded(address indexed account); /// @dev Event emitted on removing allowed order filler event AllowedFillerRemoved(address indexed account); /// @dev Event emitted on changing the liquidator address event LiquidatorAddressChanged(address indexed account); /// @dev Event emitted on swapping internal router funds event SwapRouterFunds( address sender, address[] inputTokens, uint256[] inputAmounts, address[] inputReceivers, address outputToken, uint256 outputAmount, address outputReceiver, uint256 amountOut ); /// @dev Token address and amount struct TokenInfo { address tokenAddress; uint256 tokenAmount; } /// @dev Single input and output limit order structure struct LimitOrder { TokenInfo input; TokenInfo output; uint256 expiry; uint256 salt; uint32 referralCode; bool partiallyFillable; } /// @dev Multiple inputs and outputs limit order structure struct MultiLimitOrder { TokenInfo[] inputs; TokenInfo[] outputs; uint256 expiry; uint256 salt; uint32 referralCode; bool partiallyFillable; } /// @dev The execution context provided by the filler for single token limit order struct LimitOrderContext { bytes pathDefinition; address odosExecutor; uint256 currentAmount; address inputReceiver; uint256 minSurplus; uint256 orderType; } /// @dev The execution context provided by the filler for multi token limit order struct MultiLimitOrderContext { bytes pathDefinition; address odosExecutor; uint256[] currentAmounts; address[] inputReceivers; uint256[] minSurplus; uint256 orderType; } /// @dev A helper which is used for avoiding "Stack too deep" error with single input order struct LimitOrderHelper { uint256 balanceBefore; uint256 amountOut; uint256 surplus; uint256 proratedAmount; } /// @dev A helper which is used for avoiding "Stack too deep" error with multi input order struct MultiLimitOrderHelper { address[] inputTokens; address[] outputTokens; uint256[] orderInputAmounts; uint256[] orderOutputAmounts; uint256[] filledAmounts; uint256[] filledOutputAmounts; uint256[] surplus; uint256[] balancesBefore; address orderOwner; bytes32 orderHash; uint256 amountProration; } /// @dev Contains information required for Permit2 token transfer struct Permit2Info { address contractAddress; // Permit2 contract address uint256 nonce; uint256 deadline; address orderOwner; bytes signature; } /// @dev Holds all information for a given referral struct ReferralInfo { uint64 referralFee; address beneficiary; bool registered; } /// @dev Single token limit order storage mapping(address orderOwner => mapping(bytes32 orderHash => uint256 filledAmount)) public limitOrders; /// @dev Multi token limit order storage mapping(address orderOwner => mapping(bytes32 orderHash => uint256[] filledAmounts)) public multiLimitOrders; /// @dev Allowed order fillers mapping(address => bool) public allowedFillers; /// @dev Type strings for EIP-712 signing bytes internal constant TOKEN_PERMISSIONS_TYPE_STRING = "TokenPermissions(address token,uint256 amount)"; bytes internal constant TOKEN_INFO_TYPE_STRING = "TokenInfo(address tokenAddress,uint256 tokenAmount)"; bytes internal constant LIMIT_ORDER_TYPE_STRING = "LimitOrder(" "TokenInfo input," "TokenInfo output," "uint256 expiry," "uint256 salt," "uint32 referralCode," "bool partiallyFillable" ")"; bytes internal constant MULTI_LIMIT_ORDER_TYPE_STRING = "MultiLimitOrder(" "TokenInfo[] inputs," "TokenInfo[] outputs," "uint256 expiry," "uint256 salt," "uint32 referralCode," "bool partiallyFillable" ")"; string public constant LIMIT_ORDER_WITNESS_TYPE_STRING = string(abi.encodePacked( "LimitOrder witness)", LIMIT_ORDER_TYPE_STRING, TOKEN_INFO_TYPE_STRING, TOKEN_PERMISSIONS_TYPE_STRING )); string public constant MULTI_LIMIT_ORDER_WITNESS_TYPE_STRING = string(abi.encodePacked( "MultiLimitOrder witness)", MULTI_LIMIT_ORDER_TYPE_STRING, TOKEN_INFO_TYPE_STRING, TOKEN_PERMISSIONS_TYPE_STRING )); /// @dev Type hashes for EIP-712 signing bytes32 public constant TOKEN_INFO_TYPEHASH = keccak256(TOKEN_INFO_TYPE_STRING); bytes32 public constant LIMIT_ORDER_TYPEHASH = keccak256(abi.encodePacked( LIMIT_ORDER_TYPE_STRING, TOKEN_INFO_TYPE_STRING )); bytes32 public constant MULTI_LIMIT_ORDER_TYPEHASH = keccak256(abi.encodePacked( MULTI_LIMIT_ORDER_TYPE_STRING, TOKEN_INFO_TYPE_STRING )); /// @param _odosRouterV2 OdosRouterV2 address constructor(address _odosRouterV2) EIP712("OdosLimitOrderRouter", "1") { if (_odosRouterV2 == address(0)) { revert InvalidAddress(_odosRouterV2); } ODOS_ROUTER_V2 = _odosRouterV2; changeLiquidatorAddress(msg.sender); } /// @notice Tries to execute a single input limit order, expects the input token to be approved via the ERC20 interface /// @param order Single input limit order struct /// @param signature Order signature and signature validation method /// @param context Execution context /// @return orderHash Order hash function fillLimitOrder( LimitOrder calldata order, Signature calldata signature, LimitOrderContext calldata context ) external returns (bytes32 orderHash) { // 1-3 Checks _limitOrderChecks(order); // 4. Get order hash orderHash = getLimitOrderHash(order); // 5. Recover the orderOwner and validate signature address orderOwner = _getOrderOwnerOrRevert(orderHash, signature.signature, signature.validationMethod); // 6,7 Try get order filled amount uint256 filledAmount = _getFilledAmount(order, context, orderHash, orderOwner); // 8. Transfer tokens from order owner IERC20(order.input.tokenAddress).safeTransferFrom(orderOwner, context.inputReceiver, context.currentAmount); // 9-17 Fill order _limitOrderFill(order, context, orderHash, orderOwner, filledAmount); } /// @notice Tries to execute a single input limit order, expects the input token to be approved via the Permit2 interface /// @param order Single input limit order struct /// @param context Execution context /// @param permit2 Permit2 struct /// @return orderHash Order hash function fillLimitOrderPermit2( LimitOrder calldata order, LimitOrderContext calldata context, Permit2Info calldata permit2 ) external returns (bytes32 orderHash) { // 1-3 Checks _limitOrderChecks(order); // 4. Get order hash bytes32 orderStructHash = getLimitOrderStructHash(order); orderHash = _hashTypedDataV4(orderStructHash); // 5. No need to recover address as it is set in Permit2Info // 6,7 Try get order filled amount uint256 filledAmount = _getFilledAmount(order, context, orderHash, permit2.orderOwner); // 8. Transfer tokens from order owner ISignatureTransfer(permit2.contractAddress).permitWitnessTransferFrom( ISignatureTransfer.PermitTransferFrom( ISignatureTransfer.TokenPermissions( order.input.tokenAddress, context.currentAmount ), permit2.nonce, permit2.deadline ), ISignatureTransfer.SignatureTransferDetails( context.inputReceiver, context.currentAmount ), permit2.orderOwner, orderStructHash, LIMIT_ORDER_WITNESS_TYPE_STRING, permit2.signature ); // 9-17 Fill order _limitOrderFill(order, context, orderHash, permit2.orderOwner, filledAmount); } /// @notice Tries to execute a multi input limit order, expects the input tokens to be approved via the ERC20 interface /// @param order Multi input limit order struct /// @param signature Signature and signature validation method /// @param context Execution context /// @return orderHash Order hash function fillMultiLimitOrder( MultiLimitOrder calldata order, Signature calldata signature, MultiLimitOrderContext calldata context ) external returns (bytes32 orderHash) { // 1-3 Checks _multiOrderChecks(order); // 4. Get order hash orderHash = getMultiLimitOrderHash(order); // 5. Recover the orderOwner and validate signature address orderOwner = _getOrderOwnerOrRevert(orderHash, signature.signature, signature.validationMethod); // 6,7 Try get order filled amount MultiLimitOrderHelper memory helper = _getMultiFilledAmount(order, context, orderHash, orderOwner); // 8. Transfer tokens from order owner to the receiver for (uint256 i = 0; i < order.inputs.length; i++) { IERC20(order.inputs[i].tokenAddress).safeTransferFrom(orderOwner, context.inputReceivers[i], context.currentAmounts[i]); // update filled amount helper.filledAmounts[i] += context.currentAmounts[i]; helper.inputTokens[i] = order.inputs[i].tokenAddress; helper.orderInputAmounts[i] = order.inputs[i].tokenAmount; } _multiLimitOrderFill(order, context, helper); } /// @notice Tries to execute a multi input limit order, expects the input tokens to be approved via the Permit2 interface /// @param order Single input limit order struct /// @param context Execution context /// @param permit2 Permit2 struct /// @return orderHash Order hash function fillMultiLimitOrderPermit2( MultiLimitOrder calldata order, MultiLimitOrderContext calldata context, Permit2Info calldata permit2 ) external returns (bytes32 orderHash) { // 1-3 Checks _multiOrderChecks(order); // 4. Get order hash bytes32 orderStructHash = getMultiLimitOrderStructHash(order); orderHash = _hashTypedDataV4(orderStructHash); // 5. No need to recover address as it is set in Permit2Info // 6,7 Try get order filled amount MultiLimitOrderHelper memory helper = _getMultiFilledAmount(order, context, orderHash, permit2.orderOwner); // 8. Transfer tokens from order owner to the receiver ISignatureTransfer.PermitBatchTransferFrom memory permit = ISignatureTransfer.PermitBatchTransferFrom( new ISignatureTransfer.TokenPermissions[](order.inputs.length), permit2.nonce, permit2.deadline ); ISignatureTransfer.SignatureTransferDetails[] memory transferDetails = new ISignatureTransfer.SignatureTransferDetails[](order.inputs.length); for (uint256 i = 0; i < order.inputs.length; i++) { permit.permitted[i].token = order.inputs[i].tokenAddress; permit.permitted[i].amount = context.currentAmounts[i]; // Fill helper data helper.filledAmounts[i] += context.currentAmounts[i]; helper.inputTokens[i] = order.inputs[i].tokenAddress; helper.orderInputAmounts[i] = context.currentAmounts[i]; transferDetails[i].to = context.inputReceivers[i]; transferDetails[i].requestedAmount = context.currentAmounts[i]; } ISignatureTransfer(permit2.contractAddress).permitWitnessTransferFrom( permit, transferDetails, permit2.orderOwner, orderStructHash, MULTI_LIMIT_ORDER_WITNESS_TYPE_STRING, permit2.signature ); // 9-15 Fill order _multiLimitOrderFill(order, context, helper); } /// @notice Cancels single input limit order. Only the order owner address can cancel it. /// @param orderHash Single input limit order hash function cancelLimitOrder( bytes32 orderHash ) external { limitOrders[msg.sender][orderHash] = type(uint256).max; emit LimitOrderCancelled(orderHash, msg.sender); } /// @notice Cancels multi input limit order. Only the order owner address can cancel it. /// @param orderHash Multi input limit order hash function cancelMultiLimitOrder( bytes32 orderHash ) external { uint256[] memory _filledAmounts = new uint256[](1); _filledAmounts[0] = type(uint256).max; multiLimitOrders[msg.sender][orderHash] = _filledAmounts; emit MultiLimitOrderCancelled(orderHash, msg.sender); } /// @notice Directly swap funds held in router, multi input tokens to one output token. Only owner or liquidatorAddress can call it. /// @param inputs List of input token structs /// @param inputReceivers List of addresses for swap execution /// @param output Output token structs /// @param outputReceiver Address which will receive output token /// @param pathDefinition Encoded path definition for executor /// @param odosExecutor Address of contract which will execute the path /// @return amountOut Amount of output token after swap function swapRouterFunds( TokenInfo[] memory inputs, address[] memory inputReceivers, TokenInfo memory output, address outputReceiver, bytes calldata pathDefinition, address odosExecutor ) external returns (uint256 amountOut) { if (msg.sender != liquidatorAddress && msg.sender != owner()) { revert AddressNotAllowed(msg.sender); } uint256[] memory amountsIn = new uint256[](inputs.length); address[] memory tokensIn = new address[](inputs.length); for (uint256 i = 0; i < inputs.length; i++) { tokensIn[i] = inputs[i].tokenAddress; // Allow total amount spending amountsIn[i] = inputs[i].tokenAmount == 0 ? IERC20(tokensIn[i]).balanceOf(address(this)) : inputs[i].tokenAmount; // Transfer funds to the receivers IERC20(tokensIn[i]).safeTransfer(inputReceivers[i], amountsIn[i]); } // Get output token balances before uint256 balanceBefore = IERC20(output.tokenAddress).balanceOf(address(this)); // Delegate the execution of the path to the specified Odos Executor IOdosExecutor(odosExecutor).executePath(pathDefinition, amountsIn, msg.sender); // Get output token balances difference amountOut = IERC20(output.tokenAddress).balanceOf(address(this)) - balanceBefore; if (amountOut < output.tokenAmount) { revert SlippageLimitExceeded(output.tokenAddress, output.tokenAmount, amountOut); } // Transfer tokens to the receiver IERC20(output.tokenAddress).safeTransfer(outputReceiver, amountOut); emit SwapRouterFunds( msg.sender, tokensIn, amountsIn, inputReceivers, output.tokenAddress, output.tokenAmount, outputReceiver, amountOut ); } /// @notice Transfers funds held by the router contract /// @param tokens List of token address to be transferred /// @param amounts List of amounts of each token to be transferred /// @param dest Address to which the funds should be sent function transferRouterFunds( address[] calldata tokens, uint256[] calldata amounts, address dest ) external { if (msg.sender != liquidatorAddress && msg.sender != owner()) { revert AddressNotAllowed(msg.sender); } if (dest == address(0)) { revert InvalidAddress(dest); } if (tokens.length != amounts.length) revert InvalidArguments(); for (uint256 i = 0; i < tokens.length; i++) { if (tokens[i] == _ETH) { (bool success,) = payable(dest).call{value: amounts[i]}(""); if (!success) { revert TransferFailed(dest, amounts[i]); } } else { IERC20(tokens[i]).safeTransfer( dest, amounts[i] == 0 ? IERC20(tokens[i]).balanceOf(address(this)) : amounts[i] ); } } } /// @notice Adds an address to the list of allowed filler addresses /// @param account The address to be allowed function addAllowedFiller(address account) external onlyOwner { allowedFillers[account] = true; emit AllowedFillerAdded(account); } /// @notice Removes an address from the list of allowed filler addresses /// @param account The address to be disabled function removeAllowedFiller(address account) external onlyOwner { allowedFillers[account] = false; emit AllowedFillerRemoved(account); } /// @notice Disable the Ownable.renounceOwnership() function to prevent ownerless state function renounceOwnership() public onlyOwner view override { revert FunctionIsDisabled(); } /// @notice Changes the address which can call `swapRouterFunds()` function /// @param account The address of new liquidator function changeLiquidatorAddress(address account) public onlyOwner { liquidatorAddress = account; emit LiquidatorAddressChanged(account); } /// @dev Encodes TokenInfo struct according to EIP-712 /// @param tokenInfo TokenInfo struct /// @return Encoded struct function encodeTokenInfo( TokenInfo calldata tokenInfo ) public pure returns (bytes memory) { return abi.encode(TOKEN_INFO_TYPEHASH, tokenInfo.tokenAddress, tokenInfo.tokenAmount); } /// @notice gets LimitOrder struct hash according to EIP-712 /// @param order LimitOrder struct /// @return structHash EIP-712 struct hash function getLimitOrderStructHash( LimitOrder calldata order ) public pure returns (bytes32 structHash) { return keccak256( abi.encode( LIMIT_ORDER_TYPEHASH, keccak256(encodeTokenInfo(order.input)), keccak256(encodeTokenInfo(order.output)), order.expiry, order.salt, order.referralCode, order.partiallyFillable ) ); } /// @notice gets MultiLimitOrder struct hash according to EIP-712 /// @param order MultiLimitOrder struct /// @return structHash EIP-712 struct hash function getMultiLimitOrderStructHash( MultiLimitOrder calldata order ) public pure returns (bytes32 structHash) { bytes32[] memory encodedInputs = new bytes32[](order.inputs.length); for (uint256 i = 0; i < order.inputs.length; i++) { encodedInputs[i] = keccak256(encodeTokenInfo(order.inputs[i])); } bytes32[] memory encodedOutputs = new bytes32[](order.outputs.length); for (uint256 i = 0; i < order.outputs.length; i++) { encodedOutputs[i] = keccak256(encodeTokenInfo(order.outputs[i])); } return keccak256( abi.encode( MULTI_LIMIT_ORDER_TYPEHASH, keccak256(abi.encodePacked(encodedInputs)), keccak256(abi.encodePacked(encodedOutputs)), order.expiry, order.salt, order.referralCode, order.partiallyFillable ) ); } /// @notice Returns single input limit order hash /// @param order Single input limit order /// @return hash Order hash function getLimitOrderHash(LimitOrder calldata order) public view returns (bytes32 hash) { return _hashTypedDataV4(getLimitOrderStructHash(order)); } /// @notice Returns multi input limit order hash /// @param order Multi input limit order /// @return hash Order hash function getMultiLimitOrderHash( MultiLimitOrder calldata order ) public view returns (bytes32 hash) { return _hashTypedDataV4(getMultiLimitOrderStructHash(order)); } /// @dev Checks order parameters and current order state before execution /// @param order Single input limit order struct function _limitOrderChecks( LimitOrder calldata order ) internal view { // 1. Check msg.sender allowed if (!allowedFillers[msg.sender]) { revert AddressNotAllowed(msg.sender); } // 2. Check if order still valid if (order.expiry < block.timestamp) { revert OrderExpired(order.expiry, block.timestamp); } // 3. Check tokens, amounts if (order.input.tokenAddress == order.output.tokenAddress) { revert ArbitrageNotAllowed(order.input.tokenAddress); } } /// @dev Limit order checks /// @param order Single input limit order struct /// @param context Order execution context /// @param orderHash Limit order struct hash /// @param orderOwner Order owner address /// @return filledAmount Order amount filled by now function _getFilledAmount( LimitOrder calldata order, LimitOrderContext calldata context, bytes32 orderHash, address orderOwner ) internal view returns ( uint256 filledAmount ) { // 6. Extract previously filled amounts for order from storage, or create filledAmount = limitOrders[orderOwner][orderHash]; if (filledAmount == type(uint256).max) { revert OrderCancelled(orderHash); } // 7. Check if fill possible: // - If partiallyFillable, total amount do not exceed // - If not partiallyFillable - it was not filled previously if (order.partiallyFillable) { // Check that the currentAmount fits the total order amount if (filledAmount + context.currentAmount > order.input.tokenAmount) { revert CurrentAmountMismatch(order.input.tokenAddress, order.input.tokenAmount, filledAmount, context.currentAmount); } } else { // Revert if order was filled or currentAmount is not equal to the order amount if (filledAmount > 0 || context.currentAmount != order.input.tokenAmount) { revert CurrentAmountMismatch(order.input.tokenAddress, order.input.tokenAmount, filledAmount, context.currentAmount); } } } /// @dev Fills single input limit order /// @param order Single input limit order struct /// @param context Order execution context /// @param orderHash Order hash /// @param orderOwner Order owner address /// @param filledAmount Amount filled by now function _limitOrderFill( LimitOrder calldata order, LimitOrderContext calldata context, bytes32 orderHash, address orderOwner, uint256 filledAmount ) internal { // 9. Update order filled amounts in storage filledAmount += context.currentAmount; limitOrders[orderOwner][orderHash] = filledAmount; LimitOrderHelper memory helper; // 10. Get output token balances before helper.balanceBefore = IERC20(order.output.tokenAddress).balanceOf(address(this)); // 11. Call Odos Executor { uint256[] memory amountsIn = new uint256[](1); amountsIn[0] = context.currentAmount; IOdosExecutor(context.odosExecutor).executePath(context.pathDefinition, amountsIn, msg.sender); } // 12. Get output token balances difference helper.amountOut = IERC20(order.output.tokenAddress).balanceOf(address(this)) - helper.balanceBefore; // calculate prorated output amount in case of partial fill, otherwise it will be equal to order.output.tokenAmount helper.proratedAmount = SCALE * order.output.tokenAmount * context.currentAmount / order.input.tokenAmount / SCALE; // 13. Calculate and transfer referral fee if any if (order.referralCode > REFERRAL_WITH_FEE_THRESHOLD) { IOdosRouterV2.referralInfo memory ri = IOdosRouterV2(ODOS_ROUTER_V2).referralLookup(order.referralCode); uint256 beneficiaryAmount = helper.amountOut * ri.referralFee * 8 / (FEE_DENOM * 10); helper.amountOut = helper.amountOut * (FEE_DENOM - ri.referralFee) / FEE_DENOM; IERC20(order.output.tokenAddress).safeTransfer(ri.beneficiary, beneficiaryAmount); } // 14. Check slippage, adjust amountOut if (helper.amountOut < helper.proratedAmount) { revert SlippageLimitExceeded(order.output.tokenAddress, helper.proratedAmount, helper.amountOut); } // 15. Check surplus helper.surplus = helper.amountOut - helper.proratedAmount; if (helper.surplus < context.minSurplus) { revert MinSurplusCheckFailed(order.output.tokenAddress, context.minSurplus, helper.surplus); } // 16. Transfer tokens to the order owner IERC20(order.output.tokenAddress).safeTransfer(orderOwner, helper.proratedAmount); // 17. Emit LimitOrderFilled event emit LimitOrderFilled( orderHash, orderOwner, order.input.tokenAddress, order.output.tokenAddress, order.input.tokenAmount, order.output.tokenAmount, context.currentAmount, helper.proratedAmount, helper.surplus, order.referralCode, context.orderType ); } /// @dev Checks order parameters and current order state before execution /// @param order Multi input limit order struct function _multiOrderChecks( MultiLimitOrder calldata order ) internal view { // 1. Check msg.sender allowed if (!allowedFillers[msg.sender]) { revert AddressNotAllowed(msg.sender); } // 2. Check if order still valid if (order.expiry < block.timestamp) { revert OrderExpired(order.expiry, block.timestamp); } // 3. Check tokens, amounts for (uint256 i = 0; i < order.inputs.length; i++) { for (uint256 j = 0; j < order.outputs.length; j++) { if (order.inputs[i].tokenAddress == order.outputs[j].tokenAddress) { revert ArbitrageNotAllowed(order.inputs[i].tokenAddress); } } } } /// @dev Checks order parameters and current order state before execution /// @param order Multi input limit order struct /// @param context Order execution context /// @param orderHash Order struct hash /// @return helper Helper struct which contains order information function _getMultiFilledAmount( MultiLimitOrder calldata order, MultiLimitOrderContext calldata context, bytes32 orderHash, address orderOwner ) internal view returns ( MultiLimitOrderHelper memory helper ) { helper = MultiLimitOrderHelper({ inputTokens: new address[](order.inputs.length), outputTokens: new address[](order.outputs.length), orderInputAmounts: new uint256[](order.inputs.length), orderOutputAmounts: new uint256[](order.outputs.length), filledAmounts: new uint256[](order.inputs.length), filledOutputAmounts: new uint256[](order.outputs.length), surplus: new uint256[](order.outputs.length), balancesBefore: new uint256[](order.outputs.length), orderOwner : orderOwner, orderHash : orderHash, amountProration: 0 }); // 6. Extract previously filled amounts for order from storage, or create helper.filledAmounts = multiLimitOrders[orderOwner][orderHash]; if (helper.filledAmounts.length > 0 && helper.filledAmounts[0] == type(uint256).max) { revert OrderCancelled(orderHash); } if (helper.filledAmounts.length == 0) { helper.filledAmounts = new uint256[](order.inputs.length); } // 7. Check if fill possible: // - If partiallyFillable, total amount do not exceed // - If not partiallyFillable - it was not filled previously if (order.partiallyFillable) { // Check that the currentAmount fits the total order amount for (uint256 i = 0; i < helper.filledAmounts.length; i++) { if (helper.filledAmounts[i] + context.currentAmounts[i] > order.inputs[i].tokenAmount) { revert CurrentAmountMismatch(order.inputs[i].tokenAddress, order.inputs[i].tokenAmount, helper.filledAmounts[i], context.currentAmounts[i]); } // Set the maximum input proration uint256 thisAmountProration = SCALE * context.currentAmounts[i] / order.inputs[i].tokenAmount; if (thisAmountProration > helper.amountProration) { helper.amountProration = thisAmountProration; } } } else { // Set the proration to one, since no proration needed helper.amountProration = SCALE; // Revert if order was filled or currentAmount is not equal to the order amount for (uint256 i = 0; i < helper.filledAmounts.length; i++) { if (helper.filledAmounts[i] > 0 || context.currentAmounts[i] != order.inputs[i].tokenAmount) { revert CurrentAmountMismatch(order.inputs[i].tokenAddress, order.inputs[i].tokenAmount, helper.filledAmounts[i], context.currentAmounts[i]); } } } } /// @dev Fills multi input limit order /// @param order Multi input limit order struct /// @param context Order execution context /// @param helper Helper struct which contains order information function _multiLimitOrderFill( MultiLimitOrder calldata order, MultiLimitOrderContext calldata context, MultiLimitOrderHelper memory helper ) internal { // 9. Update order filled amounts in storage multiLimitOrders[helper.orderOwner][helper.orderHash] = helper.filledAmounts; // 10. Get output token balances before for (uint256 i = 0; i < order.outputs.length; i++) { helper.outputTokens[i] = order.outputs[i].tokenAddress; helper.orderOutputAmounts[i] = order.outputs[i].tokenAmount; helper.balancesBefore[i] = IERC20(order.outputs[i].tokenAddress).balanceOf(address(this)); } // 11. Call Odos Executor IOdosExecutor(context.odosExecutor).executePath(context.pathDefinition, context.currentAmounts, msg.sender); { // 12. Get output token balances difference uint256[] memory amountsOut = new uint256[](order.outputs.length); for (uint256 i = 0; i < order.outputs.length; i++) { amountsOut[i] = IERC20(order.outputs[i].tokenAddress).balanceOf(address(this)) - helper.balancesBefore[i]; } IOdosRouterV2.referralInfo memory ri; if (order.referralCode > REFERRAL_WITH_FEE_THRESHOLD) { ri = IOdosRouterV2(ODOS_ROUTER_V2).referralLookup(order.referralCode); } for (uint256 i = 0; i < order.outputs.length; i++) { // 13. Calculate and transfer referral fee if any if (order.referralCode > REFERRAL_WITH_FEE_THRESHOLD) { uint256 beneficiaryAmount = amountsOut[i] * ri.referralFee * 8 / (FEE_DENOM * 10); amountsOut[i] = amountsOut[i] * (FEE_DENOM - ri.referralFee) / FEE_DENOM; IERC20(order.outputs[i].tokenAddress).safeTransfer(ri.beneficiary, beneficiaryAmount); } // calculate prorated output amount in case of partial fill, otherwise it will be equal to order.output.tokenAmount uint256 proratedAmount = helper.amountProration * order.outputs[i].tokenAmount / SCALE; // 14. Check slippage, adjust amountOut if (amountsOut[i] < proratedAmount) { revert SlippageLimitExceeded(order.outputs[i].tokenAddress, proratedAmount, amountsOut[i]); } helper.filledOutputAmounts[i] = proratedAmount; // 15. Check surplus helper.surplus[i] = amountsOut[i] - proratedAmount; if (helper.surplus[i] < context.minSurplus[i]) { revert MinSurplusCheckFailed(order.outputs[i].tokenAddress, context.minSurplus[i], helper.surplus[i]); } // 16. Transfer tokens to the order owner IERC20(order.outputs[i].tokenAddress).safeTransfer(helper.orderOwner, proratedAmount); } } // 17. Emit LimitOrderFilled event emit MultiLimitOrderFilled( helper.orderHash, helper.orderOwner, helper.inputTokens, helper.outputTokens, helper.orderInputAmounts, helper.orderOutputAmounts, context.currentAmounts, helper.filledOutputAmounts, helper.surplus, order.referralCode, context.orderType ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_odosRouterV2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"ArbitrageNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderAmount","type":"uint256"},{"internalType":"uint256","name":"filledAmount","type":"uint256"},{"internalType":"uint256","name":"currentAmount","type":"uint256"}],"name":"CurrentAmountMismatch","type":"error"},{"inputs":[{"internalType":"bytes","name":"error","type":"bytes"}],"name":"ERC1271Revert","type":"error"},{"inputs":[{"internalType":"bytes","name":"error","type":"bytes"}],"name":"ERC6492DeployFailed","type":"error"},{"inputs":[],"name":"FunctionIsDisabled","type":"error"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidArguments","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"InvalidEip1271Signature","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedLength","type":"uint256"},{"internalType":"uint256","name":"actualLength","type":"uint256"}],"name":"InvalidPresignLength","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidSignatureLength","type":"error"},{"inputs":[],"name":"InvalidSignatureVValue","type":"error"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"expectedValue","type":"uint256"},{"internalType":"uint256","name":"actualValue","type":"uint256"}],"name":"MinSurplusCheckFailed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderCancelled","type":"error"},{"inputs":[{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"OrderExpired","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"OrderNotPresigned","type":"error"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"actualAmount","type":"uint256"}],"name":"SlippageLimitExceeded","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AllowedFillerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AllowedFillerRemoved","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"orderOwner","type":"address"}],"name":"LimitOrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"orderOwner","type":"address"},{"indexed":false,"internalType":"address","name":"inputToken","type":"address"},{"indexed":false,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderInputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderOutputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"filledInputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"filledOutputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"surplus","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"referralCode","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"orderType","type":"uint256"}],"name":"LimitOrderFilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"LiquidatorAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"orderOwner","type":"address"}],"name":"MultiLimitOrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"orderOwner","type":"address"},{"indexed":false,"internalType":"address[]","name":"inputTokens","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"outputTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"orderInputAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"orderOutputAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"filledInputAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"filledOutputAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"surplus","type":"uint256[]"},{"indexed":false,"internalType":"uint32","name":"referralCode","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"orderType","type":"uint256"}],"name":"MultiLimitOrderFilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"preSigned","type":"bool"}],"name":"OrderPreSigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address[]","name":"inputTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"inputAmounts","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"inputReceivers","type":"address[]"},{"indexed":false,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"outputReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"SwapRouterFunds","type":"event"},{"inputs":[],"name":"LIMIT_ORDER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIMIT_ORDER_WITNESS_TYPE_STRING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MULTI_LIMIT_ORDER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MULTI_LIMIT_ORDER_WITNESS_TYPE_STRING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_INFO_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAllowedFiller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedFillers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"cancelLimitOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"cancelMultiLimitOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"changeLiquidatorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"tokenInfo","type":"tuple"}],"name":"encodeTokenInfo","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"output","type":"tuple"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.LimitOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"enum SignatureValidator.SignatureValidationMethod","name":"validationMethod","type":"uint8"}],"internalType":"struct SignatureValidator.Signature","name":"signature","type":"tuple"},{"components":[{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"odosExecutor","type":"address"},{"internalType":"uint256","name":"currentAmount","type":"uint256"},{"internalType":"address","name":"inputReceiver","type":"address"},{"internalType":"uint256","name":"minSurplus","type":"uint256"},{"internalType":"uint256","name":"orderType","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.LimitOrderContext","name":"context","type":"tuple"}],"name":"fillLimitOrder","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"output","type":"tuple"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.LimitOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"odosExecutor","type":"address"},{"internalType":"uint256","name":"currentAmount","type":"uint256"},{"internalType":"address","name":"inputReceiver","type":"address"},{"internalType":"uint256","name":"minSurplus","type":"uint256"},{"internalType":"uint256","name":"orderType","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.LimitOrderContext","name":"context","type":"tuple"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"orderOwner","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OdosLimitOrderRouter.Permit2Info","name":"permit2","type":"tuple"}],"name":"fillLimitOrderPermit2","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.MultiLimitOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"enum SignatureValidator.SignatureValidationMethod","name":"validationMethod","type":"uint8"}],"internalType":"struct SignatureValidator.Signature","name":"signature","type":"tuple"},{"components":[{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"odosExecutor","type":"address"},{"internalType":"uint256[]","name":"currentAmounts","type":"uint256[]"},{"internalType":"address[]","name":"inputReceivers","type":"address[]"},{"internalType":"uint256[]","name":"minSurplus","type":"uint256[]"},{"internalType":"uint256","name":"orderType","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.MultiLimitOrderContext","name":"context","type":"tuple"}],"name":"fillMultiLimitOrder","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.MultiLimitOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"odosExecutor","type":"address"},{"internalType":"uint256[]","name":"currentAmounts","type":"uint256[]"},{"internalType":"address[]","name":"inputReceivers","type":"address[]"},{"internalType":"uint256[]","name":"minSurplus","type":"uint256[]"},{"internalType":"uint256","name":"orderType","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.MultiLimitOrderContext","name":"context","type":"tuple"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"orderOwner","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OdosLimitOrderRouter.Permit2Info","name":"permit2","type":"tuple"}],"name":"fillMultiLimitOrderPermit2","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"output","type":"tuple"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.LimitOrder","name":"order","type":"tuple"}],"name":"getLimitOrderHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"input","type":"tuple"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"output","type":"tuple"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.LimitOrder","name":"order","type":"tuple"}],"name":"getLimitOrderStructHash","outputs":[{"internalType":"bytes32","name":"structHash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.MultiLimitOrder","name":"order","type":"tuple"}],"name":"getMultiLimitOrderHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"outputs","type":"tuple[]"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"uint32","name":"referralCode","type":"uint32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"}],"internalType":"struct OdosLimitOrderRouter.MultiLimitOrder","name":"order","type":"tuple"}],"name":"getMultiLimitOrderStructHash","outputs":[{"internalType":"bytes32","name":"structHash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSig","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"bool","name":"allowSideEffects","type":"bool"}],"name":"isValidSigImpl","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSigWithSideEffects","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"orderOwner","type":"address"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"limitOrders","outputs":[{"internalType":"uint256","name":"filledAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"orderOwner","type":"address"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"multiLimitOrders","outputs":[{"internalType":"uint256","name":"filledAmounts","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"preSignedOrders","outputs":[{"internalType":"bool","name":"preSigned","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAllowedFiller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bool","name":"preSigned","type":"bool"}],"name":"setPreSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo[]","name":"inputs","type":"tuple[]"},{"internalType":"address[]","name":"inputReceivers","type":"address[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"internalType":"struct OdosLimitOrderRouter.TokenInfo","name":"output","type":"tuple"},{"internalType":"address","name":"outputReceiver","type":"address"},{"internalType":"bytes","name":"pathDefinition","type":"bytes"},{"internalType":"address","name":"odosExecutor","type":"address"}],"name":"swapRouterFunds","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"dest","type":"address"}],"name":"transferRouterFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101806040523480156200001257600080fd5b50604051620064bd380380620064bd833981016040819052620000359162000338565b604080518082018252601481527f4f646f734c696d69744f72646572526f75746572000000000000000000000000602080830191909152825180840190935260018352603160f81b90830152906200008f8260006200019a565b61012052620000a08160016200019a565b61014052815160208084019190912060e052815190820120610100524660a0526200012e60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c0526200014233620001d3565b6001600160a01b0381166200017a57604051634726455360e11b81526001600160a01b03821660048201526024015b60405180910390fd5b6001600160a01b038116610160526200019333620001f1565b5062000550565b6000602083511015620001ba57620001b28362000245565b9050620001cd565b81620001c784826200040f565b5060ff90505b92915050565b600380546001600160a01b0319169055620001ee8162000288565b50565b620001fb620002da565b600580546001600160a01b0319166001600160a01b0383169081179091556040517f1535fa8f7275b71050af30bf7f74391b45be7ba2b545fd28279dafe9b50f642490600090a250565b600080829050601f8151111562000273578260405163305a27a960e01b8152600401620001719190620004db565b805162000280826200052b565b179392505050565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6002546001600160a01b03163314620003365760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000171565b565b6000602082840312156200034b57600080fd5b81516001600160a01b03811681146200036357600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200039557607f821691505b602082108103620003b657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200040a57600081815260208120601f850160051c81016020861015620003e55750805b601f850160051c820191505b818110156200040657828155600101620003f1565b5050505b505050565b81516001600160401b038111156200042b576200042b6200036a565b62000443816200043c845462000380565b84620003bc565b602080601f8311600181146200047b5760008415620004625750858301515b600019600386901b1c1916600185901b17855562000406565b600085815260208120601f198616915b82811015620004ac578886015182559484019460019091019084016200048b565b5085821015620004cb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083528351808285015260005b818110156200050a57858101830151858201604001528201620004ec565b506000604082860101526040601f19601f8301168501019250505092915050565b80516020808301519190811015620003b65760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051615f00620005bd60003960008181612cd30152613ccc015260006111a30152600061117901526000614708015260006146e00152600061463b015260006146650152600061468f0152615f006000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806391d326b011610145578063d678b6fc116100bd578063e5440d921161008c578063eb8fb26811610071578063eb8fb26814610518578063f2fde38b1461052b578063ff247a8e1461053e57600080fd5b8063e5440d92146104f2578063e5dae17d1461050557600080fd5b8063d678b6fc146104be578063dfbc013c146104c6578063e225651a146104d9578063e30c3978146104e157600080fd5b8063adad9a2b11610114578063bba06de4116100f9578063bba06de414610490578063ce0f52d5146104a3578063ce64c997146104b657600080fd5b8063adad9a2b14610475578063b5967d011461048857600080fd5b806391d326b01461041157806398ef1ed8146104245780639ef0fbfd14610437578063aca766aa1461044a57600080fd5b8063559475e5116101d857806375c111f2116101a757806384b0196e1161018c57806384b0196e146103d25780638da5cb5b146103ed5780638f068430146103fe57600080fd5b806375c111f21461039f57806379ba5097146103ca57600080fd5b8063559475e5146103515780636467329514610364578063712c512214610377578063715018a61461039757600080fd5b8063242dcbf01161022f5780634584eff6116102145780634584eff61461032357806354cc8fc61461033657806354dd5f741461034957600080fd5b8063242dcbf0146102ed5780633e0cf5431461030057600080fd5b806316d4340114610261578063174da621146102895780631d971a4a1461029e57806321d1c55f146102cc575b600080fd5b61027461026f366004614af6565b610551565b60405190151581526020015b60405180910390f35b61029c610297366004614baf565b61090f565b005b6102746102ac366004614c25565b600460209081526000928352604080842090915290825290205460ff1681565b6102df6102da366004614c8e565b610c17565b604051908152602001610280565b6102df6102fb366004614d06565b610cb1565b61027461030e366004614d2a565b60086020526000908152604090205460ff1681565b61029c610331366004614d47565b610cca565b6102df610344366004614d60565b610d13565b6102df610efe565b6102df61035f366004614dd1565b610f5a565b61029c610372366004614d47565b610f98565b61038a610385366004614e06565b611035565b6040516102809190614e72565b61029c6110a3565b6005546103b2906001600160a01b031681565b6040516001600160a01b039091168152602001610280565b61029c6110dd565b6103da61116b565b6040516102809796959493929190614ec0565b6002546001600160a01b03166103b2565b61027461040c366004614f4a565b61120f565b6102df61041f366004614fa6565b61128c565b610274610432366004614f4a565b611539565b6102df610445366004614fed565b61165d565b6102df610458366004614c25565b600660209081526000928352604080842090915290825290205481565b6102df610483366004614d06565b61183c565b61038a611943565b61029c61049e366004614d2a565b6119b2565b61029c6104b1366004614d2a565b611a06565b6102df611a57565b6102df611a7a565b6102df6104d4366004614fa6565b611abd565b61038a611acb565b6003546001600160a01b03166103b2565b6102df61050036600461505b565b611b28565b61029c610513366004614d2a565b611fda565b61029c6105263660046150cc565b612039565b61029c610539366004614d2a565b612099565b6102df61054c366004615234565b612117565b60006001600160a01b0386163b606082602086108015906105b257507f6492649264926492649264926492649264926492649264926492649264926492878761059b60208261536c565b6105a7928a929061537f565b6105b0916153a9565b145b905080156106a457600060608882896105cc60208261536c565b926105d99392919061537f565b8101906105e69190615437565b95509092509050600085900361069d57600080836001600160a01b03168360405161061191906154a3565b6000604051808303816000865af19150503d806000811461064e576040519150601f19603f3d011682016040523d82523d6000602084013e610653565b606091505b50915091508161069a57806040517f9d0d6e2d0000000000000000000000000000000000000000000000000000000081526004016106919190614e72565b60405180910390fd5b50505b50506106de565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b80806106ea5750600083115b1561080257604051630b135d3f60e11b81526001600160a01b038a1690631626ba7e9061071d908b9086906004016154bf565b602060405180830381865afa925050508015610756575060408051601f3d908101601f19168201909252610753918101906154d8565b60015b6107be573d808015610784576040519150601f19603f3d011682016040523d82523d6000602084013e610789565b606091505b50806040517f6f2a95990000000000000000000000000000000000000000000000000000000081526004016106919190614e72565b6001600160e01b03198116630b135d3f60e11b14841580156107dd5750825b80156107e7575086155b156107f657806000526001601ffd5b94506109069350505050565b6041861461083c576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061084b602082898b61537f565b610854916153a9565b90506000610866604060208a8c61537f565b61086f916153a9565b905060008989604081811061088657610886615502565b919091013560f81c915050601b81148015906108a657508060ff16601c14155b156108dd576040517f449f5db100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8b6001600160a01b03166108f38c8386866125ce565b6001600160a01b03161496505050505050505b95945050505050565b6005546001600160a01b0316331480159061093557506002546001600160a01b03163314155b15610955576040516351ee5ed560e01b8152336004820152602401610691565b6001600160a01b0381166109a0576040517f8e4c8aa60000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610691565b8382146109d9576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b84811015610c0f5760008686838181106109f8576109f8615502565b9050602002016020810190610a0d9190614d2a565b6001600160a01b031603610af3576000826001600160a01b0316858584818110610a3957610a39615502565b9050602002013560405160006040518083038185875af1925050503d8060008114610a80576040519150601f19603f3d011682016040523d82523d6000602084013e610a85565b606091505b5050905080610aed5782858584818110610aa157610aa1615502565b6040517f1c43b9760000000000000000000000000000000000000000000000000000000081526001600160a01b0390941660048501526020029190910135602483015250604401610691565b50610bfd565b610bfd82858584818110610b0957610b09615502565b90506020020135600014610b3557858584818110610b2957610b29615502565b90506020020135610bc6565b878784818110610b4757610b47615502565b9050602002016020810190610b5c9190614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc69190615518565b888885818110610bd857610bd8615502565b9050602002016020810190610bed9190614d2a565b6001600160a01b031691906125f6565b80610c0781615531565b9150506109dc565b505050505050565b6000610c228461268c565b610c2b84610cb1565b90506000610c5282610c3d868061554a565b610c4d6040890160208a01615591565b61276e565b90506000610c62868585856128f4565b9050610c9b82610c786080870160608801614d2a565b6040870135610c8a60208b018b614d2a565b6001600160a01b03169291906129e5565b610ca88685858585612a3c565b50509392505050565b6000610cc4610cbf8361183c565b612fe0565b92915050565b33600081815260066020908152604080832085845290915280822060001990555183917f9589246bd420836dc7c4f266f2553bca3d6fee904eb0aad0a436ba3fba8fe3f991a350565b6000610d1e84613028565b610d2784611abd565b90506000610d3982610c3d868061554a565b90506000610d498685858561318d565b905060005b610d5887806155b2565b9050811015610ef257610dee83610d7260608801886155fc565b84818110610d8257610d82615502565b9050602002016020810190610d979190614d2a565b610da460408901896155fc565b85818110610db457610db4615502565b60200291909101359050610dc88b806155b2565b86818110610dd857610dd8615502565b610c8a9260206040909202019081019150614d2a565b610dfb60408601866155fc565b82818110610e0b57610e0b615502565b9050602002013582608001518281518110610e2857610e28615502565b60200260200101818151610e3c9190615646565b905250610e4987806155b2565b82818110610e5957610e59615502565b610e6f9260206040909202019081019150614d2a565b8251805183908110610e8357610e83615502565b6001600160a01b0390921660209283029190910190910152610ea587806155b2565b82818110610eb557610eb5615502565b9050604002016020013582604001518281518110610ed557610ed5615502565b602090810291909101015280610eea81615531565b915050610d4e565b50610ca88685836138bb565b6040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e9860339139604051602001610f41929190615659565b6040516020818303038152906040528051906020012081565b60076020528260005260406000206020528160005260406000208181548110610f8257600080fd5b9060005260206000200160009250925050505481565b6040805160018082528183019092526000916020808301908036833701905050905060001981600081518110610fd057610fd0615502565b60209081029190910181019190915233600090815260078252604080822085835283529020825161100392840190614a21565b50604051339083907fa8c658e479c63c75980f19e6b202df4243db8c4a36973b4d162b6ffe6cf0d69190600090a35050565b6060604051806060016040528060338152602001615e986033913980516020918201209061106590840184614d2a565b604080516020818101949094526001600160a01b03909216908201529083013560608201526080016040516020818303038152906040529050919050565b6110ab6141cb565b6040517f21afe9d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035433906001600160a01b0316811461115f5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610691565b61116881614227565b50565b60006060808280808361119e7f00000000000000000000000000000000000000000000000000000000000000008361424d565b6111c97f0000000000000000000000000000000000000000000000000000000000000000600161424d565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b6040516316d4340160e01b815260009030906316d434019061123e9088908890889088906001906004016156b1565b6020604051808303816000875af115801561125d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128191906156ee565b90505b949350505050565b60008061129983806155b2565b905067ffffffffffffffff8111156112b3576112b36150fc565b6040519080825280602002602001820160405280156112dc578160200160208202803683370190505b50905060005b6112ec84806155b2565b90508110156113535761131d61130285806155b2565b8381811061131257611312615502565b905060400201611035565b8051906020012082828151811061133657611336615502565b60209081029190910101528061134b81615531565b9150506112e2565b50600061136360208501856155b2565b905067ffffffffffffffff81111561137d5761137d6150fc565b6040519080825280602002602001820160405280156113a6578160200160208202803683370190505b50905060005b6113b960208601866155b2565b9050811015611408576113d261130260208701876155b2565b805190602001208282815181106113eb576113eb615502565b60209081029190910101528061140081615531565b9150506113ac565b506040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e986033913960405160200161144c929190615659565b6040516020818303038152906040528051906020012082604051602001611473919061570b565b604051602081830303815290604052805190602001208260405160200161149a919061570b565b60405160208183030381529060405280519060200120866040013587606001358860800160208101906114cd9190615741565b6114dd60c08b0160a08c01615767565b6040805160208101989098528701959095526060860193909352608085019190915260a084015263ffffffff1660c0830152151560e0820152610100016040516020818303038152906040528051906020012092505050919050565b6040516316d4340160e01b815260009030906316d434019061156790889088908890889088906004016156b1565b6020604051808303816000875af19250505080156115a2575060408051601f3d908101601f1916820190925261159f918101906156ee565b60015b611656573d8080156115d0576040519150601f19603f3d011682016040523d82523d6000602084013e6115d5565b606091505b508051600181900361164857816000815181106115f4576115f4615502565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0100000000000000000000000000000000000000000000000000000000000000149250611284915050565b8060208301fd5b5050611284565b9050611284565b60006116688461268c565b60006116738561183c565b905061167e81612fe0565b9150600061169d8686856116986080890160608a01614d2a565b6128f4565b90506116ac6020850185614d2a565b6040805160a081019091526001600160a01b03919091169063137c29fe908060608101806116dd60208d018d614d2a565b6001600160a01b031681526020018a60400135815250815260200187602001358152602001876040013581525060405180604001604052808960600160208101906117289190614d2a565b6001600160a01b0316815260408a013560209091015261174e6080890160608a01614d2a565b866040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e91396040516020016117ac93929190615784565b60408051601f198184030181529190526117c960808c018c61554a565b6040518863ffffffff1660e01b81526004016117eb97969594939291906157f6565b600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b50505050610ca88686858760600160208101906118369190614d2a565b85612a3c565b60006040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e9860339139604051602001611881929190615659565b604051602081830303815290604052805190602001206118a383600001611035565b805190602001206118b684604001611035565b8051602090910120608085013560a08601356118d860e0880160c08901615741565b6118e9610100890160e08a01615767565b6040805160208101989098528701959095526060860193909352608085019190915260a084015263ffffffff1660c0830152151560e082015261010001604051602081830303815290604052805190602001209050919050565b6040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e91396040516020016119a09392919061588b565b60405160208183030381529060405281565b6119ba6141cb565b6001600160a01b038116600081815260086020526040808220805460ff19166001179055517fa2dce8c36614bedf0a7ccdd7570cfe9a7f2b13a2d778512c4204fd2e90ba99479190a250565b611a0e6141cb565b6001600160a01b038116600081815260086020526040808220805460ff19169055517f3f27d27eeec2234d4d75f7629ee5638cbbf219d246f1077f57ebedaa9c7659259190a250565b604051806060016040528060338152602001615e98603391398051906020012081565b6040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e9860339139604051602001610f41929190615659565b6000610cc4610cbf8361128c565b6040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e91396040516020016119a093929190615784565b6000611b3384613028565b6000611b3e8561128c565b9050611b4981612fe0565b91506000611b68868685611b636080890160608a01614d2a565b61318d565b604080516060810190915290915060009080611b8489806155b2565b905067ffffffffffffffff811115611b9e57611b9e6150fc565b604051908082528060200260200182016040528015611be357816020015b6040805180820190915260008082526020820152815260200190600190039081611bbc5790505b5081526020878101359082015260408088013591015290506000611c0788806155b2565b905067ffffffffffffffff811115611c2157611c216150fc565b604051908082528060200260200182016040528015611c6657816020015b6040805180820190915260008082526020820152815260200190600190039081611c3f5790505b50905060005b611c7689806155b2565b9050811015611ec757611c8989806155b2565b82818110611c9957611c99615502565b611caf9260206040909202019081019150614d2a565b8351805183908110611cc357611cc3615502565b60209081029190910101516001600160a01b039091169052611ce860408901896155fc565b82818110611cf857611cf8615502565b9050602002013583600001518281518110611d1557611d15615502565b6020908102919091018101510152611d3060408901896155fc565b82818110611d4057611d40615502565b9050602002013584608001518281518110611d5d57611d5d615502565b60200260200101818151611d719190615646565b905250611d7e89806155b2565b82818110611d8e57611d8e615502565b611da49260206040909202019081019150614d2a565b8451805183908110611db857611db8615502565b6001600160a01b0390921660209283029190910190910152611ddd60408901896155fc565b82818110611ded57611ded615502565b9050602002013584604001518281518110611e0a57611e0a615502565b6020908102919091010152611e2260608901896155fc565b82818110611e3257611e32615502565b9050602002016020810190611e479190614d2a565b828281518110611e5957611e59615502565b60209081029190910101516001600160a01b039091169052611e7e60408901896155fc565b82818110611e8e57611e8e615502565b90506020020135828281518110611ea757611ea7615502565b602090810291909101810151015280611ebf81615531565b915050611c6c565b50611ed56020870187614d2a565b6001600160a01b031663fe8ec1a78383611ef560808b0160608c01614d2a565b886040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e9139604051602001611f539392919061588b565b60408051601f19818403018152919052611f7060808e018e61554a565b6040518863ffffffff1660e01b8152600401611f92979695949392919061594a565b600060405180830381600087803b158015611fac57600080fd5b505af1158015611fc0573d6000803e3d6000fd5b50505050611fcf8888856138bb565b505050509392505050565b611fe26141cb565b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f1535fa8f7275b71050af30bf7f74391b45be7ba2b545fd28279dafe9b50f642490600090a250565b336000818152600460209081526040808320868452825291829020805460ff1916851515908117909155915191825284917f146d83fd67d3b4dab3c8bbade3b7dcd73867dc6d376b219a75a3f578f61edc9d910160405180910390a35050565b6120a16141cb565b600380546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff1990911681179091556120df6002546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6005546000906001600160a01b0316331480159061214057506002546001600160a01b03163314155b15612160576040516351ee5ed560e01b8152336004820152602401610691565b6000885167ffffffffffffffff81111561217c5761217c6150fc565b6040519080825280602002602001820160405280156121a5578160200160208202803683370190505b5090506000895167ffffffffffffffff8111156121c4576121c46150fc565b6040519080825280602002602001820160405280156121ed578160200160208202803683370190505b50905060005b8a518110156123b3578a818151811061220e5761220e615502565b60200260200101516000015182828151811061222c5761222c615502565b60200260200101906001600160a01b031690816001600160a01b0316815250508a818151811061225e5761225e615502565b602002602001015160200151600014612294578a818151811061228357612283615502565b60200260200101516020015161231a565b8181815181106122a6576122a6615502565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156122f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231a9190615518565b83828151811061232c5761232c615502565b6020026020010181815250506123a18a828151811061234d5761234d615502565b602002602001015184838151811061236757612367615502565b602002602001015184848151811061238157612381615502565b60200260200101516001600160a01b03166125f69092919063ffffffff16565b806123ab81615531565b9150506121f3565b5087516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156123fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124209190615518565b6040517fcb70e2730000000000000000000000000000000000000000000000000000000081529091506001600160a01b0386169063cb70e2739061246e908a908a9088903390600401615a1d565b600060405180830381600087803b15801561248857600080fd5b505af115801561249c573d6000803e3d6000fd5b50508a516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a0823190602401602060405180830381865afa1580156124e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250d9190615518565b612517919061536c565b9350886020015184101561255d57885160208a01516040516303c4929f60e51b81526001600160a01b039092166004830152602482015260448101859052606401610691565b8851612573906001600160a01b031689866125f6565b7f23ce0616b5c94f004b302769b5b4391f577e2120c6215edc21e3eca037dc50443383858d8d600001518e602001518e8b6040516125b8989796959493929190615a97565b60405180910390a1505050979650505050505050565b60008060006125df878787876142f9565b915091506125ec816143bd565b5095945050505050565b6040516001600160a01b0383166024820152604481018290526126879084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614522565b505050565b3360009081526008602052604090205460ff166126be576040516351ee5ed560e01b8152336004820152602401610691565b42816080013510156126ef57604051634b2d84db60e01b815260808201356004820152426024820152604401610691565b6126ff6060820160408301614d2a565b6001600160a01b03166127156020830183614d2a565b6001600160a01b031603611168576127306020820182614d2a565b6040517f906c72630000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610691565b60008082600281111561278357612783615b0a565b036127c8576116568585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061460a92505050565b60018260028111156127dc576127dc615b0a565b036128455750823560601c3660006127f7856014818961537f565b9150915061280783888484611539565b61164f57868383836040517f3ced885a0000000000000000000000000000000000000000000000000000000081526004016106919493929190615b20565b60148314612889576040517f081983230000000000000000000000000000000000000000000000000000000081526014600482015260248101849052604401610691565b50823560601c600081815260046020908152604080832088845290915290205460ff16611284576040517f5f4cb138000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0382166024820152604401610691565b6001600160a01b03811660009081526006602090815260408083208584529091529020546001810161293c57604051635152abf960e01b815260048101849052602401610691565b61294d610100860160e08701615767565b156129bc576020850135612965604086013583615646565b11156129b7576129786020860186614d2a565b60408051635e6e2c1560e01b81526001600160a01b03909216600483015260208701356024830152604482018390528501356064820152608401610691565b611284565b60008111806129d357506040840135602086013514155b15611284576129786020860186614d2a565b6040516001600160a01b0380851660248301528316604482015260648101829052612a369085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161263b565b50505050565b612a4a604085013582615646565b6001600160a01b03831660009081526006602090815260408083208784528252808320849055805160808101825283815291820183905281018290526060810191909152909150612aa16060870160408801614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190615518565b815260408051600180825281830190925260009160208083019080368337019050509050856040013581600081518110612b4757612b47615502565b602002602001018181525050856020016020810190612b669190614d2a565b6001600160a01b031663cb70e273612b7e888061554a565b84336040518563ffffffff1660e01b8152600401612b9f9493929190615a1d565b600060405180830381600087803b158015612bb957600080fd5b505af1158015612bcd573d6000803e3d6000fd5b505083519250612be69150506060880160408901614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c509190615518565b612c5a919061536c565b602080830191909152670de0b6b3a7640000908701356040870135612c8360608a013584615b53565b612c8d9190615b53565b612c979190615b6a565b612ca19190615b6a565b60608201526380000000612cbb60e0880160c08901615741565b63ffffffff161115612e155760006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663f827065e612d0860e08a0160c08b01615741565b6040516001600160e01b031960e084901b16815263ffffffff919091166004820152602401606060405180830381865afa158015612d4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6e9190615b8c565b90506000612d85670de0b6b3a7640000600a615b53565b82516020850151612da09167ffffffffffffffff1690615b53565b612dab906008615b53565b612db59190615b6a565b8251909150670de0b6b3a764000090612dd89067ffffffffffffffff168261536c565b8460200151612de79190615b53565b612df19190615b6a565b602080850191909152820151612e129082610bed60608c0160408d01614d2a565b50505b806060015181602001511015612e7157612e356060870160408801614d2a565b606082015160208301516040516303c4929f60e51b81526001600160a01b03909316600484015260248301919091526044820152606401610691565b80606001518160200151612e85919061536c565b6040820181905260808601351115612ee057612ea76060870160408801614d2a565b6040808301519051636ae033dd60e01b81526001600160a01b039092166004830152608087013560248301526044820152606401610691565b606080820151612efc91859190610bed908a0160408b01614d2a565b6001600160a01b038316847f81af66102905420f059278ff929ed6b30795eb7e25505c3418616dd28e1b4da6612f3560208a018a614d2a565b612f4560608b0160408c01614d2a565b8a600001602001358b604001602001358b60400135886060015189604001518f60c0016020810190612f779190615741565b604080516001600160a01b03998a168152989097166020890152958701949094526060860192909252608085015260a08481019190915260c084019190915263ffffffff90911660e08301528901356101008201526101200160405180910390a3505050505050565b6000610cc4612fed61462e565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b3360009081526008602052604090205460ff1661305a576040516351ee5ed560e01b8152336004820152602401610691565b428160400135101561308b5760408051634b2d84db60e01b8152908201356004820152426024820152604401610691565b60005b61309882806155b2565b90508110156131895760005b6130b160208401846155b2565b9050811015613176576130c760208401846155b2565b828181106130d7576130d7615502565b6130ed9260206040909202019081019150614d2a565b6001600160a01b031661310084806155b2565b8481811061311057613110615502565b6131269260206040909202019081019150614d2a565b6001600160a01b0316036131645761313e83806155b2565b8381811061314e5761314e615502565b6127309260206040909202019081019150614d2a565b8061316e81615531565b9150506130a4565b508061318181615531565b91505061308e565b5050565b6131f6604051806101600160405280606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160008019168152602001600081525090565b6040805161016081019091528061320d87806155b2565b905067ffffffffffffffff811115613227576132276150fc565b604051908082528060200260200182016040528015613250578160200160208202803683370190505b50815260200186806020019061326691906155b2565b905067ffffffffffffffff811115613280576132806150fc565b6040519080825280602002602001820160405280156132a9578160200160208202803683370190505b5081526020016132b987806155b2565b905067ffffffffffffffff8111156132d3576132d36150fc565b6040519080825280602002602001820160405280156132fc578160200160208202803683370190505b50815260200186806020019061331291906155b2565b905067ffffffffffffffff81111561332c5761332c6150fc565b604051908082528060200260200182016040528015613355578160200160208202803683370190505b50815260200161336587806155b2565b905067ffffffffffffffff81111561337f5761337f6150fc565b6040519080825280602002602001820160405280156133a8578160200160208202803683370190505b5081526020018680602001906133be91906155b2565b905067ffffffffffffffff8111156133d8576133d86150fc565b604051908082528060200260200182016040528015613401578160200160208202803683370190505b50815260200186806020019061341791906155b2565b905067ffffffffffffffff811115613431576134316150fc565b60405190808252806020026020018201604052801561345a578160200160208202803683370190505b50815260200186806020019061347091906155b2565b905067ffffffffffffffff81111561348a5761348a6150fc565b6040519080825280602002602001820160405280156134b3578160200160208202803683370190505b5081526001600160a01b03841660208083018290526040808401889052600060609094018490529183526007815281832087845281529181902080548251818502810185019093528083529394509092909183018282801561353457602002820191906000526020600020905b815481526020019060010190808311613520575b505050506080830182905250511580159061356e5750600019816080015160008151811061356457613564615502565b6020026020010151145b1561358f57604051635152abf960e01b815260048101849052602401610691565b8060800151516000036135f0576135a685806155b2565b905067ffffffffffffffff8111156135c0576135c06150fc565b6040519080825280602002602001820160405280156135e9578160200160208202803683370190505b5060808201525b61360060c0860160a08701615767565b156137fd5760005b8160800151518110156137f75761361f86806155b2565b8281811061362f5761362f615502565b9050604002016020013585806040019061364991906155fc565b8381811061365957613659615502565b905060200201358360800151838151811061367657613676615502565b60200260200101516136889190615646565b11156137625761369886806155b2565b828181106136a8576136a8615502565b6136be9260206040909202019081019150614d2a565b6136c887806155b2565b838181106136d8576136d8615502565b90506040020160200135836080015183815181106136f8576136f8615502565b602002602001015187806040019061371091906155fc565b8581811061372057613720615502565b604051635e6e2c1560e01b81526001600160a01b0390961660048701526024860194909452506044840191909152602090910201356064820152608401610691565b600061376e87806155b2565b8381811061377e5761377e615502565b9050604002016020013586806040019061379891906155fc565b848181106137a8576137a8615502565b90506020020135670de0b6b3a76400006137c29190615b53565b6137cc9190615b6a565b90508261014001518111156137e45761014083018190525b50806137ef81615531565b915050613608565b50611284565b670de0b6b3a764000061014082015260005b8160800151518110156138b25760008260800151828151811061383457613834615502565b60200260200101511180613891575061384d86806155b2565b8281811061385d5761385d615502565b9050604002016020013585806040019061387791906155fc565b8381811061388757613887615502565b9050602002013514155b156138a05761369886806155b2565b806138aa81615531565b91505061380f565b50949350505050565b60808101516101008201516001600160a01b031660009081526007602090815260408083206101208601518452825290912082516138fe93919290910190614a21565b5060005b61390f60208501856155b2565b9050811015613a935761392560208501856155b2565b8281811061393557613935615502565b61394b9260206040909202019081019150614d2a565b8260200151828151811061396157613961615502565b6001600160a01b03909216602092830291909101820152613984908501856155b2565b8281811061399457613994615502565b90506040020160200135826060015182815181106139b4576139b4615502565b6020026020010181815250508380602001906139d091906155b2565b828181106139e0576139e0615502565b6139f69260206040909202019081019150614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015613a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a609190615518565b8260e001518281518110613a7657613a76615502565b602090810291909101015280613a8b81615531565b915050613902565b50613aa46040830160208401614d2a565b6001600160a01b031663cb70e273613abc848061554a565b613ac960408701876155fc565b336040518663ffffffff1660e01b8152600401613aea959493929190615c53565b600060405180830381600087803b158015613b0457600080fd5b505af1158015613b18573d6000803e3d6000fd5b5060009250613b2d91505060208501856155b2565b905067ffffffffffffffff811115613b4757613b476150fc565b604051908082528060200260200182016040528015613b70578160200160208202803683370190505b50905060005b613b8360208601866155b2565b9050811015613c83578260e001518181518110613ba257613ba2615502565b6020026020010151858060200190613bba91906155b2565b83818110613bca57613bca615502565b613be09260206040909202019081019150614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015613c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c4a9190615518565b613c54919061536c565b828281518110613c6657613c66615502565b602090810291909101015280613c7b81615531565b915050613b76565b5060408051606081018252600080825260208201819052918101919091526380000000613cb660a0870160808801615741565b63ffffffff161115613d6a576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663f827065e613d0160a0880160808901615741565b6040516001600160e01b031960e084901b16815263ffffffff919091166004820152602401606060405180830381865afa158015613d43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d679190615b8c565b90505b60005b613d7a60208701876155b2565b9050811015614129576380000000613d9860a0880160808901615741565b63ffffffff161115613eb1576000613db9670de0b6b3a7640000600a615b53565b836000015167ffffffffffffffff16858481518110613dda57613dda615502565b6020026020010151613dec9190615b53565b613df7906008615b53565b613e019190615b6a565b8351909150670de0b6b3a764000090613e249067ffffffffffffffff168261536c565b858481518110613e3657613e36615502565b6020026020010151613e489190615b53565b613e529190615b6a565b848381518110613e6457613e64615502565b602002602001018181525050613eaf836020015182898060200190613e8991906155b2565b86818110613e9957613e99615502565b610bed9260206040909202019081019150614d2a565b505b6000670de0b6b3a7640000613ec960208901896155b2565b84818110613ed957613ed9615502565b90506040020160200135866101400151613ef39190615b53565b613efd9190615b6a565b905080848381518110613f1257613f12615502565b60200260200101511015613fa357613f2d60208801886155b2565b83818110613f3d57613f3d615502565b613f539260206040909202019081019150614d2a565b81858481518110613f6657613f66615502565b60209081029190910101516040516303c4929f60e51b81526001600160a01b03909316600484015260248301919091526044820152606401610691565b808560a001518381518110613fba57613fba615502565b60200260200101818152505080848381518110613fd957613fd9615502565b6020026020010151613feb919061536c565b8560c00151838151811061400157614001615502565b602090810291909101015261401960808701876155fc565b8381811061402957614029615502565b905060200201358560c00151838151811061404657614046615502565b602002602001015110156140fe5761406160208801886155b2565b8381811061407157614071615502565b6140879260206040909202019081019150614d2a565b61409460808801886155fc565b848181106140a4576140a4615502565b905060200201358660c0015184815181106140c1576140c1615502565b6020908102919091010151604051636ae033dd60e01b81526001600160a01b03909316600484015260248301919091526044820152606401610691565b6101008501516141169082613e8960208b018b6155b2565b508061412181615531565b915050613d6d565b5050508061010001516001600160a01b03168161012001517fcbd6837778f636c87f1092746d97e700ff35f92362632ca761cfbbef7f5a4d2b836000015184602001518560400151866060015188806040019061418691906155fc565b8960a001518a60c001518d60800160208101906141a39190615741565b8d60a001356040516141be9a99989796959493929190615c96565b60405180910390a3505050565b6002546001600160a01b031633146142255760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610691565b565b6003805473ffffffffffffffffffffffffffffffffffffffff191690556111688161475e565b606060ff831461426757614260836147bd565b9050610cc4565b81805461427390615d44565b80601f016020809104026020016040519081016040528092919081815260200182805461429f90615d44565b80156142ec5780601f106142c1576101008083540402835291602001916142ec565b820191906000526020600020905b8154815290600101906020018083116142cf57829003601f168201915b5050505050905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561433057506000905060036143b4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614384573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166143ad576000600192509250506143b4565b9150600090505b94509492505050565b60008160048111156143d1576143d1615b0a565b036143d95750565b60018160048111156143ed576143ed615b0a565b0361443a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610691565b600281600481111561444e5761444e615b0a565b0361449b5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610691565b60038160048111156144af576144af615b0a565b036111685760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610691565b6000614577826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147fc9092919063ffffffff16565b905080516000148061459857508080602001905181019061459891906156ee565b6126875760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610691565b6000806000614619858561480b565b91509150614626816143bd565b509392505050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561468757507f000000000000000000000000000000000000000000000000000000000000000046145b156146b157507f000000000000000000000000000000000000000000000000000000000000000090565b614759604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b600280546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606060006147ca83614850565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b60606112848484600085614891565b60008082516041036148415760208301516040840151606085015160001a614835878285856142f9565b94509450505050614849565b506000905060025b9250929050565b600060ff8216601f811115610cc4576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060824710156149095760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610691565b600080866001600160a01b0316858760405161492591906154a3565b60006040518083038185875af1925050503d8060008114614962576040519150601f19603f3d011682016040523d82523d6000602084013e614967565b606091505b509150915061497887838387614983565b979650505050505050565b606083156149f25782516000036149eb576001600160a01b0385163b6149eb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610691565b5081611284565b6112848383815115614a075781518083602001fd5b8060405162461bcd60e51b81526004016106919190614e72565b828054828255906000526020600020908101928215614a5c579160200282015b82811115614a5c578251825591602001919060010190614a41565b50614a68929150614a6c565b5090565b5b80821115614a685760008155600101614a6d565b6001600160a01b038116811461116857600080fd5b8035614aa181614a81565b919050565b60008083601f840112614ab857600080fd5b50813567ffffffffffffffff811115614ad057600080fd5b60208301915083602082850101111561484957600080fd5b801515811461116857600080fd5b600080600080600060808688031215614b0e57600080fd5b8535614b1981614a81565b945060208601359350604086013567ffffffffffffffff811115614b3c57600080fd5b614b4888828901614aa6565b9094509250506060860135614b5c81614ae8565b809150509295509295909350565b60008083601f840112614b7c57600080fd5b50813567ffffffffffffffff811115614b9457600080fd5b6020830191508360208260051b850101111561484957600080fd5b600080600080600060608688031215614bc757600080fd5b853567ffffffffffffffff80821115614bdf57600080fd5b614beb89838a01614b6a565b90975095506020880135915080821115614c0457600080fd5b50614c1188828901614b6a565b9094509250506040860135614b5c81614a81565b60008060408385031215614c3857600080fd5b8235614c4381614a81565b946020939093013593505050565b60006101008284031215614c6457600080fd5b50919050565b600060408284031215614c6457600080fd5b600060c08284031215614c6457600080fd5b60008060006101408486031215614ca457600080fd5b614cae8585614c51565b925061010084013567ffffffffffffffff80821115614ccc57600080fd5b614cd887838801614c6a565b9350610120860135915080821115614cef57600080fd5b50614cfc86828701614c7c565b9150509250925092565b60006101008284031215614d1957600080fd5b614d238383614c51565b9392505050565b600060208284031215614d3c57600080fd5b8135614d2381614a81565b600060208284031215614d5957600080fd5b5035919050565b600080600060608486031215614d7557600080fd5b833567ffffffffffffffff80821115614d8d57600080fd5b614d9987838801614c7c565b94506020860135915080821115614daf57600080fd5b614dbb87838801614c6a565b93506040860135915080821115614cef57600080fd5b600080600060608486031215614de657600080fd5b8335614df181614a81565b95602085013595506040909401359392505050565b600060408284031215614e1857600080fd5b614d238383614c6a565b60005b83811015614e3d578181015183820152602001614e25565b50506000910152565b60008151808452614e5e816020860160208601614e22565b601f01601f19169290920160200192915050565b602081526000614d236020830184614e46565b600081518084526020808501945080840160005b83811015614eb557815187529582019590820190600101614e99565b509495945050505050565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201526000614efb60e0830189614e46565b8281036040840152614f0d8189614e46565b90508660608401526001600160a01b03861660808401528460a084015282810360c0840152614f3c8185614e85565b9a9950505050505050505050565b60008060008060608587031215614f6057600080fd5b8435614f6b81614a81565b935060208501359250604085013567ffffffffffffffff811115614f8e57600080fd5b614f9a87828801614aa6565b95989497509550505050565b600060208284031215614fb857600080fd5b813567ffffffffffffffff811115614fcf57600080fd5b61128484828501614c7c565b600060a08284031215614c6457600080fd5b6000806000610140848603121561500357600080fd5b61500d8585614c51565b925061010084013567ffffffffffffffff8082111561502b57600080fd5b61503787838801614c7c565b935061012086013591508082111561504e57600080fd5b50614cfc86828701614fdb565b60008060006060848603121561507057600080fd5b833567ffffffffffffffff8082111561508857600080fd5b61509487838801614c7c565b945060208601359150808211156150aa57600080fd5b6150b687838801614c7c565b9350604086013591508082111561504e57600080fd5b600080604083850312156150df57600080fd5b8235915060208301356150f181614ae8565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561513b5761513b6150fc565b604052919050565b600067ffffffffffffffff82111561515d5761515d6150fc565b5060051b60200190565b60006040828403121561517957600080fd5b6040516040810181811067ffffffffffffffff8211171561519c5761519c6150fc565b60405290508082356151ad81614a81565b8152602092830135920191909152919050565b600082601f8301126151d157600080fd5b813560206151e66151e183615143565b615112565b82815260059290921b8401810191818101908684111561520557600080fd5b8286015b8481101561522957803561521c81614a81565b8352918301918301615209565b509695505050505050565b600080600080600080600060e0888a03121561524f57600080fd5b873567ffffffffffffffff8082111561526757600080fd5b818a0191508a601f83011261527b57600080fd5b8135602061528b6151e183615143565b82815260069290921b8401810191818101908e8411156152aa57600080fd5b948201945b838610156152d3576152c18f87615167565b825282820191506040860195506152af565b9b50508b0135925050808211156152e957600080fd5b6152f58b838c016151c0565b97506153048b60408c01615167565b965061531260808b01614a96565b955060a08a013591508082111561532857600080fd5b506153358a828b01614aa6565b9094509250615348905060c08901614a96565b905092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cc457610cc4615356565b6000808585111561538f57600080fd5b8386111561539c57600080fd5b5050820193919092039150565b80356020831015610cc457600019602084900360031b1b1692915050565b600082601f8301126153d857600080fd5b813567ffffffffffffffff8111156153f2576153f26150fc565b615405601f8201601f1916602001615112565b81815284602083860101111561541a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561544c57600080fd5b833561545781614a81565b9250602084013567ffffffffffffffff8082111561547457600080fd5b615480878388016153c7565b9350604086013591508082111561549657600080fd5b50614cfc868287016153c7565b600082516154b5818460208701614e22565b9190910192915050565b8281526040602082015260006112846040830184614e46565b6000602082840312156154ea57600080fd5b81516001600160e01b031981168114614d2357600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561552a57600080fd5b5051919050565b60006001820161554357615543615356565b5060010190565b6000808335601e1984360301811261556157600080fd5b83018035915067ffffffffffffffff82111561557c57600080fd5b60200191503681900382131561484957600080fd5b6000602082840312156155a357600080fd5b813560038110614d2357600080fd5b6000808335601e198436030181126155c957600080fd5b83018035915067ffffffffffffffff8211156155e457600080fd5b6020019150600681901b360382131561484957600080fd5b6000808335601e1984360301811261561357600080fd5b83018035915067ffffffffffffffff82111561562e57600080fd5b6020019150600581901b360382131561484957600080fd5b80820180821115610cc457610cc4615356565b6000835161566b818460208801614e22565b83519083019061567f818360208801614e22565b01949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03861681528460208201526080604082015260006156da608083018587615688565b905082151560608301529695505050505050565b60006020828403121561570057600080fd5b8151614d2381614ae8565b815160009082906020808601845b8381101561573557815185529382019390820190600101615719565b50929695505050505050565b60006020828403121561575357600080fd5b813563ffffffff81168114614d2357600080fd5b60006020828403121561577957600080fd5b8135614d2381614ae8565b7f4c696d69744f72646572207769746e65737329000000000000000000000000008152600084516157bc816013850160208901614e22565b8451908301906157d3816013840160208901614e22565b84519101906157e9816013840160208801614e22565b0160130195945050505050565b6000610140615819838b5180516001600160a01b03168252602090810151910152565b60208a0151604084015260408a0151606084015261584d608084018a80516001600160a01b03168252602090810151910152565b6001600160a01b03881660c08401528660e08401528061010084015261587581840187614e46565b9050828103610120840152614f3c818587615688565b7f4d756c74694c696d69744f72646572207769746e6573732900000000000000008152600084516158c3816018850160208901614e22565b8451908301906158da816018840160208901614e22565b84519101906158f0816018840160208801614e22565b0160180195945050505050565b600081518084526020808501945080840160005b83811015614eb55761593787835180516001600160a01b03168252602090810151910152565b6040969096019590820190600101615911565b60c08152600061012082018951606060c08501528181518084526101408601915060209350838301925060005b818110156159b05761599d83855180516001600160a01b03168252602090810151910152565b9284019260409290920191600101615977565b5050828c015160e086015260408c0151610100860152848103838601526159d7818c6158fd565b925050506159f060408401896001600160a01b03169052565b8660608401528281036080840152615a088187614e46565b905082810360a0840152614f3c818587615688565b606081526000615a31606083018688615688565b8281036020840152615a438186614e85565b9150506001600160a01b038316604083015295945050505050565b600081518084526020808501945080840160005b83811015614eb55781516001600160a01b031687529582019590820190600101615a72565b60006101006001600160a01b03808c168452816020850152615abb8285018c615a5e565b91508382036040850152615acf828b614e85565b91508382036060850152615ae3828a615a5e565b978116608085015260a084019690965250509190921660c082015260e00152949350505050565b634e487b7160e01b600052602160045260246000fd5b8481526001600160a01b0384166020820152606060408201526000615b49606083018486615688565b9695505050505050565b8082028115828204841417610cc457610cc4615356565b600082615b8757634e487b7160e01b600052601260045260246000fd5b500490565b600060608284031215615b9e57600080fd5b6040516060810167ffffffffffffffff8282108183111715615bc257615bc26150fc565b81604052845191508082168214615bd857600080fd5b5081526020830151615be981614a81565b60208201526040830151615bfc81614ae8565b60408201529392505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115615c3a57600080fd5b8260051b80836020870137939093016020019392505050565b606081526000615c67606083018789615688565b8281036020840152615c7a818688615c08565b9150506001600160a01b03831660408301529695505050505050565b6000610120808352615caa8184018e615a5e565b90508281036020840152615cbe818d615a5e565b90508281036040840152615cd2818c614e85565b90508281036060840152615ce6818b614e85565b90508281036080840152615cfb81898b615c08565b905082810360a0840152615d0f8188614e85565b905082810360c0840152615d238187614e85565b63ffffffff9590951660e08401525050610100015298975050505050505050565b600181811c90821680615d5857607f821691505b602082108103614c6457634e487b7160e01b600052602260045260246000fdfe4d756c74694c696d69744f7264657228546f6b656e496e666f5b5d20696e707574732c546f6b656e496e666f5b5d206f7574707574732c75696e74323536206578706972792c75696e743235362073616c742c75696e74333220726566657272616c436f64652c626f6f6c207061727469616c6c7946696c6c61626c6529546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e74294c696d69744f7264657228546f6b656e496e666f20696e7075742c546f6b656e496e666f206f75747075742c75696e74323536206578706972792c75696e743235362073616c742c75696e74333220726566657272616c436f64652c626f6f6c207061727469616c6c7946696c6c61626c6529546f6b656e496e666f286164647265737320746f6b656e416464726573732c75696e7432353620746f6b656e416d6f756e7429a2646970667358221220f93fc380960244e11e14b61a78d7a48923f3a724e980562df529c93b2a7883e764736f6c6343000813003300000000000000000000000088de50b233052e4fb783d4f6db78cc34fea3e9fc
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806391d326b011610145578063d678b6fc116100bd578063e5440d921161008c578063eb8fb26811610071578063eb8fb26814610518578063f2fde38b1461052b578063ff247a8e1461053e57600080fd5b8063e5440d92146104f2578063e5dae17d1461050557600080fd5b8063d678b6fc146104be578063dfbc013c146104c6578063e225651a146104d9578063e30c3978146104e157600080fd5b8063adad9a2b11610114578063bba06de4116100f9578063bba06de414610490578063ce0f52d5146104a3578063ce64c997146104b657600080fd5b8063adad9a2b14610475578063b5967d011461048857600080fd5b806391d326b01461041157806398ef1ed8146104245780639ef0fbfd14610437578063aca766aa1461044a57600080fd5b8063559475e5116101d857806375c111f2116101a757806384b0196e1161018c57806384b0196e146103d25780638da5cb5b146103ed5780638f068430146103fe57600080fd5b806375c111f21461039f57806379ba5097146103ca57600080fd5b8063559475e5146103515780636467329514610364578063712c512214610377578063715018a61461039757600080fd5b8063242dcbf01161022f5780634584eff6116102145780634584eff61461032357806354cc8fc61461033657806354dd5f741461034957600080fd5b8063242dcbf0146102ed5780633e0cf5431461030057600080fd5b806316d4340114610261578063174da621146102895780631d971a4a1461029e57806321d1c55f146102cc575b600080fd5b61027461026f366004614af6565b610551565b60405190151581526020015b60405180910390f35b61029c610297366004614baf565b61090f565b005b6102746102ac366004614c25565b600460209081526000928352604080842090915290825290205460ff1681565b6102df6102da366004614c8e565b610c17565b604051908152602001610280565b6102df6102fb366004614d06565b610cb1565b61027461030e366004614d2a565b60086020526000908152604090205460ff1681565b61029c610331366004614d47565b610cca565b6102df610344366004614d60565b610d13565b6102df610efe565b6102df61035f366004614dd1565b610f5a565b61029c610372366004614d47565b610f98565b61038a610385366004614e06565b611035565b6040516102809190614e72565b61029c6110a3565b6005546103b2906001600160a01b031681565b6040516001600160a01b039091168152602001610280565b61029c6110dd565b6103da61116b565b6040516102809796959493929190614ec0565b6002546001600160a01b03166103b2565b61027461040c366004614f4a565b61120f565b6102df61041f366004614fa6565b61128c565b610274610432366004614f4a565b611539565b6102df610445366004614fed565b61165d565b6102df610458366004614c25565b600660209081526000928352604080842090915290825290205481565b6102df610483366004614d06565b61183c565b61038a611943565b61029c61049e366004614d2a565b6119b2565b61029c6104b1366004614d2a565b611a06565b6102df611a57565b6102df611a7a565b6102df6104d4366004614fa6565b611abd565b61038a611acb565b6003546001600160a01b03166103b2565b6102df61050036600461505b565b611b28565b61029c610513366004614d2a565b611fda565b61029c6105263660046150cc565b612039565b61029c610539366004614d2a565b612099565b6102df61054c366004615234565b612117565b60006001600160a01b0386163b606082602086108015906105b257507f6492649264926492649264926492649264926492649264926492649264926492878761059b60208261536c565b6105a7928a929061537f565b6105b0916153a9565b145b905080156106a457600060608882896105cc60208261536c565b926105d99392919061537f565b8101906105e69190615437565b95509092509050600085900361069d57600080836001600160a01b03168360405161061191906154a3565b6000604051808303816000865af19150503d806000811461064e576040519150601f19603f3d011682016040523d82523d6000602084013e610653565b606091505b50915091508161069a57806040517f9d0d6e2d0000000000000000000000000000000000000000000000000000000081526004016106919190614e72565b60405180910390fd5b50505b50506106de565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b80806106ea5750600083115b1561080257604051630b135d3f60e11b81526001600160a01b038a1690631626ba7e9061071d908b9086906004016154bf565b602060405180830381865afa925050508015610756575060408051601f3d908101601f19168201909252610753918101906154d8565b60015b6107be573d808015610784576040519150601f19603f3d011682016040523d82523d6000602084013e610789565b606091505b50806040517f6f2a95990000000000000000000000000000000000000000000000000000000081526004016106919190614e72565b6001600160e01b03198116630b135d3f60e11b14841580156107dd5750825b80156107e7575086155b156107f657806000526001601ffd5b94506109069350505050565b6041861461083c576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061084b602082898b61537f565b610854916153a9565b90506000610866604060208a8c61537f565b61086f916153a9565b905060008989604081811061088657610886615502565b919091013560f81c915050601b81148015906108a657508060ff16601c14155b156108dd576040517f449f5db100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8b6001600160a01b03166108f38c8386866125ce565b6001600160a01b03161496505050505050505b95945050505050565b6005546001600160a01b0316331480159061093557506002546001600160a01b03163314155b15610955576040516351ee5ed560e01b8152336004820152602401610691565b6001600160a01b0381166109a0576040517f8e4c8aa60000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610691565b8382146109d9576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b84811015610c0f5760008686838181106109f8576109f8615502565b9050602002016020810190610a0d9190614d2a565b6001600160a01b031603610af3576000826001600160a01b0316858584818110610a3957610a39615502565b9050602002013560405160006040518083038185875af1925050503d8060008114610a80576040519150601f19603f3d011682016040523d82523d6000602084013e610a85565b606091505b5050905080610aed5782858584818110610aa157610aa1615502565b6040517f1c43b9760000000000000000000000000000000000000000000000000000000081526001600160a01b0390941660048501526020029190910135602483015250604401610691565b50610bfd565b610bfd82858584818110610b0957610b09615502565b90506020020135600014610b3557858584818110610b2957610b29615502565b90506020020135610bc6565b878784818110610b4757610b47615502565b9050602002016020810190610b5c9190614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc69190615518565b888885818110610bd857610bd8615502565b9050602002016020810190610bed9190614d2a565b6001600160a01b031691906125f6565b80610c0781615531565b9150506109dc565b505050505050565b6000610c228461268c565b610c2b84610cb1565b90506000610c5282610c3d868061554a565b610c4d6040890160208a01615591565b61276e565b90506000610c62868585856128f4565b9050610c9b82610c786080870160608801614d2a565b6040870135610c8a60208b018b614d2a565b6001600160a01b03169291906129e5565b610ca88685858585612a3c565b50509392505050565b6000610cc4610cbf8361183c565b612fe0565b92915050565b33600081815260066020908152604080832085845290915280822060001990555183917f9589246bd420836dc7c4f266f2553bca3d6fee904eb0aad0a436ba3fba8fe3f991a350565b6000610d1e84613028565b610d2784611abd565b90506000610d3982610c3d868061554a565b90506000610d498685858561318d565b905060005b610d5887806155b2565b9050811015610ef257610dee83610d7260608801886155fc565b84818110610d8257610d82615502565b9050602002016020810190610d979190614d2a565b610da460408901896155fc565b85818110610db457610db4615502565b60200291909101359050610dc88b806155b2565b86818110610dd857610dd8615502565b610c8a9260206040909202019081019150614d2a565b610dfb60408601866155fc565b82818110610e0b57610e0b615502565b9050602002013582608001518281518110610e2857610e28615502565b60200260200101818151610e3c9190615646565b905250610e4987806155b2565b82818110610e5957610e59615502565b610e6f9260206040909202019081019150614d2a565b8251805183908110610e8357610e83615502565b6001600160a01b0390921660209283029190910190910152610ea587806155b2565b82818110610eb557610eb5615502565b9050604002016020013582604001518281518110610ed557610ed5615502565b602090810291909101015280610eea81615531565b915050610d4e565b50610ca88685836138bb565b6040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e9860339139604051602001610f41929190615659565b6040516020818303038152906040528051906020012081565b60076020528260005260406000206020528160005260406000208181548110610f8257600080fd5b9060005260206000200160009250925050505481565b6040805160018082528183019092526000916020808301908036833701905050905060001981600081518110610fd057610fd0615502565b60209081029190910181019190915233600090815260078252604080822085835283529020825161100392840190614a21565b50604051339083907fa8c658e479c63c75980f19e6b202df4243db8c4a36973b4d162b6ffe6cf0d69190600090a35050565b6060604051806060016040528060338152602001615e986033913980516020918201209061106590840184614d2a565b604080516020818101949094526001600160a01b03909216908201529083013560608201526080016040516020818303038152906040529050919050565b6110ab6141cb565b6040517f21afe9d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035433906001600160a01b0316811461115f5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610691565b61116881614227565b50565b60006060808280808361119e7f4f646f734c696d69744f72646572526f757465720000000000000000000000148361424d565b6111c97f3100000000000000000000000000000000000000000000000000000000000001600161424d565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b6040516316d4340160e01b815260009030906316d434019061123e9088908890889088906001906004016156b1565b6020604051808303816000875af115801561125d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128191906156ee565b90505b949350505050565b60008061129983806155b2565b905067ffffffffffffffff8111156112b3576112b36150fc565b6040519080825280602002602001820160405280156112dc578160200160208202803683370190505b50905060005b6112ec84806155b2565b90508110156113535761131d61130285806155b2565b8381811061131257611312615502565b905060400201611035565b8051906020012082828151811061133657611336615502565b60209081029190910101528061134b81615531565b9150506112e2565b50600061136360208501856155b2565b905067ffffffffffffffff81111561137d5761137d6150fc565b6040519080825280602002602001820160405280156113a6578160200160208202803683370190505b50905060005b6113b960208601866155b2565b9050811015611408576113d261130260208701876155b2565b805190602001208282815181106113eb576113eb615502565b60209081029190910101528061140081615531565b9150506113ac565b506040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e986033913960405160200161144c929190615659565b6040516020818303038152906040528051906020012082604051602001611473919061570b565b604051602081830303815290604052805190602001208260405160200161149a919061570b565b60405160208183030381529060405280519060200120866040013587606001358860800160208101906114cd9190615741565b6114dd60c08b0160a08c01615767565b6040805160208101989098528701959095526060860193909352608085019190915260a084015263ffffffff1660c0830152151560e0820152610100016040516020818303038152906040528051906020012092505050919050565b6040516316d4340160e01b815260009030906316d434019061156790889088908890889088906004016156b1565b6020604051808303816000875af19250505080156115a2575060408051601f3d908101601f1916820190925261159f918101906156ee565b60015b611656573d8080156115d0576040519150601f19603f3d011682016040523d82523d6000602084013e6115d5565b606091505b508051600181900361164857816000815181106115f4576115f4615502565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0100000000000000000000000000000000000000000000000000000000000000149250611284915050565b8060208301fd5b5050611284565b9050611284565b60006116688461268c565b60006116738561183c565b905061167e81612fe0565b9150600061169d8686856116986080890160608a01614d2a565b6128f4565b90506116ac6020850185614d2a565b6040805160a081019091526001600160a01b03919091169063137c29fe908060608101806116dd60208d018d614d2a565b6001600160a01b031681526020018a60400135815250815260200187602001358152602001876040013581525060405180604001604052808960600160208101906117289190614d2a565b6001600160a01b0316815260408a013560209091015261174e6080890160608a01614d2a565b866040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e91396040516020016117ac93929190615784565b60408051601f198184030181529190526117c960808c018c61554a565b6040518863ffffffff1660e01b81526004016117eb97969594939291906157f6565b600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b50505050610ca88686858760600160208101906118369190614d2a565b85612a3c565b60006040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e9860339139604051602001611881929190615659565b604051602081830303815290604052805190602001206118a383600001611035565b805190602001206118b684604001611035565b8051602090910120608085013560a08601356118d860e0880160c08901615741565b6118e9610100890160e08a01615767565b6040805160208101989098528701959095526060860193909352608085019190915260a084015263ffffffff1660c0830152151560e082015261010001604051602081830303815290604052805190602001209050919050565b6040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e91396040516020016119a09392919061588b565b60405160208183030381529060405281565b6119ba6141cb565b6001600160a01b038116600081815260086020526040808220805460ff19166001179055517fa2dce8c36614bedf0a7ccdd7570cfe9a7f2b13a2d778512c4204fd2e90ba99479190a250565b611a0e6141cb565b6001600160a01b038116600081815260086020526040808220805460ff19169055517f3f27d27eeec2234d4d75f7629ee5638cbbf219d246f1077f57ebedaa9c7659259190a250565b604051806060016040528060338152602001615e98603391398051906020012081565b6040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e9860339139604051602001610f41929190615659565b6000610cc4610cbf8361128c565b6040518060a0016040528060738152602001615e2560739139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e91396040516020016119a093929190615784565b6000611b3384613028565b6000611b3e8561128c565b9050611b4981612fe0565b91506000611b68868685611b636080890160608a01614d2a565b61318d565b604080516060810190915290915060009080611b8489806155b2565b905067ffffffffffffffff811115611b9e57611b9e6150fc565b604051908082528060200260200182016040528015611be357816020015b6040805180820190915260008082526020820152815260200190600190039081611bbc5790505b5081526020878101359082015260408088013591015290506000611c0788806155b2565b905067ffffffffffffffff811115611c2157611c216150fc565b604051908082528060200260200182016040528015611c6657816020015b6040805180820190915260008082526020820152815260200190600190039081611c3f5790505b50905060005b611c7689806155b2565b9050811015611ec757611c8989806155b2565b82818110611c9957611c99615502565b611caf9260206040909202019081019150614d2a565b8351805183908110611cc357611cc3615502565b60209081029190910101516001600160a01b039091169052611ce860408901896155fc565b82818110611cf857611cf8615502565b9050602002013583600001518281518110611d1557611d15615502565b6020908102919091018101510152611d3060408901896155fc565b82818110611d4057611d40615502565b9050602002013584608001518281518110611d5d57611d5d615502565b60200260200101818151611d719190615646565b905250611d7e89806155b2565b82818110611d8e57611d8e615502565b611da49260206040909202019081019150614d2a565b8451805183908110611db857611db8615502565b6001600160a01b0390921660209283029190910190910152611ddd60408901896155fc565b82818110611ded57611ded615502565b9050602002013584604001518281518110611e0a57611e0a615502565b6020908102919091010152611e2260608901896155fc565b82818110611e3257611e32615502565b9050602002016020810190611e479190614d2a565b828281518110611e5957611e59615502565b60209081029190910101516001600160a01b039091169052611e7e60408901896155fc565b82818110611e8e57611e8e615502565b90506020020135828281518110611ea757611ea7615502565b602090810291909101810151015280611ebf81615531565b915050611c6c565b50611ed56020870187614d2a565b6001600160a01b031663fe8ec1a78383611ef560808b0160608c01614d2a565b886040518060a00160405280607e8152602001615d79607e9139604051806060016040528060338152602001615e98603391396040518060600160405280602e8152602001615df7602e9139604051602001611f539392919061588b565b60408051601f19818403018152919052611f7060808e018e61554a565b6040518863ffffffff1660e01b8152600401611f92979695949392919061594a565b600060405180830381600087803b158015611fac57600080fd5b505af1158015611fc0573d6000803e3d6000fd5b50505050611fcf8888856138bb565b505050509392505050565b611fe26141cb565b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f1535fa8f7275b71050af30bf7f74391b45be7ba2b545fd28279dafe9b50f642490600090a250565b336000818152600460209081526040808320868452825291829020805460ff1916851515908117909155915191825284917f146d83fd67d3b4dab3c8bbade3b7dcd73867dc6d376b219a75a3f578f61edc9d910160405180910390a35050565b6120a16141cb565b600380546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff1990911681179091556120df6002546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6005546000906001600160a01b0316331480159061214057506002546001600160a01b03163314155b15612160576040516351ee5ed560e01b8152336004820152602401610691565b6000885167ffffffffffffffff81111561217c5761217c6150fc565b6040519080825280602002602001820160405280156121a5578160200160208202803683370190505b5090506000895167ffffffffffffffff8111156121c4576121c46150fc565b6040519080825280602002602001820160405280156121ed578160200160208202803683370190505b50905060005b8a518110156123b3578a818151811061220e5761220e615502565b60200260200101516000015182828151811061222c5761222c615502565b60200260200101906001600160a01b031690816001600160a01b0316815250508a818151811061225e5761225e615502565b602002602001015160200151600014612294578a818151811061228357612283615502565b60200260200101516020015161231a565b8181815181106122a6576122a6615502565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156122f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231a9190615518565b83828151811061232c5761232c615502565b6020026020010181815250506123a18a828151811061234d5761234d615502565b602002602001015184838151811061236757612367615502565b602002602001015184848151811061238157612381615502565b60200260200101516001600160a01b03166125f69092919063ffffffff16565b806123ab81615531565b9150506121f3565b5087516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156123fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124209190615518565b6040517fcb70e2730000000000000000000000000000000000000000000000000000000081529091506001600160a01b0386169063cb70e2739061246e908a908a9088903390600401615a1d565b600060405180830381600087803b15801561248857600080fd5b505af115801561249c573d6000803e3d6000fd5b50508a516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a0823190602401602060405180830381865afa1580156124e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250d9190615518565b612517919061536c565b9350886020015184101561255d57885160208a01516040516303c4929f60e51b81526001600160a01b039092166004830152602482015260448101859052606401610691565b8851612573906001600160a01b031689866125f6565b7f23ce0616b5c94f004b302769b5b4391f577e2120c6215edc21e3eca037dc50443383858d8d600001518e602001518e8b6040516125b8989796959493929190615a97565b60405180910390a1505050979650505050505050565b60008060006125df878787876142f9565b915091506125ec816143bd565b5095945050505050565b6040516001600160a01b0383166024820152604481018290526126879084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614522565b505050565b3360009081526008602052604090205460ff166126be576040516351ee5ed560e01b8152336004820152602401610691565b42816080013510156126ef57604051634b2d84db60e01b815260808201356004820152426024820152604401610691565b6126ff6060820160408301614d2a565b6001600160a01b03166127156020830183614d2a565b6001600160a01b031603611168576127306020820182614d2a565b6040517f906c72630000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610691565b60008082600281111561278357612783615b0a565b036127c8576116568585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061460a92505050565b60018260028111156127dc576127dc615b0a565b036128455750823560601c3660006127f7856014818961537f565b9150915061280783888484611539565b61164f57868383836040517f3ced885a0000000000000000000000000000000000000000000000000000000081526004016106919493929190615b20565b60148314612889576040517f081983230000000000000000000000000000000000000000000000000000000081526014600482015260248101849052604401610691565b50823560601c600081815260046020908152604080832088845290915290205460ff16611284576040517f5f4cb138000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0382166024820152604401610691565b6001600160a01b03811660009081526006602090815260408083208584529091529020546001810161293c57604051635152abf960e01b815260048101849052602401610691565b61294d610100860160e08701615767565b156129bc576020850135612965604086013583615646565b11156129b7576129786020860186614d2a565b60408051635e6e2c1560e01b81526001600160a01b03909216600483015260208701356024830152604482018390528501356064820152608401610691565b611284565b60008111806129d357506040840135602086013514155b15611284576129786020860186614d2a565b6040516001600160a01b0380851660248301528316604482015260648101829052612a369085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161263b565b50505050565b612a4a604085013582615646565b6001600160a01b03831660009081526006602090815260408083208784528252808320849055805160808101825283815291820183905281018290526060810191909152909150612aa16060870160408801614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190615518565b815260408051600180825281830190925260009160208083019080368337019050509050856040013581600081518110612b4757612b47615502565b602002602001018181525050856020016020810190612b669190614d2a565b6001600160a01b031663cb70e273612b7e888061554a565b84336040518563ffffffff1660e01b8152600401612b9f9493929190615a1d565b600060405180830381600087803b158015612bb957600080fd5b505af1158015612bcd573d6000803e3d6000fd5b505083519250612be69150506060880160408901614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c509190615518565b612c5a919061536c565b602080830191909152670de0b6b3a7640000908701356040870135612c8360608a013584615b53565b612c8d9190615b53565b612c979190615b6a565b612ca19190615b6a565b60608201526380000000612cbb60e0880160c08901615741565b63ffffffff161115612e155760006001600160a01b037f00000000000000000000000088de50b233052e4fb783d4f6db78cc34fea3e9fc1663f827065e612d0860e08a0160c08b01615741565b6040516001600160e01b031960e084901b16815263ffffffff919091166004820152602401606060405180830381865afa158015612d4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6e9190615b8c565b90506000612d85670de0b6b3a7640000600a615b53565b82516020850151612da09167ffffffffffffffff1690615b53565b612dab906008615b53565b612db59190615b6a565b8251909150670de0b6b3a764000090612dd89067ffffffffffffffff168261536c565b8460200151612de79190615b53565b612df19190615b6a565b602080850191909152820151612e129082610bed60608c0160408d01614d2a565b50505b806060015181602001511015612e7157612e356060870160408801614d2a565b606082015160208301516040516303c4929f60e51b81526001600160a01b03909316600484015260248301919091526044820152606401610691565b80606001518160200151612e85919061536c565b6040820181905260808601351115612ee057612ea76060870160408801614d2a565b6040808301519051636ae033dd60e01b81526001600160a01b039092166004830152608087013560248301526044820152606401610691565b606080820151612efc91859190610bed908a0160408b01614d2a565b6001600160a01b038316847f81af66102905420f059278ff929ed6b30795eb7e25505c3418616dd28e1b4da6612f3560208a018a614d2a565b612f4560608b0160408c01614d2a565b8a600001602001358b604001602001358b60400135886060015189604001518f60c0016020810190612f779190615741565b604080516001600160a01b03998a168152989097166020890152958701949094526060860192909252608085015260a08481019190915260c084019190915263ffffffff90911660e08301528901356101008201526101200160405180910390a3505050505050565b6000610cc4612fed61462e565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b3360009081526008602052604090205460ff1661305a576040516351ee5ed560e01b8152336004820152602401610691565b428160400135101561308b5760408051634b2d84db60e01b8152908201356004820152426024820152604401610691565b60005b61309882806155b2565b90508110156131895760005b6130b160208401846155b2565b9050811015613176576130c760208401846155b2565b828181106130d7576130d7615502565b6130ed9260206040909202019081019150614d2a565b6001600160a01b031661310084806155b2565b8481811061311057613110615502565b6131269260206040909202019081019150614d2a565b6001600160a01b0316036131645761313e83806155b2565b8381811061314e5761314e615502565b6127309260206040909202019081019150614d2a565b8061316e81615531565b9150506130a4565b508061318181615531565b91505061308e565b5050565b6131f6604051806101600160405280606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160008019168152602001600081525090565b6040805161016081019091528061320d87806155b2565b905067ffffffffffffffff811115613227576132276150fc565b604051908082528060200260200182016040528015613250578160200160208202803683370190505b50815260200186806020019061326691906155b2565b905067ffffffffffffffff811115613280576132806150fc565b6040519080825280602002602001820160405280156132a9578160200160208202803683370190505b5081526020016132b987806155b2565b905067ffffffffffffffff8111156132d3576132d36150fc565b6040519080825280602002602001820160405280156132fc578160200160208202803683370190505b50815260200186806020019061331291906155b2565b905067ffffffffffffffff81111561332c5761332c6150fc565b604051908082528060200260200182016040528015613355578160200160208202803683370190505b50815260200161336587806155b2565b905067ffffffffffffffff81111561337f5761337f6150fc565b6040519080825280602002602001820160405280156133a8578160200160208202803683370190505b5081526020018680602001906133be91906155b2565b905067ffffffffffffffff8111156133d8576133d86150fc565b604051908082528060200260200182016040528015613401578160200160208202803683370190505b50815260200186806020019061341791906155b2565b905067ffffffffffffffff811115613431576134316150fc565b60405190808252806020026020018201604052801561345a578160200160208202803683370190505b50815260200186806020019061347091906155b2565b905067ffffffffffffffff81111561348a5761348a6150fc565b6040519080825280602002602001820160405280156134b3578160200160208202803683370190505b5081526001600160a01b03841660208083018290526040808401889052600060609094018490529183526007815281832087845281529181902080548251818502810185019093528083529394509092909183018282801561353457602002820191906000526020600020905b815481526020019060010190808311613520575b505050506080830182905250511580159061356e5750600019816080015160008151811061356457613564615502565b6020026020010151145b1561358f57604051635152abf960e01b815260048101849052602401610691565b8060800151516000036135f0576135a685806155b2565b905067ffffffffffffffff8111156135c0576135c06150fc565b6040519080825280602002602001820160405280156135e9578160200160208202803683370190505b5060808201525b61360060c0860160a08701615767565b156137fd5760005b8160800151518110156137f75761361f86806155b2565b8281811061362f5761362f615502565b9050604002016020013585806040019061364991906155fc565b8381811061365957613659615502565b905060200201358360800151838151811061367657613676615502565b60200260200101516136889190615646565b11156137625761369886806155b2565b828181106136a8576136a8615502565b6136be9260206040909202019081019150614d2a565b6136c887806155b2565b838181106136d8576136d8615502565b90506040020160200135836080015183815181106136f8576136f8615502565b602002602001015187806040019061371091906155fc565b8581811061372057613720615502565b604051635e6e2c1560e01b81526001600160a01b0390961660048701526024860194909452506044840191909152602090910201356064820152608401610691565b600061376e87806155b2565b8381811061377e5761377e615502565b9050604002016020013586806040019061379891906155fc565b848181106137a8576137a8615502565b90506020020135670de0b6b3a76400006137c29190615b53565b6137cc9190615b6a565b90508261014001518111156137e45761014083018190525b50806137ef81615531565b915050613608565b50611284565b670de0b6b3a764000061014082015260005b8160800151518110156138b25760008260800151828151811061383457613834615502565b60200260200101511180613891575061384d86806155b2565b8281811061385d5761385d615502565b9050604002016020013585806040019061387791906155fc565b8381811061388757613887615502565b9050602002013514155b156138a05761369886806155b2565b806138aa81615531565b91505061380f565b50949350505050565b60808101516101008201516001600160a01b031660009081526007602090815260408083206101208601518452825290912082516138fe93919290910190614a21565b5060005b61390f60208501856155b2565b9050811015613a935761392560208501856155b2565b8281811061393557613935615502565b61394b9260206040909202019081019150614d2a565b8260200151828151811061396157613961615502565b6001600160a01b03909216602092830291909101820152613984908501856155b2565b8281811061399457613994615502565b90506040020160200135826060015182815181106139b4576139b4615502565b6020026020010181815250508380602001906139d091906155b2565b828181106139e0576139e0615502565b6139f69260206040909202019081019150614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015613a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a609190615518565b8260e001518281518110613a7657613a76615502565b602090810291909101015280613a8b81615531565b915050613902565b50613aa46040830160208401614d2a565b6001600160a01b031663cb70e273613abc848061554a565b613ac960408701876155fc565b336040518663ffffffff1660e01b8152600401613aea959493929190615c53565b600060405180830381600087803b158015613b0457600080fd5b505af1158015613b18573d6000803e3d6000fd5b5060009250613b2d91505060208501856155b2565b905067ffffffffffffffff811115613b4757613b476150fc565b604051908082528060200260200182016040528015613b70578160200160208202803683370190505b50905060005b613b8360208601866155b2565b9050811015613c83578260e001518181518110613ba257613ba2615502565b6020026020010151858060200190613bba91906155b2565b83818110613bca57613bca615502565b613be09260206040909202019081019150614d2a565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015613c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c4a9190615518565b613c54919061536c565b828281518110613c6657613c66615502565b602090810291909101015280613c7b81615531565b915050613b76565b5060408051606081018252600080825260208201819052918101919091526380000000613cb660a0870160808801615741565b63ffffffff161115613d6a576001600160a01b037f00000000000000000000000088de50b233052e4fb783d4f6db78cc34fea3e9fc1663f827065e613d0160a0880160808901615741565b6040516001600160e01b031960e084901b16815263ffffffff919091166004820152602401606060405180830381865afa158015613d43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d679190615b8c565b90505b60005b613d7a60208701876155b2565b9050811015614129576380000000613d9860a0880160808901615741565b63ffffffff161115613eb1576000613db9670de0b6b3a7640000600a615b53565b836000015167ffffffffffffffff16858481518110613dda57613dda615502565b6020026020010151613dec9190615b53565b613df7906008615b53565b613e019190615b6a565b8351909150670de0b6b3a764000090613e249067ffffffffffffffff168261536c565b858481518110613e3657613e36615502565b6020026020010151613e489190615b53565b613e529190615b6a565b848381518110613e6457613e64615502565b602002602001018181525050613eaf836020015182898060200190613e8991906155b2565b86818110613e9957613e99615502565b610bed9260206040909202019081019150614d2a565b505b6000670de0b6b3a7640000613ec960208901896155b2565b84818110613ed957613ed9615502565b90506040020160200135866101400151613ef39190615b53565b613efd9190615b6a565b905080848381518110613f1257613f12615502565b60200260200101511015613fa357613f2d60208801886155b2565b83818110613f3d57613f3d615502565b613f539260206040909202019081019150614d2a565b81858481518110613f6657613f66615502565b60209081029190910101516040516303c4929f60e51b81526001600160a01b03909316600484015260248301919091526044820152606401610691565b808560a001518381518110613fba57613fba615502565b60200260200101818152505080848381518110613fd957613fd9615502565b6020026020010151613feb919061536c565b8560c00151838151811061400157614001615502565b602090810291909101015261401960808701876155fc565b8381811061402957614029615502565b905060200201358560c00151838151811061404657614046615502565b602002602001015110156140fe5761406160208801886155b2565b8381811061407157614071615502565b6140879260206040909202019081019150614d2a565b61409460808801886155fc565b848181106140a4576140a4615502565b905060200201358660c0015184815181106140c1576140c1615502565b6020908102919091010151604051636ae033dd60e01b81526001600160a01b03909316600484015260248301919091526044820152606401610691565b6101008501516141169082613e8960208b018b6155b2565b508061412181615531565b915050613d6d565b5050508061010001516001600160a01b03168161012001517fcbd6837778f636c87f1092746d97e700ff35f92362632ca761cfbbef7f5a4d2b836000015184602001518560400151866060015188806040019061418691906155fc565b8960a001518a60c001518d60800160208101906141a39190615741565b8d60a001356040516141be9a99989796959493929190615c96565b60405180910390a3505050565b6002546001600160a01b031633146142255760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610691565b565b6003805473ffffffffffffffffffffffffffffffffffffffff191690556111688161475e565b606060ff831461426757614260836147bd565b9050610cc4565b81805461427390615d44565b80601f016020809104026020016040519081016040528092919081815260200182805461429f90615d44565b80156142ec5780601f106142c1576101008083540402835291602001916142ec565b820191906000526020600020905b8154815290600101906020018083116142cf57829003601f168201915b5050505050905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561433057506000905060036143b4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614384573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166143ad576000600192509250506143b4565b9150600090505b94509492505050565b60008160048111156143d1576143d1615b0a565b036143d95750565b60018160048111156143ed576143ed615b0a565b0361443a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610691565b600281600481111561444e5761444e615b0a565b0361449b5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610691565b60038160048111156144af576144af615b0a565b036111685760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610691565b6000614577826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147fc9092919063ffffffff16565b905080516000148061459857508080602001905181019061459891906156ee565b6126875760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610691565b6000806000614619858561480b565b91509150614626816143bd565b509392505050565b6000306001600160a01b037f000000000000000000000000d10634297961fea132ac7b6e7451bc4e5b17359b1614801561468757507f000000000000000000000000000000000000000000000000000000000000a86a46145b156146b157507f2516fe8370476742d626db10ceacde688a3a33e7fb7d1c889c642cdfbfc45a1890565b614759604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f68a60f4c048ebe044c5ffb48fa4c9302cad285cd2f62aa2c4df2be787ddc79ea918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b600280546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606060006147ca83614850565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b60606112848484600085614891565b60008082516041036148415760208301516040840151606085015160001a614835878285856142f9565b94509450505050614849565b506000905060025b9250929050565b600060ff8216601f811115610cc4576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060824710156149095760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610691565b600080866001600160a01b0316858760405161492591906154a3565b60006040518083038185875af1925050503d8060008114614962576040519150601f19603f3d011682016040523d82523d6000602084013e614967565b606091505b509150915061497887838387614983565b979650505050505050565b606083156149f25782516000036149eb576001600160a01b0385163b6149eb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610691565b5081611284565b6112848383815115614a075781518083602001fd5b8060405162461bcd60e51b81526004016106919190614e72565b828054828255906000526020600020908101928215614a5c579160200282015b82811115614a5c578251825591602001919060010190614a41565b50614a68929150614a6c565b5090565b5b80821115614a685760008155600101614a6d565b6001600160a01b038116811461116857600080fd5b8035614aa181614a81565b919050565b60008083601f840112614ab857600080fd5b50813567ffffffffffffffff811115614ad057600080fd5b60208301915083602082850101111561484957600080fd5b801515811461116857600080fd5b600080600080600060808688031215614b0e57600080fd5b8535614b1981614a81565b945060208601359350604086013567ffffffffffffffff811115614b3c57600080fd5b614b4888828901614aa6565b9094509250506060860135614b5c81614ae8565b809150509295509295909350565b60008083601f840112614b7c57600080fd5b50813567ffffffffffffffff811115614b9457600080fd5b6020830191508360208260051b850101111561484957600080fd5b600080600080600060608688031215614bc757600080fd5b853567ffffffffffffffff80821115614bdf57600080fd5b614beb89838a01614b6a565b90975095506020880135915080821115614c0457600080fd5b50614c1188828901614b6a565b9094509250506040860135614b5c81614a81565b60008060408385031215614c3857600080fd5b8235614c4381614a81565b946020939093013593505050565b60006101008284031215614c6457600080fd5b50919050565b600060408284031215614c6457600080fd5b600060c08284031215614c6457600080fd5b60008060006101408486031215614ca457600080fd5b614cae8585614c51565b925061010084013567ffffffffffffffff80821115614ccc57600080fd5b614cd887838801614c6a565b9350610120860135915080821115614cef57600080fd5b50614cfc86828701614c7c565b9150509250925092565b60006101008284031215614d1957600080fd5b614d238383614c51565b9392505050565b600060208284031215614d3c57600080fd5b8135614d2381614a81565b600060208284031215614d5957600080fd5b5035919050565b600080600060608486031215614d7557600080fd5b833567ffffffffffffffff80821115614d8d57600080fd5b614d9987838801614c7c565b94506020860135915080821115614daf57600080fd5b614dbb87838801614c6a565b93506040860135915080821115614cef57600080fd5b600080600060608486031215614de657600080fd5b8335614df181614a81565b95602085013595506040909401359392505050565b600060408284031215614e1857600080fd5b614d238383614c6a565b60005b83811015614e3d578181015183820152602001614e25565b50506000910152565b60008151808452614e5e816020860160208601614e22565b601f01601f19169290920160200192915050565b602081526000614d236020830184614e46565b600081518084526020808501945080840160005b83811015614eb557815187529582019590820190600101614e99565b509495945050505050565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201526000614efb60e0830189614e46565b8281036040840152614f0d8189614e46565b90508660608401526001600160a01b03861660808401528460a084015282810360c0840152614f3c8185614e85565b9a9950505050505050505050565b60008060008060608587031215614f6057600080fd5b8435614f6b81614a81565b935060208501359250604085013567ffffffffffffffff811115614f8e57600080fd5b614f9a87828801614aa6565b95989497509550505050565b600060208284031215614fb857600080fd5b813567ffffffffffffffff811115614fcf57600080fd5b61128484828501614c7c565b600060a08284031215614c6457600080fd5b6000806000610140848603121561500357600080fd5b61500d8585614c51565b925061010084013567ffffffffffffffff8082111561502b57600080fd5b61503787838801614c7c565b935061012086013591508082111561504e57600080fd5b50614cfc86828701614fdb565b60008060006060848603121561507057600080fd5b833567ffffffffffffffff8082111561508857600080fd5b61509487838801614c7c565b945060208601359150808211156150aa57600080fd5b6150b687838801614c7c565b9350604086013591508082111561504e57600080fd5b600080604083850312156150df57600080fd5b8235915060208301356150f181614ae8565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561513b5761513b6150fc565b604052919050565b600067ffffffffffffffff82111561515d5761515d6150fc565b5060051b60200190565b60006040828403121561517957600080fd5b6040516040810181811067ffffffffffffffff8211171561519c5761519c6150fc565b60405290508082356151ad81614a81565b8152602092830135920191909152919050565b600082601f8301126151d157600080fd5b813560206151e66151e183615143565b615112565b82815260059290921b8401810191818101908684111561520557600080fd5b8286015b8481101561522957803561521c81614a81565b8352918301918301615209565b509695505050505050565b600080600080600080600060e0888a03121561524f57600080fd5b873567ffffffffffffffff8082111561526757600080fd5b818a0191508a601f83011261527b57600080fd5b8135602061528b6151e183615143565b82815260069290921b8401810191818101908e8411156152aa57600080fd5b948201945b838610156152d3576152c18f87615167565b825282820191506040860195506152af565b9b50508b0135925050808211156152e957600080fd5b6152f58b838c016151c0565b97506153048b60408c01615167565b965061531260808b01614a96565b955060a08a013591508082111561532857600080fd5b506153358a828b01614aa6565b9094509250615348905060c08901614a96565b905092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cc457610cc4615356565b6000808585111561538f57600080fd5b8386111561539c57600080fd5b5050820193919092039150565b80356020831015610cc457600019602084900360031b1b1692915050565b600082601f8301126153d857600080fd5b813567ffffffffffffffff8111156153f2576153f26150fc565b615405601f8201601f1916602001615112565b81815284602083860101111561541a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561544c57600080fd5b833561545781614a81565b9250602084013567ffffffffffffffff8082111561547457600080fd5b615480878388016153c7565b9350604086013591508082111561549657600080fd5b50614cfc868287016153c7565b600082516154b5818460208701614e22565b9190910192915050565b8281526040602082015260006112846040830184614e46565b6000602082840312156154ea57600080fd5b81516001600160e01b031981168114614d2357600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561552a57600080fd5b5051919050565b60006001820161554357615543615356565b5060010190565b6000808335601e1984360301811261556157600080fd5b83018035915067ffffffffffffffff82111561557c57600080fd5b60200191503681900382131561484957600080fd5b6000602082840312156155a357600080fd5b813560038110614d2357600080fd5b6000808335601e198436030181126155c957600080fd5b83018035915067ffffffffffffffff8211156155e457600080fd5b6020019150600681901b360382131561484957600080fd5b6000808335601e1984360301811261561357600080fd5b83018035915067ffffffffffffffff82111561562e57600080fd5b6020019150600581901b360382131561484957600080fd5b80820180821115610cc457610cc4615356565b6000835161566b818460208801614e22565b83519083019061567f818360208801614e22565b01949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03861681528460208201526080604082015260006156da608083018587615688565b905082151560608301529695505050505050565b60006020828403121561570057600080fd5b8151614d2381614ae8565b815160009082906020808601845b8381101561573557815185529382019390820190600101615719565b50929695505050505050565b60006020828403121561575357600080fd5b813563ffffffff81168114614d2357600080fd5b60006020828403121561577957600080fd5b8135614d2381614ae8565b7f4c696d69744f72646572207769746e65737329000000000000000000000000008152600084516157bc816013850160208901614e22565b8451908301906157d3816013840160208901614e22565b84519101906157e9816013840160208801614e22565b0160130195945050505050565b6000610140615819838b5180516001600160a01b03168252602090810151910152565b60208a0151604084015260408a0151606084015261584d608084018a80516001600160a01b03168252602090810151910152565b6001600160a01b03881660c08401528660e08401528061010084015261587581840187614e46565b9050828103610120840152614f3c818587615688565b7f4d756c74694c696d69744f72646572207769746e6573732900000000000000008152600084516158c3816018850160208901614e22565b8451908301906158da816018840160208901614e22565b84519101906158f0816018840160208801614e22565b0160180195945050505050565b600081518084526020808501945080840160005b83811015614eb55761593787835180516001600160a01b03168252602090810151910152565b6040969096019590820190600101615911565b60c08152600061012082018951606060c08501528181518084526101408601915060209350838301925060005b818110156159b05761599d83855180516001600160a01b03168252602090810151910152565b9284019260409290920191600101615977565b5050828c015160e086015260408c0151610100860152848103838601526159d7818c6158fd565b925050506159f060408401896001600160a01b03169052565b8660608401528281036080840152615a088187614e46565b905082810360a0840152614f3c818587615688565b606081526000615a31606083018688615688565b8281036020840152615a438186614e85565b9150506001600160a01b038316604083015295945050505050565b600081518084526020808501945080840160005b83811015614eb55781516001600160a01b031687529582019590820190600101615a72565b60006101006001600160a01b03808c168452816020850152615abb8285018c615a5e565b91508382036040850152615acf828b614e85565b91508382036060850152615ae3828a615a5e565b978116608085015260a084019690965250509190921660c082015260e00152949350505050565b634e487b7160e01b600052602160045260246000fd5b8481526001600160a01b0384166020820152606060408201526000615b49606083018486615688565b9695505050505050565b8082028115828204841417610cc457610cc4615356565b600082615b8757634e487b7160e01b600052601260045260246000fd5b500490565b600060608284031215615b9e57600080fd5b6040516060810167ffffffffffffffff8282108183111715615bc257615bc26150fc565b81604052845191508082168214615bd857600080fd5b5081526020830151615be981614a81565b60208201526040830151615bfc81614ae8565b60408201529392505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115615c3a57600080fd5b8260051b80836020870137939093016020019392505050565b606081526000615c67606083018789615688565b8281036020840152615c7a818688615c08565b9150506001600160a01b03831660408301529695505050505050565b6000610120808352615caa8184018e615a5e565b90508281036020840152615cbe818d615a5e565b90508281036040840152615cd2818c614e85565b90508281036060840152615ce6818b614e85565b90508281036080840152615cfb81898b615c08565b905082810360a0840152615d0f8188614e85565b905082810360c0840152615d238187614e85565b63ffffffff9590951660e08401525050610100015298975050505050505050565b600181811c90821680615d5857607f821691505b602082108103614c6457634e487b7160e01b600052602260045260246000fdfe4d756c74694c696d69744f7264657228546f6b656e496e666f5b5d20696e707574732c546f6b656e496e666f5b5d206f7574707574732c75696e74323536206578706972792c75696e743235362073616c742c75696e74333220726566657272616c436f64652c626f6f6c207061727469616c6c7946696c6c61626c6529546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e74294c696d69744f7264657228546f6b656e496e666f20696e7075742c546f6b656e496e666f206f75747075742c75696e74323536206578706972792c75696e743235362073616c742c75696e74333220726566657272616c436f64652c626f6f6c207061727469616c6c7946696c6c61626c6529546f6b656e496e666f286164647265737320746f6b656e416464726573732c75696e7432353620746f6b656e416d6f756e7429a2646970667358221220f93fc380960244e11e14b61a78d7a48923f3a724e980562df529c93b2a7883e764736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000088de50b233052e4fb783d4f6db78cc34fea3e9fc
-----Decoded View---------------
Arg [0] : _odosRouterV2 (address): 0x88de50B233052e4Fb783d4F6db78Cc34fEa3e9FC
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000088de50b233052e4fb783d4f6db78cc34fea3e9fc
Deployed Bytecode Sourcemap
93547:34118:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77452:2440;;;;;;:::i;:::-;;:::i;:::-;;;1705:14:1;;1698:22;1680:41;;1668:2;1653:18;77452:2440:0;;;;;;;;110825:831;;;;;;:::i;:::-;;:::i;:::-;;81604:95;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;101194:867;;;;;;:::i;:::-;;:::i;:::-;;;4755:25:1;;;4743:2;4728:18;101194:867:0;4609:177:1;114802:169:0;;;;;;:::i;:::-;;:::i;98847:46::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;107552:191;;;;;;:::i;:::-;;:::i;103985:1172::-;;;;;;:::i;:::-;;:::i;100256:139::-;;;:::i;98698:108::-;;;;;;:::i;:::-;;:::i;107894:306::-;;;;;;:::i;:::-;;:::i;112836:210::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;112303:100::-;;;:::i;94198:32::-;;;;;-1:-1:-1;;;;;94198:32:0;;;;;;-1:-1:-1;;;;;8240:55:1;;;8222:74;;8210:2;8195:18;94198:32:0;8076:226:1;50775:216:0;;;:::i;75939:657::-;;;:::i;:::-;;;;;;;;;;;;;:::i;47619:87::-;47692:6;;-1:-1:-1;;;;;47692:6:0;47619:87;;79898:199;;;;;;:::i;:::-;;:::i;113792:875::-;;;;;;:::i;:::-;;:::i;80103:664::-;;;;;;:::i;:::-;;:::i;102357:1306::-;;;;;;:::i;:::-;;:::i;98547:100::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;113200:428;;;;;;:::i;:::-;;:::i;99893:226::-;;;:::i;111781:144::-;;;;;;:::i;:::-;;:::i;112056:150::-;;;;;;:::i;:::-;;:::i;100170:79::-;;;:::i;100402:151::-;;;:::i;115104:194::-;;;;;;:::i;:::-;;:::i;99677:209::-;;;:::i;49863:101::-;49943:13;;-1:-1:-1;;;;;49943:13:0;49863:101;;105453:1946;;;;;;:::i;:::-;;:::i;112540:161::-;;;;;;:::i;:::-;;:::i;84571:213::-;;;;;;:::i;:::-;;:::i;50163:181::-;;;;;;:::i;:::-;;:::i;108768:1800::-;;;;;;:::i;:::-;;:::i;77452:2440::-;77599:4;-1:-1:-1;;;;;77638:28:0;;;77673:26;77599:4;78223:2;78202:23;;;;;:121;;-1:-1:-1;77322:66:0;78244:10;;78255:20;78273:2;78244:10;78255:20;:::i;:::-;78244:50;;78276:10;;78244:50;;:::i;:::-;78236:59;;;:::i;:::-;:87;78202:121;78178:145;;78334:16;78330:522;;;78361:22;78392:28;78491:10;78361:22;78491:10;78504:20;78522:2;78491:10;78504:20;:::i;:::-;78491:34;;;;;;;:::i;:::-;78480:71;;;;;;;:::i;:::-;78429:122;-1:-1:-1;78429:122:0;;-1:-1:-1;78429:122:0;-1:-1:-1;78585:1:0;78566:20;;;78562:234;;78660:12;78674:16;78694:14;-1:-1:-1;;;;;78694:19:0;78714:15;78694:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78659:71;;;;78746:7;78741:45;;78782:3;78762:24;;;;;;;;;;;:::i;:::-;;;;;;;;78741:45;78588:208;;78562:234;78352:451;;78330:522;;;78834:10;;78818:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78818:26:0;;-1:-1:-1;;;;78330:522:0;78898:16;:39;;;;78936:1;78918:15;:19;78898:39;78894:618;;;78952:62;;-1:-1:-1;;;78952:62:0;;-1:-1:-1;;;;;78952:40:0;;;;;:62;;78993:5;;79000:13;;78952:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;78952:62:0;;;;;;;;-1:-1:-1;;78952:62:0;;;;;;;;;;;;:::i;:::-;;;78948:557;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79498:3;79484:18;;;;;;;;;;;:::i;78948:557::-;-1:-1:-1;;;;;;79069:29:0;;-1:-1:-1;;;79069:29:0;79115:20;;:40;;;;;79139:16;79115:40;:61;;;;;79160:16;79159:17;79115:61;79111:302;;;79355:7;79352:1;79345:18;79387:1;79383:2;79376:13;79111:302;79432:7;-1:-1:-1;79425:14:0;;-1:-1:-1;;;;79425:14:0;78948:557;79576:2;79555:23;;79551:77;;79596:24;;;;;;;;;;;;;;79551:77;79634:9;79654:16;79667:2;79634:9;79654:10;;:16;:::i;:::-;79646:25;;;:::i;:::-;79634:37;-1:-1:-1;79678:9:0;79698:17;79712:2;79709;79698:10;;:17;:::i;:::-;79690:26;;;:::i;:::-;79678:38;;79723:7;79739:10;;79750:2;79739:14;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;79770:2:0;79765:7;;;;;:18;;;79776:1;:7;;79781:2;79776:7;;79765:18;79761:72;;;79801:24;;;;;;;;;;;;;;79761:72;79879:7;-1:-1:-1;;;;;79846:40:0;:29;79860:5;79867:1;79870;79873;79846:13;:29::i;:::-;-1:-1:-1;;;;;79846:40:0;;79839:47;;;;;;;;77452:2440;;;;;;;;:::o;110825:831::-;110983:17;;-1:-1:-1;;;;;110983:17:0;110969:10;:31;;;;:56;;-1:-1:-1;47692:6:0;;-1:-1:-1;;;;;47692:6:0;111004:10;:21;;110969:56;110965:115;;;111043:29;;-1:-1:-1;;;111043:29:0;;111061:10;111043:29;;;8222:74:1;8195:18;;111043:29:0;8076:226:1;110965:115:0;-1:-1:-1;;;;;111090:18:0;;111086:68;;111126:20;;;;;-1:-1:-1;;;;;8240:55:1;;111126:20:0;;;8222:74:1;8195:18;;111126:20:0;8076:226:1;111086:68:0;111164:31;;;111160:62;;111204:18;;;;;;;;;;;;;;111160:62;111234:9;111229:422;111249:17;;;111229:422;;;93860:1;111286:6;;111293:1;111286:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;111286:17:0;;111282:362;;111317:12;111342:4;-1:-1:-1;;;;;111334:18:0;111360:7;;111368:1;111360:10;;;;;;;:::i;:::-;;;;;;;111334:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111316:59;;;111391:7;111386:78;;111435:4;111441:7;;111449:1;111441:10;;;;;;;:::i;:::-;111420:32;;;;;-1:-1:-1;;;;;20522:55:1;;;111420:32:0;;;20504:74:1;111441:10:0;;;;;;;20594:18:1;;;20587:34;-1:-1:-1;20477:18:1;;111420:32:0;20330:297:1;111386:78:0;111305:168;111282:362;;;111490:144;111533:4;111550:7;;111558:1;111550:10;;;;;;;:::i;:::-;;;;;;;111564:1;111550:15;:73;;111613:7;;111621:1;111613:10;;;;;;;:::i;:::-;;;;;;;111550:73;;;111575:6;;111582:1;111575:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;111568:42;;-1:-1:-1;;;111568:42:0;;111604:4;111568:42;;;8222:74:1;-1:-1:-1;;;;;111568:27:0;;;;;;;8195:18:1;;111568:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111497:6;;111504:1;111497:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;111490:30:0;;:144;:30;:144::i;:::-;111268:3;;;;:::i;:::-;;;;111229:422;;;;110825:831;;;;;:::o;101194:867::-;101355:17;101403:24;101421:5;101403:17;:24::i;:::-;101474;101492:5;101474:17;:24::i;:::-;101462:36;-1:-1:-1;101564:18:0;101585:82;101462:36;101619:19;:9;;:19;:::i;:::-;101640:26;;;;;;;;:::i;:::-;101585:22;:82::i;:::-;101564:103;;101716:20;101739:55;101756:5;101763:7;101772:9;101783:10;101739:16;:55::i;:::-;101716:78;-1:-1:-1;101847:107:0;101897:10;101909:21;;;;;;;;:::i;:::-;101932;;;;101854:24;;;;:5;:24;:::i;:::-;-1:-1:-1;;;;;101847:49:0;;:107;;:49;:107::i;:::-;101987:68;102003:5;102010:7;102019:9;102030:10;102042:12;101987:15;:68::i;:::-;101377:684;;101194:867;;;;;:::o;114802:169::-;114886:12;114917:48;114934:30;114958:5;114934:23;:30::i;:::-;114917:16;:48::i;:::-;114910:55;114802:169;-1:-1:-1;;114802:169:0:o;107552:191::-;107641:10;107629:23;;;;:11;:23;;;;;;;;:34;;;;;;;;;-1:-1:-1;;107629:54:0;;107695:42;107653:9;;107695:42;;;107552:191;:::o;103985:1172::-;104161:17;104209:24;104227:5;104209:17;:24::i;:::-;104280:29;104303:5;104280:22;:29::i;:::-;104268:41;-1:-1:-1;104375:18:0;104396:82;104268:41;104430:19;:9;;:19;:::i;104396:82::-;104375:103;;104527:35;104565:60;104587:5;104594:7;104603:9;104614:10;104565:21;:60::i;:::-;104527:98;;104699:9;104694:405;104718:12;:5;;:12;:::i;:::-;:19;;104714:1;:23;104694:405;;;104753:119;104807:10;104819:22;;;;:7;:22;:::i;:::-;104842:1;104819:25;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;104846:22;;;;:7;:22;:::i;:::-;104869:1;104846:25;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;104760:12:0;:5;;:12;:::i;:::-;104773:1;104760:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;104760:28:0;:::i;104753:119::-;104939:22;;;;:7;:22;:::i;:::-;104962:1;104939:25;;;;;;;:::i;:::-;;;;;;;104912:6;:20;;;104933:1;104912:23;;;;;;;;:::i;:::-;;;;;;:52;;;;;;;:::i;:::-;;;-1:-1:-1;104997:12:0;:5;;:12;:::i;:::-;105010:1;104997:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;104997:28:0;:::i;:::-;104973:18;;:21;;104992:1;;104973:21;;;;;;:::i;:::-;-1:-1:-1;;;;;104973:52:0;;;:21;;;;;;;;;;;:52;105064:12;:5;;:12;:::i;:::-;105077:1;105064:15;;;;;;;:::i;:::-;;;;;;:27;;;105034:6;:24;;;105059:1;105034:27;;;;;;;;:::i;:::-;;;;;;;;;;:57;104739:3;;;;:::i;:::-;;;;104694:405;;;;105107:44;105128:5;105135:7;105144:6;105107:20;:44::i;100256:139::-;100336:23;;;;;;;;;;;;;;;;;100367:22;;;;;;;;;;;;;;;;;100313:81;;;;;;;;;:::i;:::-;;;;;;;;;;;;;100303:92;;;;;;100256:139;:::o;98698:108::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;107894:306::-;108010:16;;;108024:1;108010:16;;;;;;;;;107976:31;;108010:16;;;;;;;;;;;-1:-1:-1;108010:16:0;107976:50;;-1:-1:-1;;108033:14:0;108048:1;108033:17;;;;;;;;:::i;:::-;;;;;;;;;;;:37;;;;108094:10;108077:28;;;;:16;:28;;;;;;:39;;;;;;;:56;;;;;;;;:::i;:::-;-1:-1:-1;108147:47:0;;108183:10;;108172:9;;108147:47;;;;;107969:231;107894:306;:::o;112836:210::-;112931:12;100226:22;;;;;;;;;;;;;;;;;100216:33;;;;;;;;112994:22;;;;:9;:22;:::i;:::-;112962:78;;;113018:21;112962:78;;;24286:25:1;;;;-1:-1:-1;;;;;24347:55:1;;;24327:18;;;24320:83;113018:21:0;;;;24419:18:1;;;24412:34;24259:18;;112962:78:0;;;;;;;;;;;;112955:85;;112836:210;;;:::o;112303:100::-;47505:13;:11;:13::i;:::-;112377:20:::1;;;;;;;;;;;;;;50775:216:::0;49943:13;;13058:10;;-1:-1:-1;;;;;49943:13:0;50876:24;;50868:78;;;;-1:-1:-1;;;50868:78:0;;24659:2:1;50868:78:0;;;24641:21:1;24698:2;24678:18;;;24671:30;24737:34;24717:18;;;24710:62;24808:11;24788:18;;;24781:39;24837:19;;50868:78:0;24457:405:1;50868:78:0;50957:26;50976:6;50957:18;:26::i;:::-;50817:174;50775:216::o;75939:657::-;76060:13;76088:18;;76060:13;;;76088:18;76362:41;:5;76060:13;76362:26;:41::i;:::-;76418:47;:8;76448:16;76418:29;:47::i;:::-;76561:16;;;76544:1;76561:16;;;;;;;;;76309:279;;;;-1:-1:-1;76309:279:0;;-1:-1:-1;76480:13:0;;-1:-1:-1;76516:4:0;;-1:-1:-1;76544:1:0;-1:-1:-1;76561:16:0;-1:-1:-1;76309:279:0;-1:-1:-1;75939:657:0:o;79898:199::-;80038:53;;-1:-1:-1;;;80038:53:0;;80015:4;;80038;;:19;;:53;;80058:7;;80067:5;;80074:10;;;;80086:4;;80038:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80031:60;;79898:199;;;;;;;:::o;113792:875::-;113902:18;;113979:12;:5;;:12;:::i;:::-;:19;;113965:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;113965:34:0;;113932:67;;114011:9;114006:129;114030:12;:5;;:12;:::i;:::-;:19;;114026:1;:23;114006:129;;;114094:32;114110:12;:5;;:12;:::i;:::-;114123:1;114110:15;;;;;;;:::i;:::-;;;;;;114094;:32::i;:::-;114084:43;;;;;;114065:13;114079:1;114065:16;;;;;;;;:::i;:::-;;;;;;;;;;:62;114051:3;;;;:::i;:::-;;;;114006:129;;;-1:-1:-1;114141:31:0;114189:13;;;;:5;:13;:::i;:::-;:20;;114175:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;114175:35:0;;114141:69;;114222:9;114217:132;114241:13;;;;:5;:13;:::i;:::-;:20;;114237:1;:24;114217:132;;;114307:33;114323:13;;;;:5;:13;:::i;114307:33::-;114297:44;;;;;;114277:14;114292:1;114277:17;;;;;;;;:::i;:::-;;;;;;;;;;:64;114263:3;;;;:::i;:::-;;;;114217:132;;;;100488:29;;;;;;;;;;;;;;;;;100525:22;;;;;;;;;;;;;;;;;100465:87;;;;;;;;;:::i;:::-;;;;;;;;;;;;;100455:98;;;;;;114469:13;114452:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;114442:42;;;;;;114522:14;114505:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;114495:43;;;;;;114549:5;:12;;;114572:5;:10;;;114593:5;:18;;;;;;;;;;:::i;:::-;114622:23;;;;;;;;:::i;:::-;114384:270;;;;;;27293:25:1;;;;27334:18;;27327:34;;;;27377:18;;;27370:34;;;;27420:18;;;27413:34;;;;27463:19;;;27456:35;27540:10;27528:23;27507:19;;;27500:52;27596:14;27589:22;27568:19;;;27561:51;27265:19;;114384:270:0;;;;;;;;;;;;114364:297;;;;;;114357:304;;;;113792:875;;;:::o;80103:664::-;80223:54;;-1:-1:-1;;;80223:54:0;;80203:4;;80223;;:19;;:54;;80243:7;;80252:5;;80259:10;;;;80203:4;;80223:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;80223:54:0;;;;;;;;-1:-1:-1;;80223:54:0;;;;;;;;;;;;:::i;:::-;;;80219:543;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;80507:12:0;;80539:1;80532:8;;;80528:227;;80549:5;80555:1;80549:8;;;;;;;;:::i;:::-;;;;;;;;:16;;;-1:-1:-1;80542:23:0;;-1:-1:-1;;80542:23:0;80528:227;80749:3;80742:4;80735:5;80731:16;80724:29;80722:33;80353:409;80326:436;80219:543;;;80310:7;-1:-1:-1;80303:14:0;;102357:1306;102525:17;102573:24;102591:5;102573:17;:24::i;:::-;102632:23;102658:30;102682:5;102658:23;:30::i;:::-;102632:56;;102707:33;102724:15;102707:16;:33::i;:::-;102695:45;-1:-1:-1;102857:20:0;102880:63;102897:5;102904:7;102695:45;102924:18;;;;;;;;:::i;:::-;102880:16;:63::i;:::-;102857:86;-1:-1:-1;103015:23:0;;;;:7;:23;:::i;:::-;103074:225;;;103122:117;;;;;;-1:-1:-1;;;;;102996:69:0;;;;;;;103074:225;;;;;103170:24;;;;:5;:24;:::i;:::-;-1:-1:-1;;;;;103122:117:0;;;;;103207:7;:21;;;103122:117;;;103074:225;;;;103250:7;:13;;;103074:225;;;;103274:7;:16;;;103074:225;;;103308:116;;;;;;;;103362:7;:21;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;103308:116:0;;;103394:21;;;;103308:116;;;;;103433:18;;;;;;;;:::i;:::-;103460:15;99792:23;;;;;;;;;;;;;;;;;99822:22;;;;;;;;;;;;;;;;;99851:29;;;;;;;;;;;;;;;;;99741:144;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;99741:144:0;;;;;;;;;103524:17;;;;:7;:17;:::i;:::-;102996:552;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103581:76;103597:5;103604:7;103613:9;103624:7;:18;;;;;;;;;;:::i;:::-;103644:12;103581:15;:76::i;113200:428::-;113300:18;100336:23;;;;;;;;;;;;;;;;;100367:22;;;;;;;;;;;;;;;;;100313:81;;;;;;;;;:::i;:::-;;;;;;;;;;;;;100303:92;;;;;;113419:28;113435:5;:11;;113419:15;:28::i;:::-;113409:39;;;;;;113469:29;113485:5;:12;;113469:15;:29::i;:::-;113459:40;;;;;;;113510:12;;;;113533:10;;;;113554:18;;;;;;;;:::i;:::-;113583:23;;;;;;;;:::i;:::-;113357:258;;;;;;27293:25:1;;;;27334:18;;27327:34;;;;27377:18;;;27370:34;;;;27420:18;;;27413:34;;;;27463:19;;;27456:35;27540:10;27528:23;27507:19;;;27500:52;27596:14;27589:22;27568:19;;;27561:51;27265:19;;113357:258:0;;;;;;;;;;;;113337:285;;;;;;113330:292;;113200:428;;;:::o;99893:226::-;100019:29;;;;;;;;;;;;;;;;;100055:22;;;;;;;;;;;;;;;;;100084:29;;;;;;;;;;;;;;;;;99963:155;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;99893:226;:::o;111781:144::-;47505:13;:11;:13::i;:::-;-1:-1:-1;;;;;111850:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;:30;;-1:-1:-1;;111850:30:0::1;111876:4;111850:30;::::0;;111892:27;::::1;::::0;111850:23;111892:27:::1;111781:144:::0;:::o;112056:150::-;47505:13;:11;:13::i;:::-;-1:-1:-1;;;;;112128:23:0;::::1;112154:5;112128:23:::0;;;:14:::1;:23;::::0;;;;;:31;;-1:-1:-1;;112128:31:0::1;::::0;;112171:29;::::1;::::0;112154:5;112171:29:::1;112056:150:::0;:::o;100170:79::-;100226:22;;;;;;;;;;;;;;;;;100216:33;;;;;;100170:79;:::o;100402:151::-;100488:29;;;;;;;;;;;;;;;;;100525:22;;;;;;;;;;;;;;;;;100465:87;;;;;;;;;:::i;115104:194::-;115208:12;115239:53;115256:35;115285:5;115256:28;:35::i;99677:209::-;99792:23;;;;;;;;;;;;;;;;;99822:22;;;;;;;;;;;;;;;;;99851:29;;;;;;;;;;;;;;;;;99741:144;;;;;;;;;;:::i;105453:1946::-;105636:17;105684:24;105702:5;105684:17;:24::i;:::-;105743:23;105769:35;105798:5;105769:28;:35::i;:::-;105743:61;;105823:33;105840:15;105823:16;:33::i;:::-;105811:45;-1:-1:-1;105973:35:0;106011:68;106033:5;106040:7;105811:45;106060:18;;;;;;;;:::i;:::-;106011:21;:68::i;:::-;106207:167;;;;;;;;;105973:106;;-1:-1:-1;106148:56:0;;106207:167;106300:12;:5;;:12;:::i;:::-;:19;;106258:62;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;106258:62:0;;;;;;;;;;;;;;;-1:-1:-1;106207:167:0;;;106329:13;;;;106207:167;;;;;106351:16;;;;106207:167;;;106148:226;-1:-1:-1;;106509:12:0;:5;;:12;:::i;:::-;:19;;106459:70;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;106459:70:0;;;;;;;;;;;;;;;;106381:148;;106543:9;106538:534;106562:12;:5;;:12;:::i;:::-;:19;;106558:1;:23;106538:534;;;106625:12;:5;;:12;:::i;:::-;106638:1;106625:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;106625:28:0;:::i;:::-;106597:16;;:19;;106614:1;;106597:19;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;106597:56:0;;;;;106691:22;;;;:7;:22;:::i;:::-;106714:1;106691:25;;;;;;;:::i;:::-;;;;;;;106662:6;:16;;;106679:1;106662:19;;;;;;;;:::i;:::-;;;;;;;;;;;;:26;:54;106781:22;;;;:7;:22;:::i;:::-;106804:1;106781:25;;;;;;;:::i;:::-;;;;;;;106754:6;:20;;;106775:1;106754:23;;;;;;;;:::i;:::-;;;;;;:52;;;;;;;:::i;:::-;;;-1:-1:-1;106839:12:0;:5;;:12;:::i;:::-;106852:1;106839:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;106839:28:0;:::i;:::-;106815:18;;:21;;106834:1;;106815:21;;;;;;:::i;:::-;-1:-1:-1;;;;;106815:52:0;;;:21;;;;;;;;;;;:52;106906:22;;;;:7;:22;:::i;:::-;106929:1;106906:25;;;;;;;:::i;:::-;;;;;;;106876:6;:24;;;106901:1;106876:27;;;;;;;;:::i;:::-;;;;;;;;;;:55;106966:22;;;;:7;:22;:::i;:::-;106989:1;106966:25;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;106942:15;106958:1;106942:18;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;106942:49:0;;;;;107037:22;;;;:7;:22;:::i;:::-;107060:1;107037:25;;;;;;;:::i;:::-;;;;;;;107000:15;107016:1;107000:18;;;;;;;;:::i;:::-;;;;;;;;;;;;:34;:62;106583:3;;;;:::i;:::-;;;;106538:534;;;-1:-1:-1;107097:23:0;;;;:7;:23;:::i;:::-;-1:-1:-1;;;;;107078:69:0;;107156:6;107171:15;107195:18;;;;;;;;:::i;:::-;107222:15;100019:29;;;;;;;;;;;;;;;;;100055:22;;;;;;;;;;;;;;;;;100084:29;;;;;;;;;;;;;;;;;99963:155;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;99963:155:0;;;;;;;;;107292:17;;;;:7;:17;:::i;:::-;107078:238;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107349:44;107370:5;107377:7;107386:6;107349:20;:44::i;:::-;105658:1741;;;;105453:1946;;;;;:::o;112540:161::-;47505:13;:11;:13::i;:::-;112623:17:::1;:27:::0;;-1:-1:-1;;112623:27:0::1;-1:-1:-1::0;;;;;112623:27:0;::::1;::::0;;::::1;::::0;;;112662:33:::1;::::0;::::1;::::0;-1:-1:-1;;112662:33:0::1;112540:161:::0;:::o;84571:213::-;84684:10;84668:27;;;;:15;:27;;;;;;;;:38;;;;;;;;;:50;;-1:-1:-1;;84668:50:0;;;;;;;;;;84730:48;;1680:41:1;;;84668:38:0;;84730:48;;1653:18:1;84730:48:0;;;;;;;84571:213;;:::o;50163:181::-;47505:13;:11;:13::i;:::-;50253::::1;:24:::0;;-1:-1:-1;;;;;50253:24:0;::::1;-1:-1:-1::0;;50253:24:0;;::::1;::::0;::::1;::::0;;;50318:7:::1;47692:6:::0;;-1:-1:-1;;;;;47692:6:0;;47619:87;50318:7:::1;-1:-1:-1::0;;;;;50293:43:0::1;;;;;;;;;;;50163:181:::0;:::o;108768:1800::-;109061:17;;109014;;-1:-1:-1;;;;;109061:17:0;109047:10;:31;;;;:56;;-1:-1:-1;47692:6:0;;-1:-1:-1;;;;;47692:6:0;109082:10;:21;;109047:56;109043:115;;;109121:29;;-1:-1:-1;;;109121:29:0;;109139:10;109121:29;;;8222:74:1;8195:18;;109121:29:0;8076:226:1;109043:115:0;109164:26;109207:6;:13;109193:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;109193:28:0;;109164:57;;109228:25;109270:6;:13;109256:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;109256:28:0;;109228:56;;109298:9;109293:385;109317:6;:13;109313:1;:17;109293:385;;;109360:6;109367:1;109360:9;;;;;;;;:::i;:::-;;;;;;;:22;;;109346:8;109355:1;109346:11;;;;;;;;:::i;:::-;;;;;;:36;-1:-1:-1;;;;;109346:36:0;;;-1:-1:-1;;;;;109346:36:0;;;;;109446:6;109453:1;109446:9;;;;;;;;:::i;:::-;;;;;;;:21;;;109471:1;109446:26;:106;;109531:6;109538:1;109531:9;;;;;;;;:::i;:::-;;;;;;;:21;;;109446:106;;;109491:8;109500:1;109491:11;;;;;;;;:::i;:::-;;;;;;;;;;;109484:44;;-1:-1:-1;;;109484:44:0;;109522:4;109484:44;;;8222:74:1;-1:-1:-1;;;;;109484:29:0;;;;;;8195:18:1;;109484:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109431:9;109441:1;109431:12;;;;;;;;:::i;:::-;;;;;;:121;;;;;109605:65;109638:14;109653:1;109638:17;;;;;;;;:::i;:::-;;;;;;;109657:9;109667:1;109657:12;;;;;;;;:::i;:::-;;;;;;;109612:8;109621:1;109612:11;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;109605:32:0;;;:65;;;;;:::i;:::-;109332:3;;;;:::i;:::-;;;;109293:385;;;-1:-1:-1;109756:19:0;;109749:52;;-1:-1:-1;;;109749:52:0;;109795:4;109749:52;;;8222:74:1;109725:21:0;;-1:-1:-1;;;;;109749:37:0;;;;8195:18:1;;109749:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109884:78;;;;;109725:76;;-1:-1:-1;;;;;;109884:39:0;;;;;:78;;109924:14;;;;109940:9;;109951:10;;109884:78;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;110035:19:0;;110028:52;;-1:-1:-1;;;110028:52:0;;110074:4;110028:52;;;8222:74:1;110083:13:0;;-1:-1:-1;;;;;;110028:37:0;;;;-1:-1:-1;110028:37:0;;8195:18:1;;110028:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:68;;;;:::i;:::-;110016:80;;110121:6;:18;;;110109:9;:30;110105:133;;;110179:19;;110200:18;;;;110157:73;;-1:-1:-1;;;110157:73:0;;-1:-1:-1;;;;;33681:55:1;;;110157:73:0;;;33663:74:1;33753:18;;;33746:34;33796:18;;;33789:34;;;33636:18;;110157:73:0;33461:368:1;110105:133:0;110293:19;;110286:67;;-1:-1:-1;;;;;110286:40:0;110327:14;110343:9;110286:40;:67::i;:::-;110367:195;110391:10;110410:8;110427:9;110445:14;110468:6;:19;;;110496:6;:18;;;110523:14;110546:9;110367:195;;;;;;;;;;;;;:::i;:::-;;;;;;;;109036:1532;;;108768:1800;;;;;;;;;:::o;43868:236::-;43953:7;43974:17;43993:18;44015:25;44026:4;44032:1;44035;44038;44015:10;:25::i;:::-;43973:67;;;;44051:18;44063:5;44051:11;:18::i;:::-;-1:-1:-1;44087:9:0;43868:236;-1:-1:-1;;;;;43868:236:0:o;55631:177::-;55741:58;;-1:-1:-1;;;;;20522:55:1;;55741:58:0;;;20504:74:1;20594:18;;;20587:34;;;55714:86:0;;55734:5;;55764:23;;20477:18:1;;55741:58:0;;;;-1:-1:-1;;55741:58:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;55741:58:0;;;;;;;;;;55714:19;:86::i;:::-;55631:177;;;:::o;115433:539::-;115583:10;115568:26;;;;:14;:26;;;;;;;;115563:86;;115612:29;;-1:-1:-1;;;115612:29:0;;115630:10;115612:29;;;8222:74:1;8195:18;;115612:29:0;8076:226:1;115563:86:0;115714:15;115699:5;:12;;;:30;115695:103;;;115747:43;;-1:-1:-1;;;115747:43:0;;115760:12;;;;115747:43;;;35640:25:1;115774:15:0;35681:18:1;;;35674:34;35613:18;;115747:43:0;35466:248:1;115695:103:0;115871:25;;;;:12;;;:25;:::i;:::-;-1:-1:-1;;;;;115843:53:0;:24;;;;:5;:24;:::i;:::-;-1:-1:-1;;;;;115843:53:0;;115839:128;;115934:24;;;;:5;:24;:::i;:::-;115914:45;;;;;-1:-1:-1;;;;;8240:55:1;;;115914:45:0;;;8222:74:1;8195:18;;115914:45:0;8076:226:1;82948:1363:0;83120:15;;83151:16;:52;;;;;;;;:::i;:::-;;83147:1159;;83224:42;83238:9;83249:16;;83224:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83224:13:0;;-1:-1:-1;;;83224:42:0:i;83147:1159::-;83304:33;83284:16;:53;;;;;;;;:::i;:::-;;83280:1026;;-1:-1:-1;83441:37:0;;83437:2;83433:46;83654:24;;83681:21;:16;83698:2;83681:16;83454:23;83681:21;:::i;:::-;83654:48;;;;83718:41;83729:7;83738:9;83749;;83718:10;:41::i;:::-;83713:130;;83803:9;83814:7;83823:9;;83779:54;;;;;;;;;;;;;;:::i;83280:1026::-;83953:2;83926:29;;83922:112;;83975:49;;;;;83996:2;83975:49;;;35640:25:1;35681:18;;;35674:34;;;35613:18;;83975:49:0;35466:248:1;83922:112:0;-1:-1:-1;84135:37:0;;84131:2;84127:46;84197:24;;;;:15;:24;;;;;;;;:35;;;;;;;;;;;84192:107;;84252:37;;;;;;;;36784:25:1;;;-1:-1:-1;;;;;36845:55:1;;36825:18;;;36818:83;36757:18;;84252:37:0;36610:297:1;116255:1266:0;-1:-1:-1;;;;;116576:23:0;;116446:20;116576:23;;;:11;:23;;;;;;;;:34;;;;;;;;;116623:33;;;116619:88;;116674:25;;-1:-1:-1;;;116674:25:0;;;;;4755::1;;;4728:18;;116674:25:0;4609:177:1;116619:88:0;116883:23;;;;;;;;:::i;:::-;116879:637;;;117027:23;;;;116988:36;117003:21;;;;116988:12;:36;:::i;:::-;:62;116984:205;;;117092:24;;;;:5;:24;:::i;:::-;117157:21;117070:109;;-1:-1:-1;;;117070:109:0;;-1:-1:-1;;;;;37161:55:1;;;117070:109:0;;;37143:74:1;117118:23:0;;;;37233:18:1;;;37226:34;37276:18;;;37269:34;;;117157:21:0;;;37319:18:1;;;37312:34;37115:19;;117070:109:0;36912:440:1;116984:205:0;116879:637;;;117317:1;117302:12;:16;:68;;;-1:-1:-1;117322:21:0;;;;117347:23;;;;117322:48;;117302:68;117298:211;;;117412:24;;;;:5;:24;:::i;56053:205::-;56181:68;;-1:-1:-1;;;;;37638:15:1;;;56181:68:0;;;37620:34:1;37690:15;;37670:18;;;37663:43;37722:18;;;37715:34;;;56154:96:0;;56174:5;;56204:27;;37532:18:1;;56181:68:0;37357:398:1;56154:96:0;56053:205;;;;:::o;117796:2660::-;118047:37;118063:21;;;;118047:37;;:::i;:::-;-1:-1:-1;;;;;118091:23:0;;;;;;:11;:23;;;;;;;;:34;;;;;;;;:49;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;118047:37:0;;-1:-1:-1;118263:25:0;;;;:12;;;:25;:::i;:::-;118256:58;;-1:-1:-1;;;118256:58:0;;118308:4;118256:58;;;8222:74:1;-1:-1:-1;;;;;118256:43:0;;;;;;;8195:18:1;;118256:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118233:81;;118392:16;;;118406:1;118392:16;;;;;;;;;118233:20;;118392:16;;;;;;;;;;;-1:-1:-1;118392:16:0;118363:45;;118432:7;:21;;;118417:9;118427:1;118417:12;;;;;;;;:::i;:::-;;;;;;:36;;;;;118476:7;:20;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;118462:47:0;;118510:22;:7;;:22;:::i;:::-;118534:9;118545:10;118462:94;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;118701:20:0;;;-1:-1:-1;118647:25:0;;-1:-1:-1;;118647:25:0;;;:12;;;:25;:::i;:::-;118640:58;;-1:-1:-1;;;118640:58:0;;118692:4;118640:58;;;8222:74:1;-1:-1:-1;;;;;118640:43:0;;;;;;;8195:18:1;;118640:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:81;;;;:::i;:::-;118621:16;;;;:100;;;;93729:4;;118934:23;;;118910:21;;;;118875:32;118883:24;;;;93729:4;118875:32;:::i;:::-;:56;;;;:::i;:::-;:82;;;;:::i;:::-;:90;;;;:::i;:::-;118851:21;;;:114;93978:7;119033:18;;;;;;;;:::i;:::-;:48;;;119029:444;;;119092:36;-1:-1:-1;;;;;119145:14:0;119131:44;;119176:18;;;;;;;;:::i;:::-;119131:64;;-1:-1:-1;;;;;;119131:64:0;;;;;;;;38374:23:1;;;;119131:64:0;;;38356:42:1;38329:18;;119131:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;119092:103;-1:-1:-1;119204:25:0;119273:14;94027:4;119285:2;119273:14;:::i;:::-;119251;;119232:16;;;;:33;;;;;;:::i;:::-;:37;;119268:1;119232:37;:::i;:::-;:56;;;;:::i;:::-;119348:14;;119204:84;;-1:-1:-1;94027:4:0;;119336:26;;;;94027:4;119336:26;:::i;:::-;119316:6;:16;;;:47;;;;:::i;:::-;:59;;;;:::i;:::-;119297:16;;;;:78;;;;119431:14;;;119384:81;;119447:17;119391:25;;;;:12;;;:25;:::i;119384:81::-;119083:390;;119029:444;119549:6;:21;;;119530:6;:16;;;:40;119526:159;;;119610:25;;;;:12;;;:25;:::i;:::-;119637:21;;;;119660:16;;;;119588:89;;-1:-1:-1;;;119588:89:0;;-1:-1:-1;;;;;33681:55:1;;;119588:89:0;;;33663:74:1;33753:18;;;33746:34;;;;33796:18;;;33789:34;33636:18;;119588:89:0;33461:368:1;119526:159:0;119755:6;:21;;;119736:6;:16;;;:40;;;;:::i;:::-;119719:14;;;:57;;;119804:18;;;;-1:-1:-1;119783:149:0;;;119862:25;;;;:12;;;:25;:::i;:::-;119909:14;;;;;119840:84;;-1:-1:-1;;;119840:84:0;;-1:-1:-1;;;;;33681:55:1;;;119840:84:0;;;33663:74:1;119889:18:0;;;;33753::1;;;33746:34;33796:18;;;33789:34;33636:18;;119840:84:0;33461:368:1;119783:149:0;120046:21;;;;;119987:81;;120034:10;;120046:21;119994:25;;;;:12;;;:25;:::i;119987:81::-;-1:-1:-1;;;;;120122:328:0;;120147:9;120122:328;120184:24;;;;:5;:24;:::i;:::-;120217:25;;;;:12;;;:25;:::i;:::-;120251:5;:11;;:23;;;120283:5;:12;;:24;;;120316:7;:21;;;120346:6;:21;;;120376:6;:14;;;120399:5;:18;;;;;;;;;;:::i;:::-;120122:328;;;-1:-1:-1;;;;;39680:15:1;;;39662:34;;39732:15;;;;39727:2;39712:18;;39705:43;39764:18;;;39757:34;;;;39822:2;39807:18;;39800:34;;;;39865:3;39850:19;;39843:35;120426:17:0;39894:19:1;;;39887:35;;;;39953:3;39938:19;;39931:35;;;;40015:10;40003:23;;;39997:3;39982:19;;39975:52;120426:17:0;;;40058:3:1;40043:19;;40036:35;39588:3;39573:19;120122:328:0;;;;;;;117990:2466;117796:2660;;;;;:::o;75677:167::-;75754:7;75781:55;75803:20;:18;:20::i;:::-;75825:10;45855:4;45849:11;45886:10;45874:23;;45927:4;45918:14;;45911:39;;;;45980:4;45971:14;;45964:34;46035:4;46020:20;;;45652:406;120590:701;120745:10;120730:26;;;;:14;:26;;;;;;;;120725:86;;120774:29;;-1:-1:-1;;;120774:29:0;;120792:10;120774:29;;;8222:74:1;8195:18;;120774:29:0;8076:226:1;120725:86:0;120876:15;120861:5;:12;;;:30;120857:103;;;120922:12;120909:43;;-1:-1:-1;;;120909:43:0;;120922:12;;;;120909:43;;;35640:25:1;120936:15:0;35681:18:1;;;35674:34;35613:18;;120909:43:0;35466:248:1;120857:103:0;121006:9;121001:285;121025:12;:5;;:12;:::i;:::-;:19;;121021:1;:23;121001:285;;;121065:9;121060:219;121084:13;;;;:5;:13;:::i;:::-;:20;;121080:1;:24;121060:219;;;121158:13;;;;:5;:13;:::i;:::-;121172:1;121158:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;121158:29:0;:::i;:::-;-1:-1:-1;;;;;121126:61:0;:12;:5;;:12;:::i;:::-;121139:1;121126:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;121126:28:0;:::i;:::-;-1:-1:-1;;;;;121126:61:0;;121122:148;;121229:12;:5;;:12;:::i;:::-;121242:1;121229:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;121229:28:0;:::i;121122:148::-;121106:3;;;;:::i;:::-;;;;121060:219;;;-1:-1:-1;121046:3:0;;;;:::i;:::-;;;;121001:285;;;;120590:701;:::o;121582:2742::-;121788:35;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121788:35:0;121848:595;;;;;;;;;;121906:12;:5;;:12;:::i;:::-;:19;;121892:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;121892:34:0;;121848:595;;;;121963:5;:13;;;;;;;;:::i;:::-;:20;;121949:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;121949:35:0;-1:-1:-1;121848:595:0;;;;122026:12;:5;;:12;:::i;:::-;:19;;122012:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122012:34:0;;121848:595;;;;122089:5;:13;;;;;;;;:::i;:::-;:20;;122075:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122075:35:0;-1:-1:-1;121848:595:0;;;;122148:12;:5;;:12;:::i;:::-;:19;;122134:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122134:34:0;;121848:595;;;;122212:5;:13;;;;;;;;:::i;:::-;:20;;122198:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122198:35:0;;121848:595;;;;122265:5;:13;;;;;;;;:::i;:::-;:20;;122251:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122251:35:0;;121848:595;;;;122325:5;:13;;;;;;;;:::i;:::-;:20;;122311:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122311:35:0;-1:-1:-1;121848:595:0;;-1:-1:-1;;;;;121848:595:0;;;;;;;;;;;;;;;;-1:-1:-1;121848:595:0;;;;;;;122554:28;;;:16;:28;;;;;:39;;;;;;;;;122531:62;;;;;;;;;;;;;;;;;121839:604;;-1:-1:-1;122531:62:0;;122554:39;;122531:62;;122554:39;122531:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;122531:20:0;;;:62;;;-1:-1:-1;122606:27:0;:31;;;;:79;;;-1:-1:-1;;122641:6:0;:20;;;122662:1;122641:23;;;;;;;;:::i;:::-;;;;;;;:44;122606:79;122602:134;;;122703:25;;-1:-1:-1;;;122703:25:0;;;;;4755::1;;;4728:18;;122703:25:0;4609:177:1;122602:134:0;122748:6;:20;;;:27;122779:1;122748:32;122744:112;;122828:12;:5;;:12;:::i;:::-;:19;;122814:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;122814:34:0;-1:-1:-1;122791:20:0;;;:57;122744:112;123032:23;;;;;;;;:::i;:::-;123028:1291;;;123138:9;123133:619;123157:6;:20;;;:27;123153:1;:31;123133:619;;;123260:12;:5;;:12;:::i;:::-;123273:1;123260:15;;;;;;;:::i;:::-;;;;;;:27;;;123232:7;:22;;;;;;;;:::i;:::-;123255:1;123232:25;;;;;;;:::i;:::-;;;;;;;123206:6;:20;;;123227:1;123206:23;;;;;;;;:::i;:::-;;;;;;;:51;;;;:::i;:::-;:81;123202:264;;;123331:12;:5;;:12;:::i;:::-;123344:1;123331:15;;;;;;;:::i;:::-;:28;;;:15;;;;;:28;;;;-1:-1:-1;123331:28:0;:::i;:::-;123361:12;:5;;:12;:::i;:::-;123374:1;123361:15;;;;;;;:::i;:::-;;;;;;:27;;;123403:6;:20;;;123424:1;123403:23;;;;;;;;:::i;:::-;;;;;;;123428:7;:22;;;;;;;;:::i;:::-;123451:1;123428:25;;;;;;;:::i;:::-;123309:145;;-1:-1:-1;;;123309:145:0;;-1:-1:-1;;;;;37161:55:1;;;123309:145:0;;;37143:74:1;37233:18;;;37226:34;;;;-1:-1:-1;37276:18:1;;;37269:34;;;;123428:25:0;;;;;;37319:18:1;;;37312:34;37115:19;;123309:145:0;36912:440:1;123202:264:0;123520:27;123586:12;:5;;:12;:::i;:::-;123599:1;123586:15;;;;;;;:::i;:::-;;;;;;:27;;;123558:7;:22;;;;;;;;:::i;:::-;123581:1;123558:25;;;;;;;:::i;:::-;;;;;;;93729:4;123550:33;;;;:::i;:::-;:63;;;;:::i;:::-;123520:93;;123650:6;:22;;;123628:19;:44;123624:119;;;123687:22;;;:44;;;123624:119;-1:-1:-1;123186:3:0;;;;:::i;:::-;;;;123133:619;;;;123028:1291;;;93729:4;123836:22;;;:30;123969:9;123964:348;123988:6;:20;;;:27;123984:1;:31;123964:348;;;124063:1;124037:6;:20;;;124058:1;124037:23;;;;;;;;:::i;:::-;;;;;;;:27;:87;;;-1:-1:-1;124097:12:0;:5;;:12;:::i;:::-;124110:1;124097:15;;;;;;;:::i;:::-;;;;;;:27;;;124068:7;:22;;;;;;;;:::i;:::-;124091:1;124068:25;;;;;;;:::i;:::-;;;;;;;:56;;124037:87;124033:270;;;124168:12;:5;;:12;:::i;124033:270::-;124017:3;;;;:::i;:::-;;;;123964:348;;;;121582:2742;;;;;;:::o;124537:3125::-;124825:20;;;;124786:17;;;;-1:-1:-1;;;;;124769:35:0;;;;;:16;:35;;;;;;;;124805:16;;;;124769:53;;;;;;;:76;;;;:53;;:76;;;;;:::i;:::-;;124904:9;124899:288;124923:13;;;;:5;:13;:::i;:::-;:20;;124919:1;:24;124899:288;;;124984:13;;;;:5;:13;:::i;:::-;124998:1;124984:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;124984:29:0;:::i;:::-;124959:6;:19;;;124979:1;124959:22;;;;;;;;:::i;:::-;-1:-1:-1;;;;;124959:54:0;;;:22;;;;;;;;;;:54;125053:13;;;;:5;:13;:::i;:::-;125067:1;125053:16;;;;;;;:::i;:::-;;;;;;:28;;;125022:6;:25;;;125048:1;125022:28;;;;;;;;:::i;:::-;;;;;;:59;;;;;125124:5;:13;;;;;;;;:::i;:::-;125138:1;125124:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;125124:29:0;:::i;:::-;125117:62;;-1:-1:-1;;;125117:62:0;;125173:4;125117:62;;;8222:74:1;-1:-1:-1;;;;;125117:47:0;;;;;;;8195:18:1;;125117:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125090:6;:21;;;125112:1;125090:24;;;;;;;;:::i;:::-;;;;;;;;;;:89;124945:3;;;;:::i;:::-;;;;124899:288;;;-1:-1:-1;125238:20:0;;;;;;;;:::i;:::-;-1:-1:-1;;;;;125224:47:0;;125272:22;:7;;:22;:::i;:::-;125296;;;;:7;:22;:::i;:::-;125320:10;125224:107;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;125400:27:0;;-1:-1:-1;125444:13:0;;-1:-1:-1;;125444:13:0;;;:5;:13;:::i;:::-;:20;;125430:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;125430:35:0;;125400:65;;125479:9;125474:177;125498:13;;;;:5;:13;:::i;:::-;:20;;125494:1;:24;125474:177;;;125617:6;:21;;;125639:1;125617:24;;;;;;;;:::i;:::-;;;;;;;125559:5;:13;;;;;;;;:::i;:::-;125573:1;125559:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;125559:29:0;:::i;:::-;125552:62;;-1:-1:-1;;;125552:62:0;;125608:4;125552:62;;;8222:74:1;-1:-1:-1;;;;;125552:47:0;;;;;;;8195:18:1;;125552:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;;:::i;:::-;125536:10;125547:1;125536:13;;;;;;;;:::i;:::-;;;;;;;;;;:105;125520:3;;;;:::i;:::-;;;;125474:177;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;93978:7:0;125712:18;;;;;;;;:::i;:::-;:48;;;125708:144;;;-1:-1:-1;;;;;125792:14:0;125778:44;;125823:18;;;;;;;;:::i;:::-;125778:64;;-1:-1:-1;;;;;;125778:64:0;;;;;;;;38374:23:1;;;;125778:64:0;;;38356:42:1;38329:18;;125778:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125773:69;;125708:144;125867:9;125862:1391;125886:13;;;;:5;:13;:::i;:::-;:20;;125882:1;:24;125862:1391;;;93978:7;125987:18;;;;;;;;:::i;:::-;:48;;;125983:343;;;126050:25;126116:14;94027:4;126128:2;126116:14;:::i;:::-;126094:2;:14;;;126078:30;;:10;126089:1;126078:13;;;;;;;;:::i;:::-;;;;;;;:30;;;;:::i;:::-;:34;;126111:1;126078:34;:::i;:::-;:53;;;;:::i;:::-;126189:14;;126050:81;;-1:-1:-1;94027:4:0;;126177:26;;;;94027:4;126177:26;:::i;:::-;126160:10;126171:1;126160:13;;;;;;;;:::i;:::-;;;;;;;:44;;;;:::i;:::-;:56;;;;:::i;:::-;126144:10;126155:1;126144:13;;;;;;;;:::i;:::-;;;;;;:72;;;;;126229:85;126280:2;:14;;;126296:17;126236:5;:13;;;;;;;;:::i;:::-;126250:1;126236:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;126236:29:0;:::i;126229:85::-;126037:289;125983:343;126463:22;93729:4;126513:13;;;;:5;:13;:::i;:::-;126527:1;126513:16;;;;;;;:::i;:::-;;;;;;:28;;;126488:6;:22;;;:53;;;;:::i;:::-;:61;;;;:::i;:::-;126463:86;;126631:14;126615:10;126626:1;126615:13;;;;;;;;:::i;:::-;;;;;;;:30;126611:151;;;126689:13;;;;:5;:13;:::i;:::-;126703:1;126689:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;126689:29:0;:::i;:::-;126720:14;126736:10;126747:1;126736:13;;;;;;;;:::i;:::-;;;;;;;;;;;126667:83;;-1:-1:-1;;;126667:83:0;;-1:-1:-1;;;;;33681:55:1;;;126667:83:0;;;33663:74:1;33753:18;;;33746:34;;;;33796:18;;;33789:34;33636:18;;126667:83:0;33461:368:1;126611:151:0;126804:14;126772:6;:26;;;126799:1;126772:29;;;;;;;;:::i;:::-;;;;;;:46;;;;;126897:14;126881:10;126892:1;126881:13;;;;;;;;:::i;:::-;;;;;;;:30;;;;:::i;:::-;126861:6;:14;;;126876:1;126861:17;;;;;;;;:::i;:::-;;;;;;;;;;:50;126946:18;;;;:7;:18;:::i;:::-;126965:1;126946:21;;;;;;;:::i;:::-;;;;;;;126926:6;:14;;;126941:1;126926:17;;;;;;;;:::i;:::-;;;;;;;:41;126922:173;;;127011:13;;;;:5;:13;:::i;:::-;127025:1;127011:16;;;;;;;:::i;:::-;:29;;;:16;;;;;:29;;;;-1:-1:-1;127011:29:0;:::i;:::-;127042:18;;;;:7;:18;:::i;:::-;127061:1;127042:21;;;;;;;:::i;:::-;;;;;;;127065:6;:14;;;127080:1;127065:17;;;;;;;;:::i;:::-;;;;;;;;;;;126989:94;;-1:-1:-1;;;126989:94:0;;-1:-1:-1;;;;;33681:55:1;;;126989:94:0;;;33663:74:1;33753:18;;;33746:34;;;;33796:18;;;33789:34;33636:18;;126989:94:0;33461:368:1;126922:173:0;127209:17;;;;127158:85;;127228:14;127165:13;;;;:5;:13;:::i;127158:85::-;-1:-1:-1;125908:3:0;;;;:::i;:::-;;;;125862:1391;;;;125340:1920;;127368:6;:17;;;-1:-1:-1;;;;;127313:343:0;127343:6;:16;;;127313:343;127394:6;:18;;;127421:6;:19;;;127449:6;:24;;;127482:6;:25;;;127516:7;:22;;;;;;;;:::i;:::-;127547:6;:26;;;127582:6;:14;;;127605:5;:18;;;;;;;;;;:::i;:::-;127632:7;:17;;;127313:343;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;124537:3125;;;:::o;47784:132::-;47692:6;;-1:-1:-1;;;;;47692:6:0;13058:10;47848:23;47840:68;;;;-1:-1:-1;;;47840:68:0;;42948:2:1;47840:68:0;;;42930:21:1;;;42967:18;;;42960:30;43026:34;43006:18;;;42999:62;43078:18;;47840:68:0;42746:356:1;47840:68:0;47784:132::o;50534:156::-;50624:13;50617:20;;-1:-1:-1;;50617:20:0;;;50648:34;50673:8;50648:24;:34::i;69308:274::-;69402:13;67253:66;69432:47;;69428:147;;69503:15;69512:5;69503:8;:15::i;:::-;69496:22;;;;69428:147;69558:5;69551:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69308:274;;;;:::o;42252:1477::-;42340:7;;43274:66;43261:79;;43257:163;;;-1:-1:-1;43373:1:0;;-1:-1:-1;43377:30:0;43357:51;;43257:163;43534:24;;;43517:14;43534:24;;;;;;;;;43776:25:1;;;43849:4;43837:17;;43817:18;;;43810:45;;;;43871:18;;;43864:34;;;43914:18;;;43907:34;;;43534:24:0;;43748:19:1;;43534:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;43534:24:0;;-1:-1:-1;;43534:24:0;;;-1:-1:-1;;;;;;;43573:20:0;;43569:103;;43626:1;43630:29;43610:50;;;;;;;43569:103;43692:6;-1:-1:-1;43700:20:0;;-1:-1:-1;42252:1477:0;;;;;;;;:::o;37712:521::-;37790:20;37781:5;:29;;;;;;;;:::i;:::-;;37777:449;;37712:521;:::o;37777:449::-;37888:29;37879:5;:38;;;;;;;;:::i;:::-;;37875:351;;37934:34;;-1:-1:-1;;;37934:34:0;;44154:2:1;37934:34:0;;;44136:21:1;44193:2;44173:18;;;44166:30;44232:26;44212:18;;;44205:54;44276:18;;37934:34:0;43952:348:1;37875:351:0;37999:35;37990:5;:44;;;;;;;;:::i;:::-;;37986:240;;38051:41;;-1:-1:-1;;;38051:41:0;;44507:2:1;38051:41:0;;;44489:21:1;44546:2;44526:18;;;44519:30;44585:33;44565:18;;;44558:61;44636:18;;38051:41:0;44305:355:1;37986:240:0;38123:30;38114:5;:39;;;;;;;;:::i;:::-;;38110:116;;38170:44;;-1:-1:-1;;;38170:44:0;;44867:2:1;38170:44:0;;;44849:21:1;44906:2;44886:18;;;44879:30;44945:34;44925:18;;;44918:62;45016:4;44996:18;;;44989:32;45038:19;;38170:44:0;44665:398:1;59977:649:0;60401:23;60427:69;60455:4;60427:69;;;;;;;;;;;;;;;;;60435:5;-1:-1:-1;;;;;60427:27:0;;;:69;;;;;:::i;:::-;60401:95;;60515:10;:17;60536:1;60515:22;:56;;;;60552:10;60541:30;;;;;;;;;;;;:::i;:::-;60507:111;;;;-1:-1:-1;;;60507:111:0;;45270:2:1;60507:111:0;;;45252:21:1;45309:2;45289:18;;;45282:30;45348:34;45328:18;;;45321:62;45419:12;45399:18;;;45392:40;45449:19;;60507:111:0;45068:406:1;40868:231:0;40946:7;40967:17;40986:18;41008:27;41019:4;41025:9;41008:10;:27::i;:::-;40966:69;;;;41046:18;41058:5;41046:11;:18::i;:::-;-1:-1:-1;41082:9:0;40868:231;-1:-1:-1;;;40868:231:0:o;74577:268::-;74630:7;74662:4;-1:-1:-1;;;;;74671:11:0;74654:28;;:63;;;;;74703:14;74686:13;:31;74654:63;74650:188;;;-1:-1:-1;74741:22:0;;74577:268::o;74650:188::-;74803:23;74945:81;;;72769:95;74945:81;;;45738:25:1;74968:11:0;45779:18:1;;;45772:34;;;;74981:14:0;45822:18:1;;;45815:34;74997:13:0;45865:18:1;;;45858:34;75020:4:0;45908:19:1;;;45901:84;74908:7:0;;45710:19:1;;74945:81:0;;;;;;;;;;;;74935:92;;;;;;74928:99;;74853:182;;74803:23;74796:30;;74577:268;:::o;48879:191::-;48972:6;;;-1:-1:-1;;;;;48989:17:0;;;-1:-1:-1;;48989:17:0;;;;;;;49022:40;;48972:6;;;48989:17;48972:6;;49022:40;;48953:16;;49022:40;48942:128;48879:191;:::o;67962:415::-;68021:13;68047:11;68061:16;68072:4;68061:10;:16::i;:::-;68187:14;;;68198:2;68187:14;;;;;;;;;68047:30;;-1:-1:-1;68167:17:0;;68187:14;;;;;;;;;-1:-1:-1;;;68280:16:0;;;-1:-1:-1;68326:4:0;68317:14;;68310:28;;;;-1:-1:-1;68280:16:0;67962:415::o;6963:229::-;7100:12;7132:52;7154:6;7162:4;7168:1;7171:12;7132:21;:52::i;39319:747::-;39400:7;39409:12;39438:9;:16;39458:2;39438:22;39434:625;;39782:4;39767:20;;39761:27;39832:4;39817:20;;39811:27;39890:4;39875:20;;39869:27;39477:9;39861:36;39933:25;39944:4;39861:36;39761:27;39811;39933:10;:25::i;:::-;39926:32;;;;;;;;;39434:625;-1:-1:-1;40007:1:0;;-1:-1:-1;40011:35:0;39434:625;39319:747;;;;;:::o;68454:251::-;68515:7;68588:4;68552:40;;68616:2;68607:11;;68603:71;;;68642:20;;;;;;;;;;;;;;8049:455;8219:12;8277:5;8252:21;:30;;8244:81;;;;-1:-1:-1;;;8244:81:0;;46198:2:1;8244:81:0;;;46180:21:1;46237:2;46217:18;;;46210:30;46276:34;46256:18;;;46249:62;46347:8;46327:18;;;46320:36;46373:19;;8244:81:0;45996:402:1;8244:81:0;8337:12;8351:23;8378:6;-1:-1:-1;;;;;8378:11:0;8397:5;8404:4;8378:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8336:73;;;;8427:69;8454:6;8462:7;8471:10;8483:12;8427:26;:69::i;:::-;8420:76;8049:455;-1:-1:-1;;;;;;;8049:455:0:o;10622:644::-;10807:12;10836:7;10832:427;;;10864:10;:17;10885:1;10864:22;10860:290;;-1:-1:-1;;;;;4503:19:0;;;11074:60;;;;-1:-1:-1;;;11074:60:0;;46605:2:1;11074:60:0;;;46587:21:1;46644:2;46624:18;;;46617:30;46683:31;46663:18;;;46656:59;46732:18;;11074:60:0;46403:353:1;11074:60:0;-1:-1:-1;11171:10:0;11164:17;;10832:427;11214:33;11222:10;11234:12;11969:17;;:21;11965:388;;12201:10;12195:17;12258:15;12245:10;12241:2;12237:19;12230:44;11965:388;12328:12;12321:20;;-1:-1:-1;;;12321:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:154:1;-1:-1:-1;;;;;93:5:1;89:54;82:5;79:65;69:93;;158:1;155;148:12;173:134;241:20;;270:31;241:20;270:31;:::i;:::-;173:134;;;:::o;312:347::-;363:8;373:6;427:3;420:4;412:6;408:17;404:27;394:55;;445:1;442;435:12;394:55;-1:-1:-1;468:20:1;;511:18;500:30;;497:50;;;543:1;540;533:12;497:50;580:4;572:6;568:17;556:29;;632:3;625:4;616:6;608;604:19;600:30;597:39;594:59;;;649:1;646;639:12;664:118;750:5;743:13;736:21;729:5;726:32;716:60;;772:1;769;762:12;787:748;881:6;889;897;905;913;966:3;954:9;945:7;941:23;937:33;934:53;;;983:1;980;973:12;934:53;1022:9;1009:23;1041:31;1066:5;1041:31;:::i;:::-;1091:5;-1:-1:-1;1143:2:1;1128:18;;1115:32;;-1:-1:-1;1198:2:1;1183:18;;1170:32;1225:18;1214:30;;1211:50;;;1257:1;1254;1247:12;1211:50;1296:58;1346:7;1337:6;1326:9;1322:22;1296:58;:::i;:::-;1373:8;;-1:-1:-1;1270:84:1;-1:-1:-1;;1460:2:1;1445:18;;1432:32;1473:30;1432:32;1473:30;:::i;:::-;1522:7;1512:17;;;787:748;;;;;;;;:::o;1732:367::-;1795:8;1805:6;1859:3;1852:4;1844:6;1840:17;1836:27;1826:55;;1877:1;1874;1867:12;1826:55;-1:-1:-1;1900:20:1;;1943:18;1932:30;;1929:50;;;1975:1;1972;1965:12;1929:50;2012:4;2004:6;2000:17;1988:29;;2072:3;2065:4;2055:6;2052:1;2048:14;2040:6;2036:27;2032:38;2029:47;2026:67;;;2089:1;2086;2079:12;2104:908;2235:6;2243;2251;2259;2267;2320:2;2308:9;2299:7;2295:23;2291:32;2288:52;;;2336:1;2333;2326:12;2288:52;2376:9;2363:23;2405:18;2446:2;2438:6;2435:14;2432:34;;;2462:1;2459;2452:12;2432:34;2501:70;2563:7;2554:6;2543:9;2539:22;2501:70;:::i;:::-;2590:8;;-1:-1:-1;2475:96:1;-1:-1:-1;2678:2:1;2663:18;;2650:32;;-1:-1:-1;2694:16:1;;;2691:36;;;2723:1;2720;2713:12;2691:36;;2762:72;2826:7;2815:8;2804:9;2800:24;2762:72;:::i;:::-;2853:8;;-1:-1:-1;2736:98:1;-1:-1:-1;;2938:2:1;2923:18;;2910:32;2951:31;2910:32;2951:31;:::i;3017:315::-;3085:6;3093;3146:2;3134:9;3125:7;3121:23;3117:32;3114:52;;;3162:1;3159;3152:12;3114:52;3201:9;3188:23;3220:31;3245:5;3220:31;:::i;:::-;3270:5;3322:2;3307:18;;;;3294:32;;-1:-1:-1;;;3017:315:1:o;3337:159::-;3400:5;3445:3;3436:6;3431:3;3427:16;3423:26;3420:46;;;3462:1;3459;3452:12;3420:46;-1:-1:-1;3484:6:1;3337:159;-1:-1:-1;3337:159:1:o;3501:157::-;3563:5;3608:2;3599:6;3594:3;3590:16;3586:25;3583:45;;;3624:1;3621;3614:12;3663:166;3733:5;3778:3;3769:6;3764:3;3760:16;3756:26;3753:46;;;3795:1;3792;3785:12;3834:770;4007:6;4015;4023;4076:3;4064:9;4055:7;4051:23;4047:33;4044:53;;;4093:1;4090;4083:12;4044:53;4116:57;4165:7;4154:9;4116:57;:::i;:::-;4106:67;;4224:3;4213:9;4209:19;4196:33;4248:18;4289:2;4281:6;4278:14;4275:34;;;4305:1;4302;4295:12;4275:34;4328:69;4389:7;4380:6;4369:9;4365:22;4328:69;:::i;:::-;4318:79;;4450:3;4439:9;4435:19;4422:33;4406:49;;4480:2;4470:8;4467:16;4464:36;;;4496:1;4493;4486:12;4464:36;;4519:79;4590:7;4579:8;4568:9;4564:24;4519:79;:::i;:::-;4509:89;;;3834:770;;;;;:::o;4791:245::-;4880:6;4933:3;4921:9;4912:7;4908:23;4904:33;4901:53;;;4950:1;4947;4940:12;4901:53;4973:57;5022:7;5011:9;4973:57;:::i;:::-;4963:67;4791:245;-1:-1:-1;;;4791:245:1:o;5041:247::-;5100:6;5153:2;5141:9;5132:7;5128:23;5124:32;5121:52;;;5169:1;5166;5159:12;5121:52;5208:9;5195:23;5227:31;5252:5;5227:31;:::i;5293:180::-;5352:6;5405:2;5393:9;5384:7;5380:23;5376:32;5373:52;;;5421:1;5418;5411:12;5373:52;-1:-1:-1;5444:23:1;;5293:180;-1:-1:-1;5293:180:1:o;5478:892::-;5661:6;5669;5677;5730:2;5718:9;5709:7;5705:23;5701:32;5698:52;;;5746:1;5743;5736:12;5698:52;5786:9;5773:23;5815:18;5856:2;5848:6;5845:14;5842:34;;;5872:1;5869;5862:12;5842:34;5895:77;5964:7;5955:6;5944:9;5940:22;5895:77;:::i;:::-;5885:87;;6025:2;6014:9;6010:18;5997:32;5981:48;;6054:2;6044:8;6041:16;6038:36;;;6070:1;6067;6060:12;6038:36;6093:71;6156:7;6145:8;6134:9;6130:24;6093:71;:::i;:::-;6083:81;;6217:2;6206:9;6202:18;6189:32;6173:48;;6246:2;6236:8;6233:16;6230:36;;;6262:1;6259;6252:12;6375:383;6452:6;6460;6468;6521:2;6509:9;6500:7;6496:23;6492:32;6489:52;;;6537:1;6534;6527:12;6489:52;6576:9;6563:23;6595:31;6620:5;6595:31;:::i;:::-;6645:5;6697:2;6682:18;;6669:32;;-1:-1:-1;6748:2:1;6733:18;;;6720:32;;6375:383;-1:-1:-1;;;6375:383:1:o;6945:242::-;7033:6;7086:2;7074:9;7065:7;7061:23;7057:32;7054:52;;;7102:1;7099;7092:12;7054:52;7125:56;7173:7;7162:9;7125:56;:::i;7192:250::-;7277:1;7287:113;7301:6;7298:1;7295:13;7287:113;;;7377:11;;;7371:18;7358:11;;;7351:39;7323:2;7316:10;7287:113;;;-1:-1:-1;;7434:1:1;7416:16;;7409:27;7192:250::o;7447:270::-;7488:3;7526:5;7520:12;7553:6;7548:3;7541:19;7569:76;7638:6;7631:4;7626:3;7622:14;7615:4;7608:5;7604:16;7569:76;:::i;:::-;7699:2;7678:15;-1:-1:-1;;7674:29:1;7665:39;;;;7706:4;7661:50;;7447:270;-1:-1:-1;;7447:270:1:o;7722:217::-;7869:2;7858:9;7851:21;7832:4;7889:44;7929:2;7918:9;7914:18;7906:6;7889:44;:::i;8307:435::-;8360:3;8398:5;8392:12;8425:6;8420:3;8413:19;8451:4;8480:2;8475:3;8471:12;8464:19;;8517:2;8510:5;8506:14;8538:1;8548:169;8562:6;8559:1;8556:13;8548:169;;;8623:13;;8611:26;;8657:12;;;;8692:15;;;;8584:1;8577:9;8548:169;;;-1:-1:-1;8733:3:1;;8307:435;-1:-1:-1;;;;;8307:435:1:o;8747:994::-;9144:66;9136:6;9132:79;9121:9;9114:98;9248:3;9243:2;9232:9;9228:18;9221:31;9095:4;9275:45;9315:3;9304:9;9300:19;9292:6;9275:45;:::i;:::-;9368:9;9360:6;9356:22;9351:2;9340:9;9336:18;9329:50;9402:32;9427:6;9419;9402:32;:::i;:::-;9388:46;;9470:6;9465:2;9454:9;9450:18;9443:34;-1:-1:-1;;;;;9518:6:1;9514:55;9508:3;9497:9;9493:19;9486:84;9607:6;9601:3;9590:9;9586:19;9579:35;9663:9;9655:6;9651:22;9645:3;9634:9;9630:19;9623:51;9691:44;9728:6;9720;9691:44;:::i;:::-;9683:52;8747:994;-1:-1:-1;;;;;;;;;;8747:994:1:o;9746:612::-;9834:6;9842;9850;9858;9911:2;9899:9;9890:7;9886:23;9882:32;9879:52;;;9927:1;9924;9917:12;9879:52;9966:9;9953:23;9985:31;10010:5;9985:31;:::i;:::-;10035:5;-1:-1:-1;10087:2:1;10072:18;;10059:32;;-1:-1:-1;10142:2:1;10127:18;;10114:32;10169:18;10158:30;;10155:50;;;10201:1;10198;10191:12;10155:50;10240:58;10290:7;10281:6;10270:9;10266:22;10240:58;:::i;:::-;9746:612;;;;-1:-1:-1;10317:8:1;-1:-1:-1;;;;9746:612:1:o;10363:374::-;10457:6;10510:2;10498:9;10489:7;10485:23;10481:32;10478:52;;;10526:1;10523;10516:12;10478:52;10566:9;10553:23;10599:18;10591:6;10588:30;10585:50;;;10631:1;10628;10621:12;10585:50;10654:77;10723:7;10714:6;10703:9;10699:22;10654:77;:::i;10742:160::-;10806:5;10851:3;10842:6;10837:3;10833:16;10829:26;10826:46;;;10868:1;10865;10858:12;10907:774;11082:6;11090;11098;11151:3;11139:9;11130:7;11126:23;11122:33;11119:53;;;11168:1;11165;11158:12;11119:53;11191:57;11240:7;11229:9;11191:57;:::i;:::-;11181:67;;11299:3;11288:9;11284:19;11271:33;11323:18;11364:2;11356:6;11353:14;11350:34;;;11380:1;11377;11370:12;11350:34;11403:77;11472:7;11463:6;11452:9;11448:22;11403:77;:::i;:::-;11393:87;;11533:3;11522:9;11518:19;11505:33;11489:49;;11563:2;11553:8;11550:16;11547:36;;;11579:1;11576;11569:12;11547:36;;11602:73;11667:7;11656:8;11645:9;11641:24;11602:73;:::i;11910:896::-;12095:6;12103;12111;12164:2;12152:9;12143:7;12139:23;12135:32;12132:52;;;12180:1;12177;12170:12;12132:52;12220:9;12207:23;12249:18;12290:2;12282:6;12279:14;12276:34;;;12306:1;12303;12296:12;12276:34;12329:77;12398:7;12389:6;12378:9;12374:22;12329:77;:::i;:::-;12319:87;;12459:2;12448:9;12444:18;12431:32;12415:48;;12488:2;12478:8;12475:16;12472:36;;;12504:1;12501;12494:12;12472:36;12527:79;12598:7;12587:8;12576:9;12572:24;12527:79;:::i;:::-;12517:89;;12659:2;12648:9;12644:18;12631:32;12615:48;;12688:2;12678:8;12675:16;12672:36;;;12704:1;12701;12694:12;12811:309;12876:6;12884;12937:2;12925:9;12916:7;12912:23;12908:32;12905:52;;;12953:1;12950;12943:12;12905:52;12989:9;12976:23;12966:33;;13049:2;13038:9;13034:18;13021:32;13062:28;13084:5;13062:28;:::i;:::-;13109:5;13099:15;;;12811:309;;;;;:::o;13125:184::-;-1:-1:-1;;;13174:1:1;13167:88;13274:4;13271:1;13264:15;13298:4;13295:1;13288:15;13314:275;13385:2;13379:9;13450:2;13431:13;;-1:-1:-1;;13427:27:1;13415:40;;13485:18;13470:34;;13506:22;;;13467:62;13464:88;;;13532:18;;:::i;:::-;13568:2;13561:22;13314:275;;-1:-1:-1;13314:275:1:o;13594:192::-;13663:4;13696:18;13688:6;13685:30;13682:56;;;13718:18;;:::i;:::-;-1:-1:-1;13763:1:1;13759:14;13775:4;13755:25;;13594:192::o;13791:551::-;13847:5;13895:4;13883:9;13878:3;13874:19;13870:30;13867:50;;;13913:1;13910;13903:12;13867:50;13946:4;13940:11;13990:4;13982:6;13978:17;14061:6;14049:10;14046:22;14025:18;14013:10;14010:34;14007:62;14004:88;;;14072:18;;:::i;:::-;14108:4;14101:24;14143:6;-1:-1:-1;14143:6:1;14173:23;;14205:33;14173:23;14205:33;:::i;:::-;14247:23;;14331:2;14316:18;;;14303:32;14286:15;;14279:57;;;;13791:551;;-1:-1:-1;13791:551:1:o;14347:746::-;14401:5;14454:3;14447:4;14439:6;14435:17;14431:27;14421:55;;14472:1;14469;14462:12;14421:55;14508:6;14495:20;14534:4;14558:69;14574:52;14623:2;14574:52;:::i;:::-;14558:69;:::i;:::-;14661:15;;;14747:1;14743:10;;;;14731:23;;14727:32;;;14692:12;;;;14771:15;;;14768:35;;;14799:1;14796;14789:12;14768:35;14835:2;14827:6;14823:15;14847:217;14863:6;14858:3;14855:15;14847:217;;;14943:3;14930:17;14960:31;14985:5;14960:31;:::i;:::-;15004:18;;15042:12;;;;14880;;14847:217;;;-1:-1:-1;15082:5:1;14347:746;-1:-1:-1;;;;;;14347:746:1:o;15098:1762::-;15317:6;15325;15333;15341;15349;15357;15365;15418:3;15406:9;15397:7;15393:23;15389:33;15386:53;;;15435:1;15432;15425:12;15386:53;15475:9;15462:23;15504:18;15545:2;15537:6;15534:14;15531:34;;;15561:1;15558;15551:12;15531:34;15599:6;15588:9;15584:22;15574:32;;15644:7;15637:4;15633:2;15629:13;15625:27;15615:55;;15666:1;15663;15656:12;15615:55;15702:2;15689:16;15724:4;15748:69;15764:52;15813:2;15764:52;:::i;15748:69::-;15851:15;;;15933:1;15929:10;;;;15921:19;;15917:28;;;15882:12;;;;15957:19;;;15954:39;;;15989:1;15986;15979:12;15954:39;16013:11;;;;16033:168;16049:6;16044:3;16041:15;16033:168;;;16117:41;16150:7;16145:3;16117:41;:::i;:::-;16112:3;16105:54;16188:2;16183:3;16179:12;16172:19;;16075:4;16070:3;16066:14;16059:21;;16033:168;;;16220:5;-1:-1:-1;;16263:18:1;;16250:32;;-1:-1:-1;;16294:16:1;;;16291:36;;;16323:1;16320;16313:12;16291:36;16346:63;16401:7;16390:8;16379:9;16375:24;16346:63;:::i;:::-;16336:73;;16428:58;16478:7;16471:4;16460:9;16456:20;16428:58;:::i;:::-;16418:68;;16505:39;16539:3;16528:9;16524:19;16505:39;:::i;:::-;16495:49;;16597:3;16586:9;16582:19;16569:33;16553:49;;16627:2;16617:8;16614:16;16611:36;;;16643:1;16640;16633:12;16611:36;;16682:60;16734:7;16723:8;16712:9;16708:24;16682:60;:::i;:::-;16761:8;;-1:-1:-1;16656:86:1;-1:-1:-1;16815:39:1;;-1:-1:-1;16849:3:1;16834:19;;16815:39;:::i;:::-;16805:49;;15098:1762;;;;;;;;;;:::o;16865:184::-;-1:-1:-1;;;16914:1:1;16907:88;17014:4;17011:1;17004:15;17038:4;17035:1;17028:15;17054:128;17121:9;;;17142:11;;;17139:37;;;17156:18;;:::i;17187:331::-;17292:9;17303;17345:8;17333:10;17330:24;17327:44;;;17367:1;17364;17357:12;17327:44;17396:6;17386:8;17383:20;17380:40;;;17416:1;17413;17406:12;17380:40;-1:-1:-1;;17442:23:1;;;17487:25;;;;;-1:-1:-1;17187:331:1:o;17523:255::-;17643:19;;17682:2;17674:11;;17671:101;;;-1:-1:-1;;17743:2:1;17739:12;;;17736:1;17732:20;17728:33;17717:45;17523:255;;;;:::o;17783:530::-;17825:5;17878:3;17871:4;17863:6;17859:17;17855:27;17845:55;;17896:1;17893;17886:12;17845:55;17932:6;17919:20;17958:18;17954:2;17951:26;17948:52;;;17980:18;;:::i;:::-;18024:55;18067:2;18048:13;;-1:-1:-1;;18044:27:1;18073:4;18040:38;18024:55;:::i;:::-;18104:2;18095:7;18088:19;18150:3;18143:4;18138:2;18130:6;18126:15;18122:26;18119:35;18116:55;;;18167:1;18164;18157:12;18116:55;18232:2;18225:4;18217:6;18213:17;18206:4;18197:7;18193:18;18180:55;18280:1;18255:16;;;18273:4;18251:27;18244:38;;;;18259:7;17783:530;-1:-1:-1;;;17783:530:1:o;18318:682::-;18421:6;18429;18437;18490:2;18478:9;18469:7;18465:23;18461:32;18458:52;;;18506:1;18503;18496:12;18458:52;18545:9;18532:23;18564:31;18589:5;18564:31;:::i;:::-;18614:5;-1:-1:-1;18670:2:1;18655:18;;18642:32;18693:18;18723:14;;;18720:34;;;18750:1;18747;18740:12;18720:34;18773:49;18814:7;18805:6;18794:9;18790:22;18773:49;:::i;:::-;18763:59;;18875:2;18864:9;18860:18;18847:32;18831:48;;18904:2;18894:8;18891:16;18888:36;;;18920:1;18917;18910:12;18888:36;;18943:51;18986:7;18975:8;18964:9;18960:24;18943:51;:::i;19005:287::-;19134:3;19172:6;19166:13;19188:66;19247:6;19242:3;19235:4;19227:6;19223:17;19188:66;:::i;:::-;19270:16;;;;;19005:287;-1:-1:-1;;19005:287:1:o;19297:288::-;19472:6;19461:9;19454:25;19515:2;19510;19499:9;19495:18;19488:30;19435:4;19535:44;19575:2;19564:9;19560:18;19552:6;19535:44;:::i;19590:336::-;19659:6;19712:2;19700:9;19691:7;19687:23;19683:32;19680:52;;;19728:1;19725;19718:12;19680:52;19760:9;19754:16;-1:-1:-1;;;;;;19803:5:1;19799:78;19792:5;19789:89;19779:117;;19892:1;19889;19882:12;19931:184;-1:-1:-1;;;19980:1:1;19973:88;20080:4;20077:1;20070:15;20104:4;20101:1;20094:15;20632:184;20702:6;20755:2;20743:9;20734:7;20730:23;20726:32;20723:52;;;20771:1;20768;20761:12;20723:52;-1:-1:-1;20794:16:1;;20632:184;-1:-1:-1;20632:184:1:o;20821:135::-;20860:3;20881:17;;;20878:43;;20901:18;;:::i;:::-;-1:-1:-1;20948:1:1;20937:13;;20821:135::o;20961:521::-;21038:4;21044:6;21104:11;21091:25;21198:2;21194:7;21183:8;21167:14;21163:29;21159:43;21139:18;21135:68;21125:96;;21217:1;21214;21207:12;21125:96;21244:33;;21296:20;;;-1:-1:-1;21339:18:1;21328:30;;21325:50;;;21371:1;21368;21361:12;21325:50;21404:4;21392:17;;-1:-1:-1;21435:14:1;21431:27;;;21421:38;;21418:58;;;21472:1;21469;21462:12;21487:286;21576:6;21629:2;21617:9;21608:7;21604:23;21600:32;21597:52;;;21645:1;21642;21635:12;21597:52;21684:9;21671:23;21723:1;21716:5;21713:12;21703:40;;21739:1;21736;21729:12;21778:574;21900:4;21906:6;21966:11;21953:25;22060:2;22056:7;22045:8;22029:14;22025:29;22021:43;22001:18;21997:68;21987:96;;22079:1;22076;22069:12;21987:96;22106:33;;22158:20;;;-1:-1:-1;22201:18:1;22190:30;;22187:50;;;22233:1;22230;22223:12;22187:50;22266:4;22254:17;;-1:-1:-1;22317:1:1;22313:14;;;22297;22293:35;22283:46;;22280:66;;;22342:1;22339;22332:12;22357:545;22450:4;22456:6;22516:11;22503:25;22610:2;22606:7;22595:8;22579:14;22575:29;22571:43;22551:18;22547:68;22537:96;;22629:1;22626;22619:12;22537:96;22656:33;;22708:20;;;-1:-1:-1;22751:18:1;22740:30;;22737:50;;;22783:1;22780;22773:12;22737:50;22816:4;22804:17;;-1:-1:-1;22867:1:1;22863:14;;;22847;22843:35;22833:46;;22830:66;;;22892:1;22889;22882:12;23457:125;23522:9;;;23543:10;;;23540:36;;;23556:18;;:::i;23587:492::-;23762:3;23800:6;23794:13;23816:66;23875:6;23870:3;23863:4;23855:6;23851:17;23816:66;:::i;:::-;23945:13;;23904:16;;;;23967:70;23945:13;23904:16;24014:4;24002:17;;23967:70;:::i;:::-;24053:20;;23587:492;-1:-1:-1;;;;23587:492:1:o;24867:266::-;24955:6;24950:3;24943:19;25007:6;25000:5;24993:4;24988:3;24984:14;24971:43;-1:-1:-1;25059:1:1;25034:16;;;25052:4;25030:27;;;25023:38;;;;25115:2;25094:15;;;-1:-1:-1;;25090:29:1;25081:39;;;25077:50;;24867:266::o;25138:518::-;-1:-1:-1;;;;;25377:6:1;25373:55;25362:9;25355:74;25465:6;25460:2;25449:9;25445:18;25438:34;25508:3;25503:2;25492:9;25488:18;25481:31;25336:4;25529:62;25586:3;25575:9;25571:19;25563:6;25555;25529:62;:::i;:::-;25521:70;;25641:6;25634:14;25627:22;25622:2;25611:9;25607:18;25600:50;25138:518;;;;;;;;:::o;25661:245::-;25728:6;25781:2;25769:9;25760:7;25756:23;25752:32;25749:52;;;25797:1;25794;25787:12;25749:52;25829:9;25823:16;25848:28;25870:5;25848:28;:::i;25911:543::-;26129:13;;26072:3;;26103;;26182:4;26209:15;;;26072:3;26252:175;26266:6;26263:1;26260:13;26252:175;;;26329:13;;26315:28;;26365:14;;;;26402:15;;;;26288:1;26281:9;26252:175;;;-1:-1:-1;26443:5:1;;25911:543;-1:-1:-1;;;;;;25911:543:1:o;26459:276::-;26517:6;26570:2;26558:9;26549:7;26545:23;26541:32;26538:52;;;26586:1;26583;26576:12;26538:52;26625:9;26612:23;26675:10;26668:5;26664:22;26657:5;26654:33;26644:61;;26701:1;26698;26691:12;26740:241;26796:6;26849:2;26837:9;26828:7;26824:23;26820:32;26817:52;;;26865:1;26862;26855:12;26817:52;26904:9;26891:23;26923:28;26945:5;26923:28;:::i;27623:859::-;27975:21;27970:3;27963:34;27945:3;28026:6;28020:13;28042:75;28110:6;28105:2;28100:3;28096:12;28089:4;28081:6;28077:17;28042:75;:::i;:::-;28177:13;;28136:16;;;;28199:76;28177:13;28261:2;28253:11;;28246:4;28234:17;;28199:76;:::i;:::-;28336:13;;28294:17;;;28358:76;28336:13;28420:2;28412:11;;28405:4;28393:17;;28358:76;:::i;:::-;28454:17;28473:2;28450:26;;27623:859;-1:-1:-1;;;;;27623:859:1:o;28698:1111::-;29134:4;29163:3;29175:60;29225:9;29216:6;29210:13;28573:12;;-1:-1:-1;;;;;28569:61:1;28557:74;;28680:4;28669:16;;;28663:23;28647:14;;28640:47;28487:206;29175:60;29291:4;29283:6;29279:17;29273:24;29266:4;29255:9;29251:20;29244:54;29354:4;29346:6;29342:17;29336:24;29329:4;29318:9;29314:20;29307:54;29370:63;29428:3;29417:9;29413:19;29405:6;28573:12;;-1:-1:-1;;;;;28569:61:1;28557:74;;28680:4;28669:16;;;28663:23;28647:14;;28640:47;28487:206;29370:63;-1:-1:-1;;;;;29474:6:1;29470:55;29464:3;29453:9;29449:19;29442:84;29563:6;29557:3;29546:9;29542:19;29535:35;29607:2;29601:3;29590:9;29586:19;29579:31;29633:44;29673:2;29662:9;29658:18;29650:6;29633:44;:::i;:::-;29619:58;;29726:9;29718:6;29714:22;29708:3;29697:9;29693:19;29686:51;29754:49;29796:6;29788;29780;29754:49;:::i;29814:864::-;30166:26;30161:3;30154:39;30136:3;30222:6;30216:13;30238:75;30306:6;30301:2;30296:3;30292:12;30285:4;30277:6;30273:17;30238:75;:::i;:::-;30373:13;;30332:16;;;;30395:76;30373:13;30457:2;30449:11;;30442:4;30430:17;;30395:76;:::i;:::-;30532:13;;30490:17;;;30554:76;30532:13;30616:2;30608:11;;30601:4;30589:17;;30554:76;:::i;:::-;30650:17;30669:2;30646:26;;29814:864;-1:-1:-1;;;;;29814:864:1:o;30683:489::-;30760:3;30798:5;30792:12;30825:6;30820:3;30813:19;30851:4;30880:2;30875:3;30871:12;30864:19;;30917:2;30910:5;30906:14;30938:1;30948:199;30962:6;30959:1;30956:13;30948:199;;;31011:54;31061:3;31052:6;31046:13;28573:12;;-1:-1:-1;;;;;28569:61:1;28557:74;;28680:4;28669:16;;;28663:23;28647:14;;28640:47;28487:206;31011:54;31094:4;31085:14;;;;;31122:15;;;;30984:1;30977:9;30948:199;;31177:1706;31710:3;31699:9;31692:22;31673:4;31752:3;31741:9;31737:19;31791:6;31785:13;31835:4;31829:3;31818:9;31814:19;31807:33;31860:6;31895:12;31889:19;31932:6;31924;31917:22;31970:3;31959:9;31955:19;31948:26;;31993:4;31983:14;;32038:2;32024:12;32020:21;32006:35;;32059:1;32069:199;32083:6;32080:1;32077:13;32069:199;;;32132:54;32182:3;32173:6;32167:13;28573:12;;-1:-1:-1;;;;;28569:61:1;28557:74;;28680:4;28669:16;;;28663:23;28647:14;;28640:47;28487:206;32132:54;32243:15;;;;32215:4;32206:14;;;;;32105:1;32098:9;32069:199;;;32073:3;;32323:2;32315:6;32311:15;32305:22;32299:3;32288:9;32284:19;32277:51;32383:4;32375:6;32371:17;32365:24;32359:3;32348:9;32344:19;32337:53;32435:9;32430:3;32426:19;32421:2;32410:9;32406:18;32399:47;32469:65;32530:3;32522:6;32469:65;:::i;:::-;32455:79;;;;32543:48;32585:4;32574:9;32570:20;32562:6;-1:-1:-1;;;;;8010:54:1;7998:67;;7944:127;32543:48;32629:6;32622:4;32611:9;32607:20;32600:36;32685:9;32677:6;32673:22;32667:3;32656:9;32652:19;32645:51;32719:32;32744:6;32736;32719:32;:::i;:::-;32705:46;;32800:9;32792:6;32788:22;32782:3;32771:9;32767:19;32760:51;32828:49;32870:6;32862;32854;32828:49;:::i;32888:568::-;33151:2;33140:9;33133:21;33114:4;33177:61;33234:2;33223:9;33219:18;33211:6;33203;33177:61;:::i;:::-;33286:9;33278:6;33274:22;33269:2;33258:9;33254:18;33247:50;33314:44;33351:6;33343;33314:44;:::i;:::-;33306:52;;;-1:-1:-1;;;;;33398:6:1;33394:55;33389:2;33378:9;33374:18;33367:83;32888:568;;;;;;;:::o;33834:484::-;33887:3;33925:5;33919:12;33952:6;33947:3;33940:19;33978:4;34007:2;34002:3;33998:12;33991:19;;34044:2;34037:5;34033:14;34065:1;34075:218;34089:6;34086:1;34083:13;34075:218;;;34154:13;;-1:-1:-1;;;;;34150:62:1;34138:75;;34233:12;;;;34268:15;;;;34111:1;34104:9;34075:218;;34323:1138;34761:4;34790:3;-1:-1:-1;;;;;34893:2:1;34885:6;34881:15;34870:9;34863:34;34933:2;34928;34917:9;34913:18;34906:30;34959:56;35011:2;35000:9;34996:18;34988:6;34959:56;:::i;:::-;34945:70;;35063:9;35055:6;35051:22;35046:2;35035:9;35031:18;35024:50;35097:44;35134:6;35126;35097:44;:::i;:::-;35083:58;;35189:9;35181:6;35177:22;35172:2;35161:9;35157:18;35150:50;35217:44;35254:6;35246;35217:44;:::i;:::-;35298:15;;;35292:3;35277:19;;35270:44;35345:3;35330:19;;35323:35;;;;-1:-1:-1;;35395:15:1;;;;35389:3;35374:19;;35367:44;35442:3;35427:19;35420:35;35209:52;34323:1138;-1:-1:-1;;;;34323:1138:1:o;35719:184::-;-1:-1:-1;;;35768:1:1;35761:88;35868:4;35865:1;35858:15;35892:4;35889:1;35882:15;35908:435;36121:6;36110:9;36103:25;-1:-1:-1;;;;;36168:6:1;36164:55;36159:2;36148:9;36144:18;36137:83;36256:2;36251;36240:9;36236:18;36229:30;36084:4;36276:61;36333:2;36322:9;36318:18;36310:6;36302;36276:61;:::i;:::-;36268:69;35908:435;-1:-1:-1;;;;;;35908:435:1:o;37760:168::-;37833:9;;;37864;;37881:15;;;37875:22;;37861:37;37851:71;;37902:18;;:::i;37933:274::-;37973:1;37999;37989:189;;-1:-1:-1;;;38031:1:1;38024:88;38135:4;38132:1;38125:15;38163:4;38160:1;38153:15;37989:189;-1:-1:-1;38192:9:1;;37933:274::o;38409:818::-;38509:6;38562:2;38550:9;38541:7;38537:23;38533:32;38530:52;;;38578:1;38575;38568:12;38530:52;38611:2;38605:9;38653:2;38645:6;38641:15;38675:18;38743:6;38731:10;38728:22;38723:2;38711:10;38708:18;38705:46;38702:72;;;38754:18;;:::i;:::-;38794:10;38790:2;38783:22;38833:9;38827:16;38814:29;;38883:2;38876:5;38872:14;38865:5;38862:25;38852:53;;38901:1;38898;38891:12;38852:53;-1:-1:-1;38914:21:1;;38980:2;38965:18;;38959:25;38993:33;38959:25;38993:33;:::i;:::-;39054:2;39042:15;;39035:32;39112:2;39097:18;;39091:25;39125:30;39091:25;39125:30;:::i;:::-;39183:2;39171:15;;39164:32;39175:6;38409:818;-1:-1:-1;;;38409:818:1:o;40082:358::-;40182:6;40177:3;40170:19;40152:3;40212:66;40204:6;40201:78;40198:98;;;40292:1;40289;40282:12;40198:98;40328:6;40325:1;40321:14;40380:8;40373:5;40366:4;40361:3;40357:14;40344:45;40409:18;;;;40429:4;40405:29;;40082:358;-1:-1:-1;;;40082:358:1:o;40445:595::-;40718:2;40707:9;40700:21;40681:4;40744:61;40801:2;40790:9;40786:18;40778:6;40770;40744:61;:::i;:::-;40853:9;40845:6;40841:22;40836:2;40825:9;40821:18;40814:50;40881:61;40935:6;40927;40919;40881:61;:::i;:::-;40873:69;;;-1:-1:-1;;;;;40982:6:1;40978:55;40973:2;40962:9;40958:18;40951:83;40445:595;;;;;;;;:::o;41045:1696::-;41719:4;41748:3;41778:2;41767:9;41760:21;41804:56;41856:2;41845:9;41841:18;41833:6;41804:56;:::i;:::-;41790:70;;41908:9;41900:6;41896:22;41891:2;41880:9;41876:18;41869:50;41942:44;41979:6;41971;41942:44;:::i;:::-;41928:58;;42034:9;42026:6;42022:22;42017:2;42006:9;42002:18;41995:50;42068:44;42105:6;42097;42068:44;:::i;:::-;42054:58;;42160:9;42152:6;42148:22;42143:2;42132:9;42128:18;42121:50;42194:44;42231:6;42223;42194:44;:::i;:::-;42180:58;;42287:9;42279:6;42275:22;42269:3;42258:9;42254:19;42247:51;42321:61;42375:6;42367;42359;42321:61;:::i;:::-;42307:75;;42431:9;42423:6;42419:22;42413:3;42402:9;42398:19;42391:51;42465:44;42502:6;42494;42465:44;:::i;:::-;42451:58;;42558:9;42550:6;42546:22;42540:3;42529:9;42525:19;42518:51;42586:44;42623:6;42615;42586:44;:::i;:::-;42679:10;42667:23;;;;42661:3;42646:19;;42639:52;-1:-1:-1;;42722:3:1;42707:19;42700:35;42578:52;41045:1696;-1:-1:-1;;;;;;;;41045:1696:1:o;43107:437::-;43186:1;43182:12;;;;43229;;;43250:61;;43304:4;43296:6;43292:17;43282:27;;43250:61;43357:2;43349:6;43346:14;43326:18;43323:38;43320:218;;-1:-1:-1;;;43391:1:1;43384:88;43495:4;43492:1;43485:15;43523:4;43520:1;43513:15
Swarm Source
ipfs://f93fc380960244e11e14b61a78d7a48923f3a724e980562df529c93b2a7883e7
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
AVAX | 67.91% | $0.999994 | 2,143.8022 | $2,143.79 | |
AVAX | 18.25% | $0.999994 | 576.1467 | $576.14 | |
AVAX | 8.99% | $39.71 | 7.1489 | $283.9 | |
AVAX | 1.29% | $0.383113 | 106.4683 | $40.79 | |
AVAX | 1.03% | $100,029 | 0.00032512 | $32.52 | |
AVAX | 0.72% | $99,672 | 0.00022768 | $22.69 | |
AVAX | 0.54% | $47.1 | 0.3644 | $17.16 | |
AVAX | 0.43% | $1 | 13.554 | $13.56 | |
AVAX | 0.40% | $0.999429 | 12.7468 | $12.74 | |
AVAX | 0.25% | $1 | 7.9337 | $7.93 | |
AVAX | 0.18% | $3,436.51 | 0.00168403 | $5.79 |
[ 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.