Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
LargeOracle
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-09-16 */ // File: @openzeppelin/[email protected]/utils/Address.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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); } } } // File: @openzeppelin/[email protected]/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } } // File: @openzeppelin/[email protected]/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @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); } } } // File: @openzeppelin/[email protected]/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @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); } } } // File: @openzeppelin/[email protected]/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @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)); } } // File: @openzeppelin/[email protected]/utils/cryptography/ECDSA.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; /** * @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)); } } // File: contracts/LargeOracleInterface.sol pragma solidity ^0.8.6; /*- * #%L * byoc-contract-eth * %% * Copyright (C) 2022 Partisia Blockchain Foundation * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ /** * Interface for accessing information about LargeOracle updates. */ abstract contract LargeOracleInterface { /// @param nonce the nonce associated update request /// @param digest the digest which was signed /// @param signature the signature function verifyUpdate(uint64 nonce, bytes32 digest, bytes calldata signature) public virtual view returns (bool); /// @notice Verify that the supplied signature is signed by the current large oracle /// @param digest the digest which was signed /// @param signature the signature function verifyContractUpdate(bytes32 digest, bytes calldata signature) public virtual view returns (bool); } // File: @openzeppelin/[email protected]/interfaces/draft-IERC1822.sol // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } // File: @openzeppelin/[email protected]/proxy/beacon/IBeacon.sol // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } // File: @openzeppelin/[email protected]/interfaces/IERC1967.sol // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); } // File: @openzeppelin/[email protected]/utils/StorageSlot.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @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 } } } // File: @openzeppelin/[email protected]/proxy/ERC1967/ERC1967Upgrade.sol // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } } // File: contracts/LargeOracleUpgradeable.sol pragma solidity ^0.8.6; /*- * #%L * byoc-contract-eth * %% * Copyright (C) 2022 Partisia Blockchain Foundation * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ /** * Contract upgradable by the large oracle. Based on UUPSUpgradable from OpenZeppelin. */ abstract contract LargeOracleUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __SELF = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __SELF, "must be through delegatecall"); require(_getImplementation() == __SELF, "must be through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __SELF, "must not be through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate that the this implementation remains valid after an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(bytes calldata signature, address newImplementation) external virtual onlyProxy { bytes32 message = sha256(abi.encodePacked(address(this), _getImplementation(), newImplementation)); require(_largeOracle().verifyContractUpdate(message, signature), "Invalid signature"); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } function _largeOracle() internal virtual view returns (LargeOracleInterface); } // File: contracts/LargeOracle.sol pragma solidity ^0.8.6; /*- * #%L * byoc-contract-eth * %% * Copyright (C) 2022 Partisia Blockchain Foundation * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ /// @title The contract responsible for verifying new small oracles contract LargeOracle is LargeOracleInterface, LargeOracleUpgradeable, Initializable { struct Oracle { uint32 size; bytes32 merkleRoot; address oracle; } bytes32 private domainSeparator; uint64 public largeNonce; mapping(uint64 => Oracle) public oracleMap; // Keeps track of signers in the case of an exceptional update. mapping(uint64 => mapping(address => bool)) private exceptionalUpdates; mapping(bytes32 => uint32) private signatureCounters; constructor() { _disableInitializers(); } /// @param _size the size of the initial oracle /// @param _merkleRoot merkle root for oracle members /// @param _oracle large oracle address function initialize(uint32 _size, bytes32 _merkleRoot, address _oracle, bytes32 _domainSeparator) external initializer { largeNonce = 0; oracleMap[largeNonce] = Oracle(_size, _merkleRoot, _oracle); domainSeparator = _domainSeparator; } /// @notice Updates the large oracle by presenting a signature from the current oracle /// @param newSize size of the new oracle /// @param newMerkleRoot root of the tree with new oracle nodes /// @param newOracle the new oracle /// @param signature a signature from the previous oracle on the new one function update(uint32 newSize, bytes32 newMerkleRoot, bytes calldata newOracle, bytes calldata signature) external { uint64 newLargeNonce = largeNonce + 1; bytes32 digest = computeDigest(newLargeNonce, newSize, newMerkleRoot, newOracle); require(verifyUpdate(largeNonce, digest, signature), "Invalid signature"); executeUpdate(newLargeNonce, newSize, newMerkleRoot, newOracle); } /// @notice provides a means to update the large oracle in case the threshold key is broken /// @param newSize size of the new oracle /// @param newMerkleRoot root of the tree with new oracle nodes /// @param newOracle the new oracle /// @param signerPbcKey the uncompressed key of the signer /// @param proof a proof that the caller is part of the current oracle /// @param signature signature by caller on the new oracle function updateExceptional( uint32 newSize, bytes32 newMerkleRoot, bytes calldata newOracle, bytes calldata signerPbcKey, bytes32[] memory proof, bytes calldata signature) external { uint64 newLargeNonce = largeNonce + 1; bytes32 digest = computeDigest(newLargeNonce, newSize, newMerkleRoot, newOracle); address signer = ECDSA.recover(digest, signature); require(keyToAddress(signerPbcKey) == signer, "Incorrect key provided"); // A particular oracle node is only allowed to "vote" on one oracle update per nonce. When // a particular update for this nonce gets 2t+1 votes, then that oracle becomes the new one. require(!exceptionalUpdates[newLargeNonce][signer], "Signer already signed this nonce"); exceptionalUpdates[newLargeNonce][signer] = true; Oracle memory currentOracle = oracleMap[largeNonce]; require(verifyMerkleProof(proof, currentOracle.merkleRoot, signerPbcKey), "Signer not part of oracle"); // initial value is guaranteed to be zero, so this makes sense. signatureCounters[digest] += 1; // this threshold could probably just be t+1. if (signatureCounters[digest] > 2 * (currentOracle.size / 3)) { executeUpdate(newLargeNonce, newSize, newMerkleRoot, newOracle); } } // Based on @openzeppelin/contracts/utils/cryptography/MerkleProof.sol // This function asserts that the Merkle Tree has been build with sorted pairs // Slight adaption of code in the WithdrawAndDeposit contract function verifyMerkleProof(bytes32[] memory proof, bytes32 root, bytes calldata signer) private pure returns (bool) { bytes32 computedHash = sha256(abi.encodePacked(signer)); for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = sha256(abi.encode(computedHash, proofElement)); } else { // Hash(current element of the proof + current computed hash) computedHash = sha256(abi.encode(proofElement, computedHash)); } } // Check if the computed hash (root) is equal to the provided root return computedHash == root; } /// @param nonce the nonce associated update request /// @param digest the digest which was signed /// @param signature the signature function verifyUpdate(uint64 nonce, bytes32 digest, bytes calldata signature) public view override returns (bool) { return oracleMap[nonce].oracle == ECDSA.recover(digest, signature); } /// @notice Verify that the supplied signature is signed by the current large oracle /// @param digest the digest which was signed /// @param signature the signature function verifyContractUpdate(bytes32 digest, bytes calldata signature) public view override returns (bool) { return verifyUpdate(largeNonce, digest, signature); } /// @notice Update the large oracle mapping. Called when an oracle update has been validated function executeUpdate(uint64 newLargeNonce, uint32 size, bytes32 merkleRoot, bytes calldata oracle) private { oracleMap[newLargeNonce] = Oracle( size, merkleRoot, keyToAddress(oracle) ); largeNonce = newLargeNonce; } /// @notice Compute the digest that the large oracle signs when updating to a new large oracle function computeDigest(uint64 nonce, uint32 size, bytes32 merkleRoot, bytes calldata oracle) private view returns (bytes32) { return sha256(abi.encodePacked(domainSeparator, nonce, size, merkleRoot, oracle)); } /// @notice convert an off-chain key to an ETH address function keyToAddress(bytes calldata key) private pure returns (address) { return address(uint160(uint256(keccak256(key)))); } function _largeOracle() internal virtual view override returns (LargeOracleInterface) { return LargeOracleInterface(address(this)); } }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"uint32","name":"_size","type":"uint32"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"bytes32","name":"_domainSeparator","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"largeNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"oracleMap","outputs":[{"internalType":"uint32","name":"size","type":"uint32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"address","name":"oracle","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"newSize","type":"uint32"},{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"},{"internalType":"bytes","name":"newOracle","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newSize","type":"uint32"},{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"},{"internalType":"bytes","name":"newOracle","type":"bytes"},{"internalType":"bytes","name":"signerPbcKey","type":"bytes"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateExceptional","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"digest","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"verifyContractUpdate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"bytes32","name":"digest","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"verifyUpdate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523073ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff1660601b8152503480156200004757600080fd5b50620000586200005e60201b60201c565b62000208565b600060019054906101000a900460ff1615620000b1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000a8906200015c565b60405180910390fd5b60ff801660008054906101000a900460ff1660ff1614620001225760ff6000806101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff6040516200011991906200017e565b60405180910390a15b565b6000620001336027836200019b565b91506200014082620001b9565b604082019050919050565b6200015681620001ac565b82525050565b60006020820190508181036000830152620001778162000124565b9050919050565b60006020820190506200019560008301846200014b565b92915050565b600082825260208201905092915050565b600060ff82169050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b60805160601c612e2462000235600039600081816102ac0152818161086c01526108fb0152612e246000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806394d23fc61161006657806394d23fc614610120578063a7c5b1111461013c578063b81f853c1461016c578063c9d9096e14610188578063d4eec37f146101a457610093565b80631d574bc61461009857806352d1902d146100c85780638a0a7a22146100e657806391c3833b14610102575b600080fd5b6100b260048036038101906100ad9190611dc4565b6101d6565b6040516100bf9190612290565b60405180910390f35b6100d06102a8565b6040516100dd91906122ab565b60405180910390f35b61010060048036038101906100fb9190611c8c565b610361565b005b61010a610773565b60405161011791906125ba565b60405180910390f35b61013a60048036038101906101359190611be5565b61078d565b005b61015660048036038101906101519190611abe565b61083d565b6040516101639190612290565b60405180910390f35b61018660048036038101906101819190611b1e565b61086a565b005b6101a2600480360381019061019d9190611b7e565b610b3e565b005b6101be60048036038101906101b99190611d97565b610d98565b6040516101cd93929190612583565b60405180910390f35b60006102268484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610df2565b73ffffffffffffffffffffffffffffffffffffffff16600360008767ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614610338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032f90612563565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905090565b60006001600260009054906101000a900467ffffffffffffffff1661038691906126a3565b90506000610397828c8c8c8c610e19565b905060006103e98286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610df2565b90508073ffffffffffffffffffffffffffffffffffffffff1661040c8989610ea1565b73ffffffffffffffffffffffffffffffffffffffff1614610462576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045990612403565b60405180910390fd5b600460008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050b906124a3565b60405180910390fd5b6001600460008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600060036000600260009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506106738782602001518b8b610ec6565b6106b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a990612503565b60405180910390fd5b60016005600085815260200190815260200160002060008282829054906101000a900463ffffffff166106e59190612669565b92506101000a81548163ffffffff021916908363ffffffff1602179055506003816000015161071491906126e1565b60026107209190612712565b63ffffffff166005600085815260200190815260200160002060009054906101000a900463ffffffff1663ffffffff16111561076457610763848e8e8e8e61107d565b5b50505050505050505050505050565b600260009054906101000a900467ffffffffffffffff1681565b60006001600260009054906101000a900467ffffffffffffffff166107b291906126a3565b905060006107c38289898989610e19565b90506107e7600260009054906101000a900467ffffffffffffffff168286866101d6565b610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081d90612423565b60405180910390fd5b610833828989898961107d565b5050505050505050565b6000610861600260009054906101000a900467ffffffffffffffff168585856101d6565b90509392505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614156108f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f090612523565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661093861118f565b73ffffffffffffffffffffffffffffffffffffffff161461098e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610985906123c3565b60405180910390fd5b600060023061099b61118f565b846040516020016109ae939291906121c6565b6040516020818303038152906040526040516109ca9190612279565b602060405180830381855afa1580156109e7573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610a0a9190611a91565b9050610a146111e6565b73ffffffffffffffffffffffffffffffffffffffff1663a7c5b1118286866040518463ffffffff1660e01b8152600401610a50939291906122ef565b60206040518083038186803b158015610a6857600080fd5b505afa158015610a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa09190611a64565b610adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad690612423565b60405180910390fd5b610b3882600067ffffffffffffffff811115610afe57610afd6129af565b5b6040519080825280601f01601f191660200182016040528015610b305781602001600182028036833780820191505090505b5060006111ee565b50505050565b60008060019054906101000a900460ff16159050808015610b6f5750600160008054906101000a900460ff1660ff16105b80610b9c5750610b7e3061136b565b158015610b9b5750600160008054906101000a900460ff1660ff16145b5b610bdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd290612483565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015610c18576001600060016101000a81548160ff0219169083151502179055505b6000600260006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060405180606001604052808663ffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681525060036000600260009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff1602179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050816001819055508015610d915760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024986001604051610d889190612366565b60405180910390a15b5050505050565b60036020528060005260406000206000915090508060000160009054906101000a900463ffffffff16908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b6000806000610e01858561138e565b91509150610e0e816113e0565b819250505092915050565b600060026001548787878787604051602001610e3a96959493929190612203565b604051602081830303815290604052604051610e569190612279565b602060405180830381855afa158015610e73573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610e969190611a91565b905095945050505050565b60008282604051610eb3929190612260565b604051809103902060001c905092915050565b60008060028484604051602001610ede929190612260565b604051602081830303815290604052604051610efa9190612279565b602060405180830381855afa158015610f17573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610f3a9190611a91565b905060005b865181101561106e576000878281518110610f5d57610f5c612980565b5b60200260200101519050808311610fe65760028382604051602001610f839291906122c6565b604051602081830303815290604052604051610f9f9190612279565b602060405180830381855afa158015610fbc573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610fdf9190611a91565b925061105a565b60028184604051602001610ffb9291906122c6565b6040516020818303038152906040526040516110179190612279565b602060405180830381855afa158015611034573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906110579190611a91565b92505b50808061106690612858565b915050610f3f565b50848114915050949350505050565b60405180606001604052808563ffffffff1681526020018481526020016110a48484610ea1565b73ffffffffffffffffffffffffffffffffffffffff16815250600360008767ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff1602179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555090505084600260006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505050505050565b60006111bd7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61154e565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600030905090565b61121a7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b611558565b60000160009054906101000a900460ff161561123e5761123983611562565b611366565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561128457600080fd5b505afa9250505080156112b557506040513d601f19601f820116820180604052508101906112b29190611a91565b60015b6112f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112eb906124c3565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b8114611359576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135090612463565b60405180910390fd5b5061136583838361161b565b5b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000806041835114156113d05760008060006020860151925060408601519150606086015160001a90506113c487828585611647565b945094505050506113d9565b60006002915091505b9250929050565b600060048111156113f4576113f3612951565b5b81600481111561140757611406612951565b5b14156114125761154b565b6001600481111561142657611425612951565b5b81600481111561143957611438612951565b5b141561147a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611471906123a3565b60405180910390fd5b6002600481111561148e5761148d612951565b5b8160048111156114a1576114a0612951565b5b14156114e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d9906123e3565b60405180910390fd5b600360048111156114f6576114f5612951565b5b81600481111561150957611508612951565b5b141561154a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154190612443565b60405180910390fd5b5b50565b6000819050919050565b6000819050919050565b61156b8161136b565b6115aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a1906124e3565b60405180910390fd5b806115d77f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61154e565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6116248361172a565b6000825111806116315750805b15611642576116408383611779565b505b505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c1115611682576000600391509150611721565b6000600187878787604051600081526020016040526040516116a79493929190612321565b6020604051602081039080840390855afa1580156116c9573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561171857600060019250925050611721565b80600092509250505b94509492505050565b61173381611562565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b606061179e8383604051806060016040528060278152602001612dc8602791396117a6565b905092915050565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516117d09190612279565b600060405180830381855af49150503d806000811461180b576040519150601f19603f3d011682016040523d82523d6000602084013e611810565b606091505b50915091506118218683838761182c565b925050509392505050565b6060831561188f57600083511415611887576118478561136b565b611886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187d90612543565b60405180910390fd5b5b82905061189a565b61189983836118a2565b5b949350505050565b6000825111156118b55781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118e99190612381565b60405180910390fd5b6000611905611900846125fa565b6125d5565b90508083825260208201905082856020860282011115611928576119276129e8565b5b60005b85811015611958578161193e88826119ba565b84526020840193506020830192505060018101905061192b565b5050509392505050565b60008135905061197181612d54565b92915050565b600082601f83011261198c5761198b6129e3565b5b813561199c8482602086016118f2565b91505092915050565b6000815190506119b481612d6b565b92915050565b6000813590506119c981612d82565b92915050565b6000815190506119de81612d82565b92915050565b60008083601f8401126119fa576119f96129e3565b5b8235905067ffffffffffffffff811115611a1757611a166129de565b5b602083019150836001820283011115611a3357611a326129e8565b5b9250929050565b600081359050611a4981612d99565b92915050565b600081359050611a5e81612db0565b92915050565b600060208284031215611a7a57611a796129f2565b5b6000611a88848285016119a5565b91505092915050565b600060208284031215611aa757611aa66129f2565b5b6000611ab5848285016119cf565b91505092915050565b600080600060408486031215611ad757611ad66129f2565b5b6000611ae5868287016119ba565b935050602084013567ffffffffffffffff811115611b0657611b056129ed565b5b611b12868287016119e4565b92509250509250925092565b600080600060408486031215611b3757611b366129f2565b5b600084013567ffffffffffffffff811115611b5557611b546129ed565b5b611b61868287016119e4565b93509350506020611b7486828701611962565b9150509250925092565b60008060008060808587031215611b9857611b976129f2565b5b6000611ba687828801611a3a565b9450506020611bb7878288016119ba565b9350506040611bc887828801611962565b9250506060611bd9878288016119ba565b91505092959194509250565b60008060008060008060808789031215611c0257611c016129f2565b5b6000611c1089828a01611a3a565b9650506020611c2189828a016119ba565b955050604087013567ffffffffffffffff811115611c4257611c416129ed565b5b611c4e89828a016119e4565b9450945050606087013567ffffffffffffffff811115611c7157611c706129ed565b5b611c7d89828a016119e4565b92509250509295509295509295565b600080600080600080600080600060c08a8c031215611cae57611cad6129f2565b5b6000611cbc8c828d01611a3a565b9950506020611ccd8c828d016119ba565b98505060408a013567ffffffffffffffff811115611cee57611ced6129ed565b5b611cfa8c828d016119e4565b975097505060608a013567ffffffffffffffff811115611d1d57611d1c6129ed565b5b611d298c828d016119e4565b955095505060808a013567ffffffffffffffff811115611d4c57611d4b6129ed565b5b611d588c828d01611977565b93505060a08a013567ffffffffffffffff811115611d7957611d786129ed565b5b611d858c828d016119e4565b92509250509295985092959850929598565b600060208284031215611dad57611dac6129f2565b5b6000611dbb84828501611a4f565b91505092915050565b60008060008060608587031215611dde57611ddd6129f2565b5b6000611dec87828801611a4f565b9450506020611dfd878288016119ba565b935050604085013567ffffffffffffffff811115611e1e57611e1d6129ed565b5b611e2a878288016119e4565b925092505092959194509250565b611e4181612750565b82525050565b611e58611e5382612750565b6128a1565b82525050565b611e6781612762565b82525050565b611e768161276e565b82525050565b611e8d611e888261276e565b6128b3565b82525050565b6000611e9f838561263c565b9350611eac8385846127e5565b611eb5836129f7565b840190509392505050565b6000611ecc838561264d565b9350611ed98385846127e5565b82840190509392505050565b6000611ef082612626565b611efa818561264d565b9350611f0a8185602086016127f4565b80840191505092915050565b611f1f816127d3565b82525050565b6000611f3082612631565b611f3a8185612658565b9350611f4a8185602086016127f4565b611f53816129f7565b840191505092915050565b6000611f6b601883612658565b9150611f7682612a2f565b602082019050919050565b6000611f8e601c83612658565b9150611f9982612a58565b602082019050919050565b6000611fb1601f83612658565b9150611fbc82612a81565b602082019050919050565b6000611fd4601683612658565b9150611fdf82612aaa565b602082019050919050565b6000611ff7601183612658565b915061200282612ad3565b602082019050919050565b600061201a602283612658565b915061202582612afc565b604082019050919050565b600061203d602983612658565b915061204882612b4b565b604082019050919050565b6000612060602e83612658565b915061206b82612b9a565b604082019050919050565b6000612083602083612658565b915061208e82612be9565b602082019050919050565b60006120a6602e83612658565b91506120b182612c12565b604082019050919050565b60006120c9602d83612658565b91506120d482612c61565b604082019050919050565b60006120ec601983612658565b91506120f782612cb0565b602082019050919050565b600061210f601c83612658565b915061211a82612cd9565b602082019050919050565b6000612132601d83612658565b915061213d82612d02565b602082019050919050565b6000612155602083612658565b915061216082612d2b565b602082019050919050565b612174816127a2565b82525050565b61218b612186826127a2565b6128cf565b82525050565b61219a816127b2565b82525050565b6121b16121ac826127b2565b6128e1565b82525050565b6121c0816127c6565b82525050565b60006121d28286611e47565b6014820191506121e28285611e47565b6014820191506121f28284611e47565b601482019150819050949350505050565b600061220f8289611e7c565b60208201915061221f82886121a0565b60088201915061222f828761217a565b60048201915061223f8286611e7c565b602082019150612250828486611ec0565b9150819050979650505050505050565b600061226d828486611ec0565b91508190509392505050565b60006122858284611ee5565b915081905092915050565b60006020820190506122a56000830184611e5e565b92915050565b60006020820190506122c06000830184611e6d565b92915050565b60006040820190506122db6000830185611e6d565b6122e86020830184611e6d565b9392505050565b60006040820190506123046000830186611e6d565b8181036020830152612317818486611e93565b9050949350505050565b60006080820190506123366000830187611e6d565b61234360208301866121b7565b6123506040830185611e6d565b61235d6060830184611e6d565b95945050505050565b600060208201905061237b6000830184611f16565b92915050565b6000602082019050818103600083015261239b8184611f25565b905092915050565b600060208201905081810360008301526123bc81611f5e565b9050919050565b600060208201905081810360008301526123dc81611f81565b9050919050565b600060208201905081810360008301526123fc81611fa4565b9050919050565b6000602082019050818103600083015261241c81611fc7565b9050919050565b6000602082019050818103600083015261243c81611fea565b9050919050565b6000602082019050818103600083015261245c8161200d565b9050919050565b6000602082019050818103600083015261247c81612030565b9050919050565b6000602082019050818103600083015261249c81612053565b9050919050565b600060208201905081810360008301526124bc81612076565b9050919050565b600060208201905081810360008301526124dc81612099565b9050919050565b600060208201905081810360008301526124fc816120bc565b9050919050565b6000602082019050818103600083015261251c816120df565b9050919050565b6000602082019050818103600083015261253c81612102565b9050919050565b6000602082019050818103600083015261255c81612125565b9050919050565b6000602082019050818103600083015261257c81612148565b9050919050565b6000606082019050612598600083018661216b565b6125a56020830185611e6d565b6125b26040830184611e38565b949350505050565b60006020820190506125cf6000830184612191565b92915050565b60006125df6125f0565b90506125eb8282612827565b919050565b6000604051905090565b600067ffffffffffffffff821115612615576126146129af565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000612674826127a2565b915061267f836127a2565b92508263ffffffff03821115612698576126976128f3565b5b828201905092915050565b60006126ae826127b2565b91506126b9836127b2565b92508267ffffffffffffffff038211156126d6576126d56128f3565b5b828201905092915050565b60006126ec826127a2565b91506126f7836127a2565b92508261270757612706612922565b5b828204905092915050565b600061271d826127a2565b9150612728836127a2565b92508163ffffffff0483118215151615612745576127446128f3565b5b828202905092915050565b600061275b82612778565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600063ffffffff82169050919050565b600067ffffffffffffffff82169050919050565b600060ff82169050919050565b60006127de826127c6565b9050919050565b82818337600083830152505050565b60005b838110156128125780820151818401526020810190506127f7565b83811115612821576000848401525b50505050565b612830826129f7565b810181811067ffffffffffffffff8211171561284f5761284e6129af565b5b80604052505050565b600061286382612798565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612896576128956128f3565b5b600182019050919050565b60006128ac826128bd565b9050919050565b6000819050919050565b60006128c882612a22565b9050919050565b60006128da82612a15565b9050919050565b60006128ec82612a08565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160c01b9050919050565b60008160e01b9050919050565b60008160601b9050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f6d757374206265207468726f756768206163746976652070726f787900000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b7f496e636f7272656374206b65792070726f766964656400000000000000000000600082015250565b7f496e76616c6964207369676e6174757265000000000000000000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524331393637557067726164653a20756e737570706f727465642070726f7860008201527f6961626c65555549440000000000000000000000000000000000000000000000602082015250565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b7f5369676e657220616c7265616479207369676e65642074686973206e6f6e6365600082015250565b7f45524331393637557067726164653a206e657720696d706c656d656e7461746960008201527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015250565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b7f5369676e6572206e6f742070617274206f66206f7261636c6500000000000000600082015250565b7f6d757374206265207468726f7567682064656c656761746563616c6c00000000600082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f6d757374206e6f74206265207468726f7567682064656c656761746563616c6c600082015250565b612d5d81612750565b8114612d6857600080fd5b50565b612d7481612762565b8114612d7f57600080fd5b50565b612d8b8161276e565b8114612d9657600080fd5b50565b612da2816127a2565b8114612dad57600080fd5b50565b612db9816127b2565b8114612dc457600080fd5b5056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b705d12891615b70f2d820a30c851e0b256b66e7c52b0bbf11ee832245c3d38b64736f6c63430008060033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c806394d23fc61161006657806394d23fc614610120578063a7c5b1111461013c578063b81f853c1461016c578063c9d9096e14610188578063d4eec37f146101a457610093565b80631d574bc61461009857806352d1902d146100c85780638a0a7a22146100e657806391c3833b14610102575b600080fd5b6100b260048036038101906100ad9190611dc4565b6101d6565b6040516100bf9190612290565b60405180910390f35b6100d06102a8565b6040516100dd91906122ab565b60405180910390f35b61010060048036038101906100fb9190611c8c565b610361565b005b61010a610773565b60405161011791906125ba565b60405180910390f35b61013a60048036038101906101359190611be5565b61078d565b005b61015660048036038101906101519190611abe565b61083d565b6040516101639190612290565b60405180910390f35b61018660048036038101906101819190611b1e565b61086a565b005b6101a2600480360381019061019d9190611b7e565b610b3e565b005b6101be60048036038101906101b99190611d97565b610d98565b6040516101cd93929190612583565b60405180910390f35b60006102268484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610df2565b73ffffffffffffffffffffffffffffffffffffffff16600360008767ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050949350505050565b60007f000000000000000000000000c4ec44acee77bc42ff647d4f60257dc887d5e81173ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614610338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032f90612563565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905090565b60006001600260009054906101000a900467ffffffffffffffff1661038691906126a3565b90506000610397828c8c8c8c610e19565b905060006103e98286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610df2565b90508073ffffffffffffffffffffffffffffffffffffffff1661040c8989610ea1565b73ffffffffffffffffffffffffffffffffffffffff1614610462576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045990612403565b60405180910390fd5b600460008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050b906124a3565b60405180910390fd5b6001600460008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600060036000600260009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506106738782602001518b8b610ec6565b6106b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a990612503565b60405180910390fd5b60016005600085815260200190815260200160002060008282829054906101000a900463ffffffff166106e59190612669565b92506101000a81548163ffffffff021916908363ffffffff1602179055506003816000015161071491906126e1565b60026107209190612712565b63ffffffff166005600085815260200190815260200160002060009054906101000a900463ffffffff1663ffffffff16111561076457610763848e8e8e8e61107d565b5b50505050505050505050505050565b600260009054906101000a900467ffffffffffffffff1681565b60006001600260009054906101000a900467ffffffffffffffff166107b291906126a3565b905060006107c38289898989610e19565b90506107e7600260009054906101000a900467ffffffffffffffff168286866101d6565b610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081d90612423565b60405180910390fd5b610833828989898961107d565b5050505050505050565b6000610861600260009054906101000a900467ffffffffffffffff168585856101d6565b90509392505050565b7f000000000000000000000000c4ec44acee77bc42ff647d4f60257dc887d5e81173ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614156108f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f090612523565b60405180910390fd5b7f000000000000000000000000c4ec44acee77bc42ff647d4f60257dc887d5e81173ffffffffffffffffffffffffffffffffffffffff1661093861118f565b73ffffffffffffffffffffffffffffffffffffffff161461098e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610985906123c3565b60405180910390fd5b600060023061099b61118f565b846040516020016109ae939291906121c6565b6040516020818303038152906040526040516109ca9190612279565b602060405180830381855afa1580156109e7573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610a0a9190611a91565b9050610a146111e6565b73ffffffffffffffffffffffffffffffffffffffff1663a7c5b1118286866040518463ffffffff1660e01b8152600401610a50939291906122ef565b60206040518083038186803b158015610a6857600080fd5b505afa158015610a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa09190611a64565b610adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad690612423565b60405180910390fd5b610b3882600067ffffffffffffffff811115610afe57610afd6129af565b5b6040519080825280601f01601f191660200182016040528015610b305781602001600182028036833780820191505090505b5060006111ee565b50505050565b60008060019054906101000a900460ff16159050808015610b6f5750600160008054906101000a900460ff1660ff16105b80610b9c5750610b7e3061136b565b158015610b9b5750600160008054906101000a900460ff1660ff16145b5b610bdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd290612483565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015610c18576001600060016101000a81548160ff0219169083151502179055505b6000600260006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060405180606001604052808663ffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681525060036000600260009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff1602179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050816001819055508015610d915760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024986001604051610d889190612366565b60405180910390a15b5050505050565b60036020528060005260406000206000915090508060000160009054906101000a900463ffffffff16908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b6000806000610e01858561138e565b91509150610e0e816113e0565b819250505092915050565b600060026001548787878787604051602001610e3a96959493929190612203565b604051602081830303815290604052604051610e569190612279565b602060405180830381855afa158015610e73573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610e969190611a91565b905095945050505050565b60008282604051610eb3929190612260565b604051809103902060001c905092915050565b60008060028484604051602001610ede929190612260565b604051602081830303815290604052604051610efa9190612279565b602060405180830381855afa158015610f17573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610f3a9190611a91565b905060005b865181101561106e576000878281518110610f5d57610f5c612980565b5b60200260200101519050808311610fe65760028382604051602001610f839291906122c6565b604051602081830303815290604052604051610f9f9190612279565b602060405180830381855afa158015610fbc573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610fdf9190611a91565b925061105a565b60028184604051602001610ffb9291906122c6565b6040516020818303038152906040526040516110179190612279565b602060405180830381855afa158015611034573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906110579190611a91565b92505b50808061106690612858565b915050610f3f565b50848114915050949350505050565b60405180606001604052808563ffffffff1681526020018481526020016110a48484610ea1565b73ffffffffffffffffffffffffffffffffffffffff16815250600360008767ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff1602179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555090505084600260006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505050505050565b60006111bd7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61154e565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600030905090565b61121a7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b611558565b60000160009054906101000a900460ff161561123e5761123983611562565b611366565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561128457600080fd5b505afa9250505080156112b557506040513d601f19601f820116820180604052508101906112b29190611a91565b60015b6112f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112eb906124c3565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b8114611359576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135090612463565b60405180910390fd5b5061136583838361161b565b5b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000806041835114156113d05760008060006020860151925060408601519150606086015160001a90506113c487828585611647565b945094505050506113d9565b60006002915091505b9250929050565b600060048111156113f4576113f3612951565b5b81600481111561140757611406612951565b5b14156114125761154b565b6001600481111561142657611425612951565b5b81600481111561143957611438612951565b5b141561147a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611471906123a3565b60405180910390fd5b6002600481111561148e5761148d612951565b5b8160048111156114a1576114a0612951565b5b14156114e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d9906123e3565b60405180910390fd5b600360048111156114f6576114f5612951565b5b81600481111561150957611508612951565b5b141561154a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154190612443565b60405180910390fd5b5b50565b6000819050919050565b6000819050919050565b61156b8161136b565b6115aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a1906124e3565b60405180910390fd5b806115d77f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61154e565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6116248361172a565b6000825111806116315750805b15611642576116408383611779565b505b505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c1115611682576000600391509150611721565b6000600187878787604051600081526020016040526040516116a79493929190612321565b6020604051602081039080840390855afa1580156116c9573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561171857600060019250925050611721565b80600092509250505b94509492505050565b61173381611562565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b606061179e8383604051806060016040528060278152602001612dc8602791396117a6565b905092915050565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516117d09190612279565b600060405180830381855af49150503d806000811461180b576040519150601f19603f3d011682016040523d82523d6000602084013e611810565b606091505b50915091506118218683838761182c565b925050509392505050565b6060831561188f57600083511415611887576118478561136b565b611886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187d90612543565b60405180910390fd5b5b82905061189a565b61189983836118a2565b5b949350505050565b6000825111156118b55781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118e99190612381565b60405180910390fd5b6000611905611900846125fa565b6125d5565b90508083825260208201905082856020860282011115611928576119276129e8565b5b60005b85811015611958578161193e88826119ba565b84526020840193506020830192505060018101905061192b565b5050509392505050565b60008135905061197181612d54565b92915050565b600082601f83011261198c5761198b6129e3565b5b813561199c8482602086016118f2565b91505092915050565b6000815190506119b481612d6b565b92915050565b6000813590506119c981612d82565b92915050565b6000815190506119de81612d82565b92915050565b60008083601f8401126119fa576119f96129e3565b5b8235905067ffffffffffffffff811115611a1757611a166129de565b5b602083019150836001820283011115611a3357611a326129e8565b5b9250929050565b600081359050611a4981612d99565b92915050565b600081359050611a5e81612db0565b92915050565b600060208284031215611a7a57611a796129f2565b5b6000611a88848285016119a5565b91505092915050565b600060208284031215611aa757611aa66129f2565b5b6000611ab5848285016119cf565b91505092915050565b600080600060408486031215611ad757611ad66129f2565b5b6000611ae5868287016119ba565b935050602084013567ffffffffffffffff811115611b0657611b056129ed565b5b611b12868287016119e4565b92509250509250925092565b600080600060408486031215611b3757611b366129f2565b5b600084013567ffffffffffffffff811115611b5557611b546129ed565b5b611b61868287016119e4565b93509350506020611b7486828701611962565b9150509250925092565b60008060008060808587031215611b9857611b976129f2565b5b6000611ba687828801611a3a565b9450506020611bb7878288016119ba565b9350506040611bc887828801611962565b9250506060611bd9878288016119ba565b91505092959194509250565b60008060008060008060808789031215611c0257611c016129f2565b5b6000611c1089828a01611a3a565b9650506020611c2189828a016119ba565b955050604087013567ffffffffffffffff811115611c4257611c416129ed565b5b611c4e89828a016119e4565b9450945050606087013567ffffffffffffffff811115611c7157611c706129ed565b5b611c7d89828a016119e4565b92509250509295509295509295565b600080600080600080600080600060c08a8c031215611cae57611cad6129f2565b5b6000611cbc8c828d01611a3a565b9950506020611ccd8c828d016119ba565b98505060408a013567ffffffffffffffff811115611cee57611ced6129ed565b5b611cfa8c828d016119e4565b975097505060608a013567ffffffffffffffff811115611d1d57611d1c6129ed565b5b611d298c828d016119e4565b955095505060808a013567ffffffffffffffff811115611d4c57611d4b6129ed565b5b611d588c828d01611977565b93505060a08a013567ffffffffffffffff811115611d7957611d786129ed565b5b611d858c828d016119e4565b92509250509295985092959850929598565b600060208284031215611dad57611dac6129f2565b5b6000611dbb84828501611a4f565b91505092915050565b60008060008060608587031215611dde57611ddd6129f2565b5b6000611dec87828801611a4f565b9450506020611dfd878288016119ba565b935050604085013567ffffffffffffffff811115611e1e57611e1d6129ed565b5b611e2a878288016119e4565b925092505092959194509250565b611e4181612750565b82525050565b611e58611e5382612750565b6128a1565b82525050565b611e6781612762565b82525050565b611e768161276e565b82525050565b611e8d611e888261276e565b6128b3565b82525050565b6000611e9f838561263c565b9350611eac8385846127e5565b611eb5836129f7565b840190509392505050565b6000611ecc838561264d565b9350611ed98385846127e5565b82840190509392505050565b6000611ef082612626565b611efa818561264d565b9350611f0a8185602086016127f4565b80840191505092915050565b611f1f816127d3565b82525050565b6000611f3082612631565b611f3a8185612658565b9350611f4a8185602086016127f4565b611f53816129f7565b840191505092915050565b6000611f6b601883612658565b9150611f7682612a2f565b602082019050919050565b6000611f8e601c83612658565b9150611f9982612a58565b602082019050919050565b6000611fb1601f83612658565b9150611fbc82612a81565b602082019050919050565b6000611fd4601683612658565b9150611fdf82612aaa565b602082019050919050565b6000611ff7601183612658565b915061200282612ad3565b602082019050919050565b600061201a602283612658565b915061202582612afc565b604082019050919050565b600061203d602983612658565b915061204882612b4b565b604082019050919050565b6000612060602e83612658565b915061206b82612b9a565b604082019050919050565b6000612083602083612658565b915061208e82612be9565b602082019050919050565b60006120a6602e83612658565b91506120b182612c12565b604082019050919050565b60006120c9602d83612658565b91506120d482612c61565b604082019050919050565b60006120ec601983612658565b91506120f782612cb0565b602082019050919050565b600061210f601c83612658565b915061211a82612cd9565b602082019050919050565b6000612132601d83612658565b915061213d82612d02565b602082019050919050565b6000612155602083612658565b915061216082612d2b565b602082019050919050565b612174816127a2565b82525050565b61218b612186826127a2565b6128cf565b82525050565b61219a816127b2565b82525050565b6121b16121ac826127b2565b6128e1565b82525050565b6121c0816127c6565b82525050565b60006121d28286611e47565b6014820191506121e28285611e47565b6014820191506121f28284611e47565b601482019150819050949350505050565b600061220f8289611e7c565b60208201915061221f82886121a0565b60088201915061222f828761217a565b60048201915061223f8286611e7c565b602082019150612250828486611ec0565b9150819050979650505050505050565b600061226d828486611ec0565b91508190509392505050565b60006122858284611ee5565b915081905092915050565b60006020820190506122a56000830184611e5e565b92915050565b60006020820190506122c06000830184611e6d565b92915050565b60006040820190506122db6000830185611e6d565b6122e86020830184611e6d565b9392505050565b60006040820190506123046000830186611e6d565b8181036020830152612317818486611e93565b9050949350505050565b60006080820190506123366000830187611e6d565b61234360208301866121b7565b6123506040830185611e6d565b61235d6060830184611e6d565b95945050505050565b600060208201905061237b6000830184611f16565b92915050565b6000602082019050818103600083015261239b8184611f25565b905092915050565b600060208201905081810360008301526123bc81611f5e565b9050919050565b600060208201905081810360008301526123dc81611f81565b9050919050565b600060208201905081810360008301526123fc81611fa4565b9050919050565b6000602082019050818103600083015261241c81611fc7565b9050919050565b6000602082019050818103600083015261243c81611fea565b9050919050565b6000602082019050818103600083015261245c8161200d565b9050919050565b6000602082019050818103600083015261247c81612030565b9050919050565b6000602082019050818103600083015261249c81612053565b9050919050565b600060208201905081810360008301526124bc81612076565b9050919050565b600060208201905081810360008301526124dc81612099565b9050919050565b600060208201905081810360008301526124fc816120bc565b9050919050565b6000602082019050818103600083015261251c816120df565b9050919050565b6000602082019050818103600083015261253c81612102565b9050919050565b6000602082019050818103600083015261255c81612125565b9050919050565b6000602082019050818103600083015261257c81612148565b9050919050565b6000606082019050612598600083018661216b565b6125a56020830185611e6d565b6125b26040830184611e38565b949350505050565b60006020820190506125cf6000830184612191565b92915050565b60006125df6125f0565b90506125eb8282612827565b919050565b6000604051905090565b600067ffffffffffffffff821115612615576126146129af565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000612674826127a2565b915061267f836127a2565b92508263ffffffff03821115612698576126976128f3565b5b828201905092915050565b60006126ae826127b2565b91506126b9836127b2565b92508267ffffffffffffffff038211156126d6576126d56128f3565b5b828201905092915050565b60006126ec826127a2565b91506126f7836127a2565b92508261270757612706612922565b5b828204905092915050565b600061271d826127a2565b9150612728836127a2565b92508163ffffffff0483118215151615612745576127446128f3565b5b828202905092915050565b600061275b82612778565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600063ffffffff82169050919050565b600067ffffffffffffffff82169050919050565b600060ff82169050919050565b60006127de826127c6565b9050919050565b82818337600083830152505050565b60005b838110156128125780820151818401526020810190506127f7565b83811115612821576000848401525b50505050565b612830826129f7565b810181811067ffffffffffffffff8211171561284f5761284e6129af565b5b80604052505050565b600061286382612798565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612896576128956128f3565b5b600182019050919050565b60006128ac826128bd565b9050919050565b6000819050919050565b60006128c882612a22565b9050919050565b60006128da82612a15565b9050919050565b60006128ec82612a08565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160c01b9050919050565b60008160e01b9050919050565b60008160601b9050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f6d757374206265207468726f756768206163746976652070726f787900000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b7f496e636f7272656374206b65792070726f766964656400000000000000000000600082015250565b7f496e76616c6964207369676e6174757265000000000000000000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524331393637557067726164653a20756e737570706f727465642070726f7860008201527f6961626c65555549440000000000000000000000000000000000000000000000602082015250565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b7f5369676e657220616c7265616479207369676e65642074686973206e6f6e6365600082015250565b7f45524331393637557067726164653a206e657720696d706c656d656e7461746960008201527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015250565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b7f5369676e6572206e6f742070617274206f66206f7261636c6500000000000000600082015250565b7f6d757374206265207468726f7567682064656c656761746563616c6c00000000600082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f6d757374206e6f74206265207468726f7567682064656c656761746563616c6c600082015250565b612d5d81612750565b8114612d6857600080fd5b50565b612d7481612762565b8114612d7f57600080fd5b50565b612d8b8161276e565b8114612d9657600080fd5b50565b612da2816127a2565b8114612dad57600080fd5b50565b612db9816127b2565b8114612dc457600080fd5b5056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b705d12891615b70f2d820a30c851e0b256b66e7c52b0bbf11ee832245c3d38b64736f6c63430008060033
Deployed Bytecode Sourcemap
61778:6582:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66674:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60046:133;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;64026:1413;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62017:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;63128:432;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;67067:182;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60368:384;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62526:267;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62048:42;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;66674:204;66787:4;66838:32;66852:6;66860:9;;66838:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:13;:32::i;:::-;66811:59;;:9;:16;66821:5;66811:16;;;;;;;;;;;;;;;:23;;;;;;;;;;;;:59;;;66804:66;;66674:204;;;;;;:::o;60046:133::-;60124:7;59387:6;59370:23;;59378:4;59370:23;;;59362:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;52058:66:::1;60151:20;;60144:27;;60046:133:::0;:::o;64026:1413::-;64277:20;64313:1;64300:10;;;;;;;;;;;:14;;;;:::i;:::-;64277:37;;64325:14;64342:63;64356:13;64371:7;64380:13;64395:9;;64342:13;:63::i;:::-;64325:80;;64416:14;64433:32;64447:6;64455:9;;64433:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:13;:32::i;:::-;64416:49;;64514:6;64484:36;;:26;64497:12;;64484;:26::i;:::-;:36;;;64476:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;64771:18;:33;64790:13;64771:33;;;;;;;;;;;;;;;:41;64805:6;64771:41;;;;;;;;;;;;;;;;;;;;;;;;;64770:42;64762:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;64904:4;64860:18;:33;64879:13;64860:33;;;;;;;;;;;;;;;:41;64894:6;64860:41;;;;;;;;;;;;;;;;:48;;;;;;;;;;;;;;;;;;64919:27;64949:9;:21;64959:10;;;;;;;;;;;64949:21;;;;;;;;;;;;;;;64919:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64989:64;65007:5;65014:13;:24;;;65040:12;;64989:17;:64::i;:::-;64981:115;;;;;;;;;;;;:::i;:::-;;;;;;;;;65211:1;65182:17;:25;65200:6;65182:25;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;65338:1;65317:13;:18;;;:22;;;;:::i;:::-;65312:1;:28;;;;:::i;:::-;65284:56;;:17;:25;65302:6;65284:25;;;;;;;;;;;;;;;;;;;;;:56;;;65280:152;;;65357:63;65371:13;65386:7;65395:13;65410:9;;65357:13;:63::i;:::-;65280:152;64266:1173;;;;64026:1413;;;;;;;;;:::o;62017:24::-;;;;;;;;;;;;;:::o;63128:432::-;63266:20;63302:1;63289:10;;;;;;;;;;;:14;;;;:::i;:::-;63266:37;;63314:14;63331:63;63345:13;63360:7;63369:13;63384:9;;63331:13;:63::i;:::-;63314:80;;63413:43;63426:10;;;;;;;;;;;63438:6;63446:9;;63413:12;:43::i;:::-;63405:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;63489:63;63503:13;63518:7;63527:13;63542:9;;63489:13;:63::i;:::-;63253:307;;63128:432;;;;;;:::o;67067:182::-;67174:4;67198:43;67211:10;;;;;;;;;;;67223:6;67231:9;;67198:12;:43::i;:::-;67191:50;;67067:182;;;;;:::o;60368:384::-;58974:6;58957:23;;58965:4;58957:23;;;;58949:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;59056:6;59032:30;;:20;:18;:20::i;:::-;:30;;;59024:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;60478:15:::1;60496:80;60528:4;60535:20;:18;:20::i;:::-;60557:17;60503:72;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;60496:80;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60478:98;;60595:14;:12;:14::i;:::-;:35;;;60631:7;60640:9;;60595:55;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60587:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;60683:61;60705:17;60734:1;60724:12;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60738:5;60683:21;:61::i;:::-;60467:285;60368:384:::0;;;:::o;62526:267::-;12997:19;13020:13;;;;;;;;;;;13019:14;12997:36;;13067:14;:34;;;;;13100:1;13085:12;;;;;;;;;;:16;;;13067:34;13066:97;;;;13108:33;13135:4;13108:18;:33::i;:::-;13107:34;:55;;;;;13161:1;13145:12;;;;;;;;;;:17;;;13107:55;13066:97;13044:193;;;;;;;;;;;;:::i;:::-;;;;;;;;;13263:1;13248:12;;:16;;;;;;;;;;;;;;;;;;13279:14;13275:67;;;13326:4;13310:13;;:20;;;;;;;;;;;;;;;;;;13275:67;62669:1:::1;62656:10;;:14;;;;;;;;;;;;;;;;;;62705:35;;;;;;;;62712:5;62705:35;;;;;;62719:11;62705:35;;;;62732:7;62705:35;;;;::::0;62681:9:::1;:21;62691:10;;;;;;;;;;;62681:21;;;;;;;;;;;;;;;:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62769:16;62751:15;:34;;;;13368:14:::0;13364:102;;;13415:5;13399:13;;:21;;;;;;;;;;;;;;;;;;13440:14;13452:1;13440:14;;;;;;:::i;:::-;;;;;;;;13364:102;12986:487;62526:267;;;;:::o;62048:42::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;37534:231::-;37612:7;37633:17;37652:18;37674:27;37685:4;37691:9;37674:10;:27::i;:::-;37632:69;;;;37712:18;37724:5;37712:11;:18::i;:::-;37748:9;37741:16;;;;37534:231;;;;:::o;67765:229::-;67885:7;67912:74;67936:15;;67953:5;67960:4;67966:10;67978:6;;67919:66;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;67912:74;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67905:81;;67765:229;;;;;;;:::o;68062:140::-;68126:7;68187:3;;68177:14;;;;;;;:::i;:::-;;;;;;;;68169:23;;68146:48;;68062:140;;;;:::o;65674:843::-;65802:4;65819:20;65842:32;65866:6;;65849:24;;;;;;;;;:::i;:::-;;;;;;;;;;;;;65842:32;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65819:55;;65892:9;65887:507;65911:5;:12;65907:1;:16;65887:507;;;65945:20;65968:5;65974:1;65968:8;;;;;;;;:::i;:::-;;;;;;;;65945:31;;66013:12;65997;:28;65993:390;;66140:46;66158:12;66172;66147:38;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66140:46;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66125:61;;65993:390;;;66321:46;66339:12;66353;66328:38;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66321:46;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66306:61;;65993:390;65930:464;65925:3;;;;;:::i;:::-;;;;65887:507;;;;66505:4;66489:12;:20;66482:27;;;65674:843;;;;;;:::o;67355:302::-;67516:96;;;;;;;;67537:4;67516:96;;;;;;67556:10;67516:96;;;;67581:20;67594:6;;67581:12;:20::i;:::-;67516:96;;;;;67489:9;:24;67499:13;67489:24;;;;;;;;;;;;;;;:123;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67636:13;67623:10;;:26;;;;;;;;;;;;;;;;;;67355:302;;;;;:::o;52208:142::-;52261:7;52288:48;52058:66;52315:20;;52288:26;:48::i;:::-;:54;;;;;;;;;;;;52281:61;;52208:142;:::o;68210:147::-;68274:20;68343:4;68307:42;;68210:147;:::o;53566:936::-;53986:42;51710:66;54013:14;;53986:26;:42::i;:::-;:48;;;;;;;;;;;;53982:513;;;54051:37;54070:17;54051:18;:37::i;:::-;53982:513;;;54143:17;54125:50;;;:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;54121:295;;54344:56;;;;;;;;;;:::i;:::-;;;;;;;;54121:295;52058:66;54236:20;;54228:4;:28;54220:82;;;;;;;;;;;;:::i;:::-;;;;;;;;;54178:140;54430:53;54448:17;54467:4;54473:9;54430:17;:53::i;:::-;53982:513;53566:936;;;:::o;1480:326::-;1540:4;1797:1;1775:7;:19;;;:23;1768:30;;1480:326;;;:::o;35985:747::-;36066:7;36075:12;36124:2;36104:9;:16;:22;36100:625;;;36143:9;36167;36191:7;36448:4;36437:9;36433:20;36427:27;36422:32;;36498:4;36487:9;36483:20;36477:27;36472:32;;36556:4;36545:9;36541:20;36535:27;36532:1;36527:36;36522:41;;36599:25;36610:4;36616:1;36619;36622;36599:10;:25::i;:::-;36592:32;;;;;;;;;36100:625;36673:1;36677:35;36657:56;;;;35985:747;;;;;;:::o;34378:521::-;34456:20;34447:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;34443:449;;;34493:7;;34443:449;34554:29;34545:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;34541:351;;;34600:34;;;;;;;;;;:::i;:::-;;;;;;;;34541:351;34665:35;34656:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;34652:240;;;34717:41;;;;;;;;;;:::i;:::-;;;;;;;;34652:240;34789:30;34780:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;34776:116;;;34836:44;;;;;;;;;;:::i;:::-;;;;;;;;34776:116;34378:521;;:::o;48819:195::-;48880:21;48992:4;48982:14;;48819:195;;;:::o;49117:::-;49178:21;49290:4;49280:14;;49117:195;;;:::o;52446:262::-;52528:37;52547:17;52528:18;:37::i;:::-;52520:95;;;;;;;;;;;;:::i;:::-;;;;;;;;;52683:17;52626:48;52058:66;52653:20;;52626:26;:48::i;:::-;:54;;;:74;;;;;;;;;;;;;;;;;;52446:262;:::o;53117:270::-;53226:29;53237:17;53226:10;:29::i;:::-;53284:1;53270:4;:11;:15;:28;;;;53289:9;53270:28;53266:114;;;53315:53;53344:17;53363:4;53315:28;:53::i;:::-;;53266:114;53117:270;;;:::o;38918:1477::-;39006:7;39015:12;39940:66;39935:1;39927:10;;:79;39923:163;;;40039:1;40043:30;40023:51;;;;;;39923:163;40183:14;40200:24;40210:4;40216:1;40219;40222;40200:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40183:41;;40257:1;40239:20;;:6;:20;;;40235:103;;;40292:1;40296:29;40276:50;;;;;;;40235:103;40358:6;40366:20;40350:37;;;;;38918:1477;;;;;;;;:::o;52821:155::-;52888:37;52907:17;52888:18;:37::i;:::-;52950:17;52941:27;;;;;;;;;;;;52821:155;:::o;6872:200::-;6955:12;6987:77;7008:6;7016:4;6987:77;;;;;;;;;;;;;;;;;:20;:77::i;:::-;6980:84;;6872:200;;;;:::o;7266:332::-;7411:12;7437;7451:23;7478:6;:19;;7498:4;7478:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7436:67;;;;7521:69;7548:6;7556:7;7565:10;7577:12;7521:26;:69::i;:::-;7514:76;;;;7266:332;;;;;:::o;7894:644::-;8079:12;8108:7;8104:427;;;8157:1;8136:10;:17;:22;8132:290;;;8354:18;8365:6;8354:10;:18::i;:::-;8346:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;8132:290;8443:10;8436:17;;;;8104:427;8486:33;8494:10;8506:12;8486:7;:33::i;:::-;7894:644;;;;;;;:::o;9080:552::-;9261:1;9241:10;:17;:21;9237:388;;;9473:10;9467:17;9530:15;9517:10;9513:2;9509:19;9502:44;9237:388;9600:12;9593:20;;;;;;;;;;;:::i;:::-;;;;;;;;24:722:1;120:5;145:81;161:64;218:6;161:64;:::i;:::-;145:81;:::i;:::-;136:90;;246:5;275:6;268:5;261:21;309:4;302:5;298:16;291:23;;335:6;385:3;377:4;369:6;365:17;360:3;356:27;353:36;350:2;;;404:79;;:::i;:::-;350:2;517:1;502:238;527:6;524:1;521:13;502:238;;;595:3;624:37;657:3;645:10;624:37;:::i;:::-;619:3;612:50;691:4;686:3;682:14;675:21;;725:4;720:3;716:14;709:21;;562:178;549:1;546;542:9;537:14;;502:238;;;506:14;126:620;;;;;;;:::o;752:139::-;798:5;836:6;823:20;814:29;;852:33;879:5;852:33;:::i;:::-;804:87;;;;:::o;914:370::-;985:5;1034:3;1027:4;1019:6;1015:17;1011:27;1001:2;;1042:79;;:::i;:::-;1001:2;1159:6;1146:20;1184:94;1274:3;1266:6;1259:4;1251:6;1247:17;1184:94;:::i;:::-;1175:103;;991:293;;;;;:::o;1290:137::-;1344:5;1375:6;1369:13;1360:22;;1391:30;1415:5;1391:30;:::i;:::-;1350:77;;;;:::o;1433:139::-;1479:5;1517:6;1504:20;1495:29;;1533:33;1560:5;1533:33;:::i;:::-;1485:87;;;;:::o;1578:143::-;1635:5;1666:6;1660:13;1651:22;;1682:33;1709:5;1682:33;:::i;:::-;1641:80;;;;:::o;1740:552::-;1797:8;1807:6;1857:3;1850:4;1842:6;1838:17;1834:27;1824:2;;1865:79;;:::i;:::-;1824:2;1978:6;1965:20;1955:30;;2008:18;2000:6;1997:30;1994:2;;;2030:79;;:::i;:::-;1994:2;2144:4;2136:6;2132:17;2120:29;;2198:3;2190:4;2182:6;2178:17;2168:8;2164:32;2161:41;2158:2;;;2205:79;;:::i;:::-;2158:2;1814:478;;;;;:::o;2298:137::-;2343:5;2381:6;2368:20;2359:29;;2397:32;2423:5;2397:32;:::i;:::-;2349:86;;;;:::o;2441:137::-;2486:5;2524:6;2511:20;2502:29;;2540:32;2566:5;2540:32;:::i;:::-;2492:86;;;;:::o;2584:345::-;2651:6;2700:2;2688:9;2679:7;2675:23;2671:32;2668:2;;;2706:79;;:::i;:::-;2668:2;2826:1;2851:61;2904:7;2895:6;2884:9;2880:22;2851:61;:::i;:::-;2841:71;;2797:125;2658:271;;;;:::o;2935:351::-;3005:6;3054:2;3042:9;3033:7;3029:23;3025:32;3022:2;;;3060:79;;:::i;:::-;3022:2;3180:1;3205:64;3261:7;3252:6;3241:9;3237:22;3205:64;:::i;:::-;3195:74;;3151:128;3012:274;;;;:::o;3292:672::-;3371:6;3379;3387;3436:2;3424:9;3415:7;3411:23;3407:32;3404:2;;;3442:79;;:::i;:::-;3404:2;3562:1;3587:53;3632:7;3623:6;3612:9;3608:22;3587:53;:::i;:::-;3577:63;;3533:117;3717:2;3706:9;3702:18;3689:32;3748:18;3740:6;3737:30;3734:2;;;3770:79;;:::i;:::-;3734:2;3883:64;3939:7;3930:6;3919:9;3915:22;3883:64;:::i;:::-;3865:82;;;;3660:297;3394:570;;;;;:::o;3970:672::-;4049:6;4057;4065;4114:2;4102:9;4093:7;4089:23;4085:32;4082:2;;;4120:79;;:::i;:::-;4082:2;4268:1;4257:9;4253:17;4240:31;4298:18;4290:6;4287:30;4284:2;;;4320:79;;:::i;:::-;4284:2;4433:64;4489:7;4480:6;4469:9;4465:22;4433:64;:::i;:::-;4415:82;;;;4211:296;4546:2;4572:53;4617:7;4608:6;4597:9;4593:22;4572:53;:::i;:::-;4562:63;;4517:118;4072:570;;;;;:::o;4648:763::-;4733:6;4741;4749;4757;4806:3;4794:9;4785:7;4781:23;4777:33;4774:2;;;4813:79;;:::i;:::-;4774:2;4933:1;4958:52;5002:7;4993:6;4982:9;4978:22;4958:52;:::i;:::-;4948:62;;4904:116;5059:2;5085:53;5130:7;5121:6;5110:9;5106:22;5085:53;:::i;:::-;5075:63;;5030:118;5187:2;5213:53;5258:7;5249:6;5238:9;5234:22;5213:53;:::i;:::-;5203:63;;5158:118;5315:2;5341:53;5386:7;5377:6;5366:9;5362:22;5341:53;:::i;:::-;5331:63;;5286:118;4764:647;;;;;;;:::o;5417:1159::-;5524:6;5532;5540;5548;5556;5564;5613:3;5601:9;5592:7;5588:23;5584:33;5581:2;;;5620:79;;:::i;:::-;5581:2;5740:1;5765:52;5809:7;5800:6;5789:9;5785:22;5765:52;:::i;:::-;5755:62;;5711:116;5866:2;5892:53;5937:7;5928:6;5917:9;5913:22;5892:53;:::i;:::-;5882:63;;5837:118;6022:2;6011:9;6007:18;5994:32;6053:18;6045:6;6042:30;6039:2;;;6075:79;;:::i;:::-;6039:2;6188:64;6244:7;6235:6;6224:9;6220:22;6188:64;:::i;:::-;6170:82;;;;5965:297;6329:2;6318:9;6314:18;6301:32;6360:18;6352:6;6349:30;6346:2;;;6382:79;;:::i;:::-;6346:2;6495:64;6551:7;6542:6;6531:9;6527:22;6495:64;:::i;:::-;6477:82;;;;6272:297;5571:1005;;;;;;;;:::o;6582:1859::-;6743:6;6751;6759;6767;6775;6783;6791;6799;6807;6856:3;6844:9;6835:7;6831:23;6827:33;6824:2;;;6863:79;;:::i;:::-;6824:2;6983:1;7008:52;7052:7;7043:6;7032:9;7028:22;7008:52;:::i;:::-;6998:62;;6954:116;7109:2;7135:53;7180:7;7171:6;7160:9;7156:22;7135:53;:::i;:::-;7125:63;;7080:118;7265:2;7254:9;7250:18;7237:32;7296:18;7288:6;7285:30;7282:2;;;7318:79;;:::i;:::-;7282:2;7431:64;7487:7;7478:6;7467:9;7463:22;7431:64;:::i;:::-;7413:82;;;;7208:297;7572:2;7561:9;7557:18;7544:32;7603:18;7595:6;7592:30;7589:2;;;7625:79;;:::i;:::-;7589:2;7738:64;7794:7;7785:6;7774:9;7770:22;7738:64;:::i;:::-;7720:82;;;;7515:297;7879:3;7868:9;7864:19;7851:33;7911:18;7903:6;7900:30;7897:2;;;7933:79;;:::i;:::-;7897:2;8038:78;8108:7;8099:6;8088:9;8084:22;8038:78;:::i;:::-;8028:88;;7822:304;8193:3;8182:9;8178:19;8165:33;8225:18;8217:6;8214:30;8211:2;;;8247:79;;:::i;:::-;8211:2;8360:64;8416:7;8407:6;8396:9;8392:22;8360:64;:::i;:::-;8342:82;;;;8136:298;6814:1627;;;;;;;;;;;:::o;8447:327::-;8505:6;8554:2;8542:9;8533:7;8529:23;8525:32;8522:2;;;8560:79;;:::i;:::-;8522:2;8680:1;8705:52;8749:7;8740:6;8729:9;8725:22;8705:52;:::i;:::-;8695:62;;8651:116;8512:262;;;;:::o;8780:815::-;8867:6;8875;8883;8891;8940:2;8928:9;8919:7;8915:23;8911:32;8908:2;;;8946:79;;:::i;:::-;8908:2;9066:1;9091:52;9135:7;9126:6;9115:9;9111:22;9091:52;:::i;:::-;9081:62;;9037:116;9192:2;9218:53;9263:7;9254:6;9243:9;9239:22;9218:53;:::i;:::-;9208:63;;9163:118;9348:2;9337:9;9333:18;9320:32;9379:18;9371:6;9368:30;9365:2;;;9401:79;;:::i;:::-;9365:2;9514:64;9570:7;9561:6;9550:9;9546:22;9514:64;:::i;:::-;9496:82;;;;9291:297;8898:697;;;;;;;:::o;9601:118::-;9688:24;9706:5;9688:24;:::i;:::-;9683:3;9676:37;9666:53;;:::o;9725:157::-;9830:45;9850:24;9868:5;9850:24;:::i;:::-;9830:45;:::i;:::-;9825:3;9818:58;9808:74;;:::o;9888:109::-;9969:21;9984:5;9969:21;:::i;:::-;9964:3;9957:34;9947:50;;:::o;10003:118::-;10090:24;10108:5;10090:24;:::i;:::-;10085:3;10078:37;10068:53;;:::o;10127:157::-;10232:45;10252:24;10270:5;10252:24;:::i;:::-;10232:45;:::i;:::-;10227:3;10220:58;10210:74;;:::o;10312:301::-;10408:3;10429:70;10492:6;10487:3;10429:70;:::i;:::-;10422:77;;10509:43;10545:6;10540:3;10533:5;10509:43;:::i;:::-;10577:29;10599:6;10577:29;:::i;:::-;10572:3;10568:39;10561:46;;10412:201;;;;;:::o;10641:314::-;10755:3;10776:88;10857:6;10852:3;10776:88;:::i;:::-;10769:95;;10874:43;10910:6;10905:3;10898:5;10874:43;:::i;:::-;10942:6;10937:3;10933:16;10926:23;;10759:196;;;;;:::o;10961:373::-;11065:3;11093:38;11125:5;11093:38;:::i;:::-;11147:88;11228:6;11223:3;11147:88;:::i;:::-;11140:95;;11244:52;11289:6;11284:3;11277:4;11270:5;11266:16;11244:52;:::i;:::-;11321:6;11316:3;11312:16;11305:23;;11069:265;;;;;:::o;11340:143::-;11433:43;11470:5;11433:43;:::i;:::-;11428:3;11421:56;11411:72;;:::o;11489:364::-;11577:3;11605:39;11638:5;11605:39;:::i;:::-;11660:71;11724:6;11719:3;11660:71;:::i;:::-;11653:78;;11740:52;11785:6;11780:3;11773:4;11766:5;11762:16;11740:52;:::i;:::-;11817:29;11839:6;11817:29;:::i;:::-;11812:3;11808:39;11801:46;;11581:272;;;;;:::o;11859:366::-;12001:3;12022:67;12086:2;12081:3;12022:67;:::i;:::-;12015:74;;12098:93;12187:3;12098:93;:::i;:::-;12216:2;12211:3;12207:12;12200:19;;12005:220;;;:::o;12231:366::-;12373:3;12394:67;12458:2;12453:3;12394:67;:::i;:::-;12387:74;;12470:93;12559:3;12470:93;:::i;:::-;12588:2;12583:3;12579:12;12572:19;;12377:220;;;:::o;12603:366::-;12745:3;12766:67;12830:2;12825:3;12766:67;:::i;:::-;12759:74;;12842:93;12931:3;12842:93;:::i;:::-;12960:2;12955:3;12951:12;12944:19;;12749:220;;;:::o;12975:366::-;13117:3;13138:67;13202:2;13197:3;13138:67;:::i;:::-;13131:74;;13214:93;13303:3;13214:93;:::i;:::-;13332:2;13327:3;13323:12;13316:19;;13121:220;;;:::o;13347:366::-;13489:3;13510:67;13574:2;13569:3;13510:67;:::i;:::-;13503:74;;13586:93;13675:3;13586:93;:::i;:::-;13704:2;13699:3;13695:12;13688:19;;13493:220;;;:::o;13719:366::-;13861:3;13882:67;13946:2;13941:3;13882:67;:::i;:::-;13875:74;;13958:93;14047:3;13958:93;:::i;:::-;14076:2;14071:3;14067:12;14060:19;;13865:220;;;:::o;14091:366::-;14233:3;14254:67;14318:2;14313:3;14254:67;:::i;:::-;14247:74;;14330:93;14419:3;14330:93;:::i;:::-;14448:2;14443:3;14439:12;14432:19;;14237:220;;;:::o;14463:366::-;14605:3;14626:67;14690:2;14685:3;14626:67;:::i;:::-;14619:74;;14702:93;14791:3;14702:93;:::i;:::-;14820:2;14815:3;14811:12;14804:19;;14609:220;;;:::o;14835:366::-;14977:3;14998:67;15062:2;15057:3;14998:67;:::i;:::-;14991:74;;15074:93;15163:3;15074:93;:::i;:::-;15192:2;15187:3;15183:12;15176:19;;14981:220;;;:::o;15207:366::-;15349:3;15370:67;15434:2;15429:3;15370:67;:::i;:::-;15363:74;;15446:93;15535:3;15446:93;:::i;:::-;15564:2;15559:3;15555:12;15548:19;;15353:220;;;:::o;15579:366::-;15721:3;15742:67;15806:2;15801:3;15742:67;:::i;:::-;15735:74;;15818:93;15907:3;15818:93;:::i;:::-;15936:2;15931:3;15927:12;15920:19;;15725:220;;;:::o;15951:366::-;16093:3;16114:67;16178:2;16173:3;16114:67;:::i;:::-;16107:74;;16190:93;16279:3;16190:93;:::i;:::-;16308:2;16303:3;16299:12;16292:19;;16097:220;;;:::o;16323:366::-;16465:3;16486:67;16550:2;16545:3;16486:67;:::i;:::-;16479:74;;16562:93;16651:3;16562:93;:::i;:::-;16680:2;16675:3;16671:12;16664:19;;16469:220;;;:::o;16695:366::-;16837:3;16858:67;16922:2;16917:3;16858:67;:::i;:::-;16851:74;;16934:93;17023:3;16934:93;:::i;:::-;17052:2;17047:3;17043:12;17036:19;;16841:220;;;:::o;17067:366::-;17209:3;17230:67;17294:2;17289:3;17230:67;:::i;:::-;17223:74;;17306:93;17395:3;17306:93;:::i;:::-;17424:2;17419:3;17415:12;17408:19;;17213:220;;;:::o;17439:115::-;17524:23;17541:5;17524:23;:::i;:::-;17519:3;17512:36;17502:52;;:::o;17560:153::-;17663:43;17682:23;17699:5;17682:23;:::i;:::-;17663:43;:::i;:::-;17658:3;17651:56;17641:72;;:::o;17719:115::-;17804:23;17821:5;17804:23;:::i;:::-;17799:3;17792:36;17782:52;;:::o;17840:153::-;17943:43;17962:23;17979:5;17962:23;:::i;:::-;17943:43;:::i;:::-;17938:3;17931:56;17921:72;;:::o;17999:112::-;18082:22;18098:5;18082:22;:::i;:::-;18077:3;18070:35;18060:51;;:::o;18117:538::-;18285:3;18300:75;18371:3;18362:6;18300:75;:::i;:::-;18400:2;18395:3;18391:12;18384:19;;18413:75;18484:3;18475:6;18413:75;:::i;:::-;18513:2;18508:3;18504:12;18497:19;;18526:75;18597:3;18588:6;18526:75;:::i;:::-;18626:2;18621:3;18617:12;18610:19;;18646:3;18639:10;;18289:366;;;;;;:::o;18661:845::-;18909:3;18924:75;18995:3;18986:6;18924:75;:::i;:::-;19024:2;19019:3;19015:12;19008:19;;19037:73;19106:3;19097:6;19037:73;:::i;:::-;19135:1;19130:3;19126:11;19119:18;;19147:73;19216:3;19207:6;19147:73;:::i;:::-;19245:1;19240:3;19236:11;19229:18;;19257:75;19328:3;19319:6;19257:75;:::i;:::-;19357:2;19352:3;19348:12;19341:19;;19377:103;19476:3;19467:6;19459;19377:103;:::i;:::-;19370:110;;19497:3;19490:10;;18913:593;;;;;;;;;:::o;19512:291::-;19652:3;19674:103;19773:3;19764:6;19756;19674:103;:::i;:::-;19667:110;;19794:3;19787:10;;19656:147;;;;;:::o;19809:271::-;19939:3;19961:93;20050:3;20041:6;19961:93;:::i;:::-;19954:100;;20071:3;20064:10;;19943:137;;;;:::o;20086:210::-;20173:4;20211:2;20200:9;20196:18;20188:26;;20224:65;20286:1;20275:9;20271:17;20262:6;20224:65;:::i;:::-;20178:118;;;;:::o;20302:222::-;20395:4;20433:2;20422:9;20418:18;20410:26;;20446:71;20514:1;20503:9;20499:17;20490:6;20446:71;:::i;:::-;20400:124;;;;:::o;20530:332::-;20651:4;20689:2;20678:9;20674:18;20666:26;;20702:71;20770:1;20759:9;20755:17;20746:6;20702:71;:::i;:::-;20783:72;20851:2;20840:9;20836:18;20827:6;20783:72;:::i;:::-;20656:206;;;;;:::o;20868:439::-;21017:4;21055:2;21044:9;21040:18;21032:26;;21068:71;21136:1;21125:9;21121:17;21112:6;21068:71;:::i;:::-;21186:9;21180:4;21176:20;21171:2;21160:9;21156:18;21149:48;21214:86;21295:4;21286:6;21278;21214:86;:::i;:::-;21206:94;;21022:285;;;;;;:::o;21313:545::-;21486:4;21524:3;21513:9;21509:19;21501:27;;21538:71;21606:1;21595:9;21591:17;21582:6;21538:71;:::i;:::-;21619:68;21683:2;21672:9;21668:18;21659:6;21619:68;:::i;:::-;21697:72;21765:2;21754:9;21750:18;21741:6;21697:72;:::i;:::-;21779;21847:2;21836:9;21832:18;21823:6;21779:72;:::i;:::-;21491:367;;;;;;;:::o;21864:234::-;21963:4;22001:2;21990:9;21986:18;21978:26;;22014:77;22088:1;22077:9;22073:17;22064:6;22014:77;:::i;:::-;21968:130;;;;:::o;22104:313::-;22217:4;22255:2;22244:9;22240:18;22232:26;;22304:9;22298:4;22294:20;22290:1;22279:9;22275:17;22268:47;22332:78;22405:4;22396:6;22332:78;:::i;:::-;22324:86;;22222:195;;;;:::o;22423:419::-;22589:4;22627:2;22616:9;22612:18;22604:26;;22676:9;22670:4;22666:20;22662:1;22651:9;22647:17;22640:47;22704:131;22830:4;22704:131;:::i;:::-;22696:139;;22594:248;;;:::o;22848:419::-;23014:4;23052:2;23041:9;23037:18;23029:26;;23101:9;23095:4;23091:20;23087:1;23076:9;23072:17;23065:47;23129:131;23255:4;23129:131;:::i;:::-;23121:139;;23019:248;;;:::o;23273:419::-;23439:4;23477:2;23466:9;23462:18;23454:26;;23526:9;23520:4;23516:20;23512:1;23501:9;23497:17;23490:47;23554:131;23680:4;23554:131;:::i;:::-;23546:139;;23444:248;;;:::o;23698:419::-;23864:4;23902:2;23891:9;23887:18;23879:26;;23951:9;23945:4;23941:20;23937:1;23926:9;23922:17;23915:47;23979:131;24105:4;23979:131;:::i;:::-;23971:139;;23869:248;;;:::o;24123:419::-;24289:4;24327:2;24316:9;24312:18;24304:26;;24376:9;24370:4;24366:20;24362:1;24351:9;24347:17;24340:47;24404:131;24530:4;24404:131;:::i;:::-;24396:139;;24294:248;;;:::o;24548:419::-;24714:4;24752:2;24741:9;24737:18;24729:26;;24801:9;24795:4;24791:20;24787:1;24776:9;24772:17;24765:47;24829:131;24955:4;24829:131;:::i;:::-;24821:139;;24719:248;;;:::o;24973:419::-;25139:4;25177:2;25166:9;25162:18;25154:26;;25226:9;25220:4;25216:20;25212:1;25201:9;25197:17;25190:47;25254:131;25380:4;25254:131;:::i;:::-;25246:139;;25144:248;;;:::o;25398:419::-;25564:4;25602:2;25591:9;25587:18;25579:26;;25651:9;25645:4;25641:20;25637:1;25626:9;25622:17;25615:47;25679:131;25805:4;25679:131;:::i;:::-;25671:139;;25569:248;;;:::o;25823:419::-;25989:4;26027:2;26016:9;26012:18;26004:26;;26076:9;26070:4;26066:20;26062:1;26051:9;26047:17;26040:47;26104:131;26230:4;26104:131;:::i;:::-;26096:139;;25994:248;;;:::o;26248:419::-;26414:4;26452:2;26441:9;26437:18;26429:26;;26501:9;26495:4;26491:20;26487:1;26476:9;26472:17;26465:47;26529:131;26655:4;26529:131;:::i;:::-;26521:139;;26419:248;;;:::o;26673:419::-;26839:4;26877:2;26866:9;26862:18;26854:26;;26926:9;26920:4;26916:20;26912:1;26901:9;26897:17;26890:47;26954:131;27080:4;26954:131;:::i;:::-;26946:139;;26844:248;;;:::o;27098:419::-;27264:4;27302:2;27291:9;27287:18;27279:26;;27351:9;27345:4;27341:20;27337:1;27326:9;27322:17;27315:47;27379:131;27505:4;27379:131;:::i;:::-;27371:139;;27269:248;;;:::o;27523:419::-;27689:4;27727:2;27716:9;27712:18;27704:26;;27776:9;27770:4;27766:20;27762:1;27751:9;27747:17;27740:47;27804:131;27930:4;27804:131;:::i;:::-;27796:139;;27694:248;;;:::o;27948:419::-;28114:4;28152:2;28141:9;28137:18;28129:26;;28201:9;28195:4;28191:20;28187:1;28176:9;28172:17;28165:47;28229:131;28355:4;28229:131;:::i;:::-;28221:139;;28119:248;;;:::o;28373:419::-;28539:4;28577:2;28566:9;28562:18;28554:26;;28626:9;28620:4;28616:20;28612:1;28601:9;28597:17;28590:47;28654:131;28780:4;28654:131;:::i;:::-;28646:139;;28544:248;;;:::o;28798:438::-;28945:4;28983:2;28972:9;28968:18;28960:26;;28996:69;29062:1;29051:9;29047:17;29038:6;28996:69;:::i;:::-;29075:72;29143:2;29132:9;29128:18;29119:6;29075:72;:::i;:::-;29157;29225:2;29214:9;29210:18;29201:6;29157:72;:::i;:::-;28950:286;;;;;;:::o;29242:218::-;29333:4;29371:2;29360:9;29356:18;29348:26;;29384:69;29450:1;29439:9;29435:17;29426:6;29384:69;:::i;:::-;29338:122;;;;:::o;29466:129::-;29500:6;29527:20;;:::i;:::-;29517:30;;29556:33;29584:4;29576:6;29556:33;:::i;:::-;29507:88;;;:::o;29601:75::-;29634:6;29667:2;29661:9;29651:19;;29641:35;:::o;29682:311::-;29759:4;29849:18;29841:6;29838:30;29835:2;;;29871:18;;:::i;:::-;29835:2;29921:4;29913:6;29909:17;29901:25;;29981:4;29975;29971:15;29963:23;;29764:229;;;:::o;29999:98::-;30050:6;30084:5;30078:12;30068:22;;30057:40;;;:::o;30103:99::-;30155:6;30189:5;30183:12;30173:22;;30162:40;;;:::o;30208:168::-;30291:11;30325:6;30320:3;30313:19;30365:4;30360:3;30356:14;30341:29;;30303:73;;;;:::o;30382:147::-;30483:11;30520:3;30505:18;;30495:34;;;;:::o;30535:169::-;30619:11;30653:6;30648:3;30641:19;30693:4;30688:3;30684:14;30669:29;;30631:73;;;;:::o;30710:246::-;30749:3;30768:19;30785:1;30768:19;:::i;:::-;30763:24;;30801:19;30818:1;30801:19;:::i;:::-;30796:24;;30898:1;30886:10;30882:18;30879:1;30876:25;30873:2;;;30904:18;;:::i;:::-;30873:2;30948:1;30945;30941:9;30934:16;;30753:203;;;;:::o;30962:254::-;31001:3;31020:19;31037:1;31020:19;:::i;:::-;31015:24;;31053:19;31070:1;31053:19;:::i;:::-;31048:24;;31158:1;31138:18;31134:26;31131:1;31128:33;31125:2;;;31164:18;;:::i;:::-;31125:2;31208:1;31205;31201:9;31194:16;;31005:211;;;;:::o;31222:182::-;31261:1;31278:19;31295:1;31278:19;:::i;:::-;31273:24;;31311:19;31328:1;31311:19;:::i;:::-;31306:24;;31349:1;31339:2;;31354:18;;:::i;:::-;31339:2;31396:1;31393;31389:9;31384:14;;31263:141;;;;:::o;31410:289::-;31449:7;31472:19;31489:1;31472:19;:::i;:::-;31467:24;;31505:19;31522:1;31505:19;:::i;:::-;31500:24;;31636:1;31624:10;31620:18;31617:1;31614:25;31609:1;31602:9;31595:17;31591:49;31588:2;;;31643:18;;:::i;:::-;31588:2;31691:1;31688;31684:9;31673:20;;31457:242;;;;:::o;31705:96::-;31742:7;31771:24;31789:5;31771:24;:::i;:::-;31760:35;;31750:51;;;:::o;31807:90::-;31841:7;31884:5;31877:13;31870:21;31859:32;;31849:48;;;:::o;31903:77::-;31940:7;31969:5;31958:16;;31948:32;;;:::o;31986:126::-;32023:7;32063:42;32056:5;32052:54;32041:65;;32031:81;;;:::o;32118:77::-;32155:7;32184:5;32173:16;;32163:32;;;:::o;32201:93::-;32237:7;32277:10;32270:5;32266:22;32255:33;;32245:49;;;:::o;32300:101::-;32336:7;32376:18;32369:5;32365:30;32354:41;;32344:57;;;:::o;32407:86::-;32442:7;32482:4;32475:5;32471:16;32460:27;;32450:43;;;:::o;32499:117::-;32555:9;32588:22;32604:5;32588:22;:::i;:::-;32575:35;;32565:51;;;:::o;32622:154::-;32706:6;32701:3;32696;32683:30;32768:1;32759:6;32754:3;32750:16;32743:27;32673:103;;;:::o;32782:307::-;32850:1;32860:113;32874:6;32871:1;32868:13;32860:113;;;32959:1;32954:3;32950:11;32944:18;32940:1;32935:3;32931:11;32924:39;32896:2;32893:1;32889:10;32884:15;;32860:113;;;32991:6;32988:1;32985:13;32982:2;;;33071:1;33062:6;33057:3;33053:16;33046:27;32982:2;32831:258;;;;:::o;33095:281::-;33178:27;33200:4;33178:27;:::i;:::-;33170:6;33166:40;33308:6;33296:10;33293:22;33272:18;33260:10;33257:34;33254:62;33251:2;;;33319:18;;:::i;:::-;33251:2;33359:10;33355:2;33348:22;33138:238;;;:::o;33382:233::-;33421:3;33444:24;33462:5;33444:24;:::i;:::-;33435:33;;33490:66;33483:5;33480:77;33477:2;;;33560:18;;:::i;:::-;33477:2;33607:1;33600:5;33596:13;33589:20;;33425:190;;;:::o;33621:100::-;33660:7;33689:26;33709:5;33689:26;:::i;:::-;33678:37;;33668:53;;;:::o;33727:79::-;33766:7;33795:5;33784:16;;33774:32;;;:::o;33812:94::-;33851:7;33880:20;33894:5;33880:20;:::i;:::-;33869:31;;33859:47;;;:::o;33912:94::-;33950:7;33979:21;33994:5;33979:21;:::i;:::-;33968:32;;33958:48;;;:::o;34012:94::-;34050:7;34079:21;34094:5;34079:21;:::i;:::-;34068:32;;34058:48;;;:::o;34112:180::-;34160:77;34157:1;34150:88;34257:4;34254:1;34247:15;34281:4;34278:1;34271:15;34298:180;34346:77;34343:1;34336:88;34443:4;34440:1;34433:15;34467:4;34464:1;34457:15;34484:180;34532:77;34529:1;34522:88;34629:4;34626:1;34619:15;34653:4;34650:1;34643:15;34670:180;34718:77;34715:1;34708:88;34815:4;34812:1;34805:15;34839:4;34836:1;34829:15;34856:180;34904:77;34901:1;34894:88;35001:4;34998:1;34991:15;35025:4;35022:1;35015:15;35042:117;35151:1;35148;35141:12;35165:117;35274:1;35271;35264:12;35288:117;35397:1;35394;35387:12;35411:117;35520:1;35517;35510:12;35534:117;35643:1;35640;35633:12;35657:102;35698:6;35749:2;35745:7;35740:2;35733:5;35729:14;35725:28;35715:38;;35705:54;;;:::o;35765:96::-;35799:8;35848:5;35843:3;35839:15;35818:36;;35808:53;;;:::o;35867:96::-;35901:8;35950:5;35945:3;35941:15;35920:36;;35910:53;;;:::o;35969:94::-;36002:8;36050:5;36046:2;36042:14;36021:35;;36011:52;;;:::o;36069:174::-;36209:26;36205:1;36197:6;36193:14;36186:50;36175:68;:::o;36249:178::-;36389:30;36385:1;36377:6;36373:14;36366:54;36355:72;:::o;36433:181::-;36573:33;36569:1;36561:6;36557:14;36550:57;36539:75;:::o;36620:172::-;36760:24;36756:1;36748:6;36744:14;36737:48;36726:66;:::o;36798:167::-;36938:19;36934:1;36926:6;36922:14;36915:43;36904:61;:::o;36971:221::-;37111:34;37107:1;37099:6;37095:14;37088:58;37180:4;37175:2;37167:6;37163:15;37156:29;37077:115;:::o;37198:228::-;37338:34;37334:1;37326:6;37322:14;37315:58;37407:11;37402:2;37394:6;37390:15;37383:36;37304:122;:::o;37432:233::-;37572:34;37568:1;37560:6;37556:14;37549:58;37641:16;37636:2;37628:6;37624:15;37617:41;37538:127;:::o;37671:182::-;37811:34;37807:1;37799:6;37795:14;37788:58;37777:76;:::o;37859:233::-;37999:34;37995:1;37987:6;37983:14;37976:58;38068:16;38063:2;38055:6;38051:15;38044:41;37965:127;:::o;38098:232::-;38238:34;38234:1;38226:6;38222:14;38215:58;38307:15;38302:2;38294:6;38290:15;38283:40;38204:126;:::o;38336:175::-;38476:27;38472:1;38464:6;38460:14;38453:51;38442:69;:::o;38517:178::-;38657:30;38653:1;38645:6;38641:14;38634:54;38623:72;:::o;38701:179::-;38841:31;38837:1;38829:6;38825:14;38818:55;38807:73;:::o;38886:182::-;39026:34;39022:1;39014:6;39010:14;39003:58;38992:76;:::o;39074:122::-;39147:24;39165:5;39147:24;:::i;:::-;39140:5;39137:35;39127:2;;39186:1;39183;39176:12;39127:2;39117:79;:::o;39202:116::-;39272:21;39287:5;39272:21;:::i;:::-;39265:5;39262:32;39252:2;;39308:1;39305;39298:12;39252:2;39242:76;:::o;39324:122::-;39397:24;39415:5;39397:24;:::i;:::-;39390:5;39387:35;39377:2;;39436:1;39433;39426:12;39377:2;39367:79;:::o;39452:120::-;39524:23;39541:5;39524:23;:::i;:::-;39517:5;39514:34;39504:2;;39562:1;39559;39552:12;39504:2;39494:78;:::o;39578:120::-;39650:23;39667:5;39650:23;:::i;:::-;39643:5;39640:34;39630:2;;39688:1;39685;39678:12;39630:2;39620:78;:::o
Swarm Source
ipfs://b705d12891615b70f2d820a30c851e0b256b66e7c52b0bbf11ee832245c3d38b
Loading...
Loading
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.