Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 12 from a total of 12 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Produce | 19834266 | 259 days ago | IN | 0 ETH | 0.01693871 | ||||
Produce | 16980626 | 660 days ago | IN | 0 ETH | 0.1048366 | ||||
Produce | 16634384 | 708 days ago | IN | 0 ETH | 0.12783 | ||||
Produce | 16633981 | 708 days ago | IN | 0 ETH | 0.09299103 | ||||
Produce | 16414990 | 739 days ago | IN | 0 ETH | 0.15006653 | ||||
Produce | 16413851 | 739 days ago | IN | 0 ETH | 0.07983244 | ||||
Produce | 16347448 | 748 days ago | IN | 0 ETH | 0.05391887 | ||||
Produce | 16218508 | 766 days ago | IN | 0 ETH | 0.05177661 | ||||
Produce | 16218163 | 766 days ago | IN | 0 ETH | 0.05446504 | ||||
Produce | 16182434 | 771 days ago | IN | 0 ETH | 0.05353704 | ||||
Produce | 16175749 | 772 days ago | IN | 0 ETH | 0.05593425 | ||||
Initialize | 16171714 | 773 days ago | IN | 0 ETH | 0.00198186 |
Latest 11 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19834266 | 259 days ago | Contract Creation | 0 ETH | |||
16980626 | 660 days ago | Contract Creation | 0 ETH | |||
16634384 | 708 days ago | Contract Creation | 0 ETH | |||
16633981 | 708 days ago | Contract Creation | 0 ETH | |||
16414990 | 739 days ago | Contract Creation | 0 ETH | |||
16413851 | 739 days ago | Contract Creation | 0 ETH | |||
16347448 | 748 days ago | Contract Creation | 0 ETH | |||
16218508 | 766 days ago | Contract Creation | 0 ETH | |||
16218163 | 766 days ago | Contract Creation | 0 ETH | |||
16182434 | 771 days ago | Contract Creation | 0 ETH | |||
16175749 | 772 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Factory
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-12-12 */ // File: contracts/interfaces/IStorageContract.sol // SPDX-License-Identifier: None pragma solidity 0.8.13; interface IStorageContract { struct InstanceInfo { string name; string symbol; address creator; } function addInstance( address instanceAddress, address creator, string memory name, string memory symbol ) external returns (uint256); function factory() external view returns(address); function getInstanceInfo() external view returns(InstanceInfo memory); function getInstance(bytes32 hash) external view returns(address); function instancesCount() external view returns (uint256); } // File: contracts/interfaces/IFactory.sol pragma solidity 0.8.13; interface IFactory { function signerAddress() external view returns(address); function platformAddress() external view returns(address); function platformCommission() external view returns(uint8); } // File: operator-filter-registry/src/IOperatorFilterRegistry.sol pragma solidity ^0.8.13; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.8.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) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 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 10, 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 * 8) < value ? 1 : 0); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.8.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 `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); } } // File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol // OpenZeppelin Contracts (last updated v4.8.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) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @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) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v4.8.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 * ==== * * [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (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/contracts/token/ERC20/extensions/draft-IERC20Permit.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: @openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { 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) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 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 10, 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 * 8) < value ? 1 : 0); } } } // File: @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { 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 = MathUpgradeable.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 `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.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); } } // File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721ReceiverUpgradeable { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } // File: @openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: @openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981Upgradeable is IERC165Upgradeable { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); } // File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); } // File: @openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721MetadataUpgradeable is IERC721Upgradeable { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } // File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * ==== * * [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (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 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/contracts-upgradeable/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v4.8.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] * ``` * 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) || (!AddressUpgradeable.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 Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } } // File: operator-filter-registry/src/upgradeable/OperatorFiltererUpgradeable.sol pragma solidity ^0.8.13; abstract contract OperatorFiltererUpgradeable is Initializable { error OperatorNotAllowed(address operator); IOperatorFilterRegistry constant operatorFilterRegistry = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); function __OperatorFilterer_init(address subscriptionOrRegistrantToCopy, bool subscribe) internal onlyInitializing { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(operatorFilterRegistry).code.length > 0) { if (!operatorFilterRegistry.isRegistered(address(this))) { if (subscribe) { operatorFilterRegistry.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { operatorFilterRegistry.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { operatorFilterRegistry.register(address(this)); } } } } } modifier onlyAllowedOperator(address from) virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(operatorFilterRegistry).code.length > 0) { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from == msg.sender) { _; return; } if (!operatorFilterRegistry.isOperatorAllowed(address(this), msg.sender)) { revert OperatorNotAllowed(msg.sender); } } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(operatorFilterRegistry).code.length > 0) { if (!operatorFilterRegistry.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } _; } } // File: operator-filter-registry/src/upgradeable/DefaultOperatorFiltererUpgradeable.sol pragma solidity ^0.8.13; abstract contract DefaultOperatorFiltererUpgradeable is OperatorFiltererUpgradeable { address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); function __DefaultOperatorFilterer_init() internal onlyInitializing { OperatorFiltererUpgradeable.__OperatorFilterer_init(DEFAULT_SUBSCRIPTION, true); } } // File: @openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File: @openzeppelin/contracts-upgradeable/token/common/ERC2981Upgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC2981Upgradeable is Initializable, IERC2981Upgradeable, ERC165Upgradeable { function __ERC2981_init() internal onlyInitializing { } function __ERC2981_init_unchained() internal onlyInitializing { } struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC165Upgradeable) returns (bool) { return interfaceId == type(IERC2981Upgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981Upgradeable */ function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) { RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId]; if (royalty.receiver == address(0)) { royalty = _defaultRoyaltyInfo; } uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator(); return (royalty.receiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: invalid receiver"); _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty( uint256 tokenId, address receiver, uint96 feeNumerator ) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: Invalid parameters"); _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[48] private __gap; } // File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } // File: @openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable { using AddressUpgradeable for address; using StringsUpgradeable for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC721_init_unchained(name_, symbol_); } function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC721Upgradeable).interfaceId || interfaceId == type(IERC721MetadataUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721Upgradeable.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721Upgradeable.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721Upgradeable.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721Upgradeable.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721ReceiverUpgradeable.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256, /* firstTokenId */ uint256 batchSize ) internal virtual { if (batchSize > 1) { if (from != address(0)) { _balances[from] -= batchSize; } if (to != address(0)) { _balances[to] += batchSize; } } } /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[44] private __gap; } // File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File: contracts/NFT.sol pragma solidity 0.8.13; contract NFT is ERC721Upgradeable, OwnableUpgradeable, ReentrancyGuard, ERC2981Upgradeable, DefaultOperatorFiltererUpgradeable { using SafeERC20 for IERC20; struct Parameters { address storageContract; // Address of the storage contract address payingToken; // Address of ERC20 paying token or ETH address (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) uint256 mintPrice; // Mint price uint256 whitelistMintPrice; // Mint price for whitelisted users string contractURI; // Contract URI (for OpenSea) string erc721name; // The name of the collection string erc721shortName; // The symbol of the collection bool transferable; // Flag if the tokens transferable or not uint256 maxTotalSupply; // The max amount of tokens to be minted address feeReceiver; // The receiver of the royalties uint96 feeNumerator; // Fee numerator uint256 collectionExpire; // The period of time in which collection is expired (for the BE) address creator; // Creator address } address public payingToken; // Current token accepted as a mint payment address public storageContract; // Storage contract address uint256 public mintPrice; // Mint price uint256 public whitelistMintPrice; // Mint price for whitelisted users bool public transferable; // Flag if the tokens transferable or not uint256 public totalSupply; // The current totalSupply uint256 public maxTotalSupply; // The max amount of tokens to be minted uint96 public totalRoyalty; // Royalty fraction for platform + Royalty fraction for creator address public creator; // Creator address uint256 public collectionExpire; // The period of time in which collection is expired (for the BE) string public contractURI; // Contract URI (for OpenSea) address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; mapping(uint256 => string) public metadataUri; // token ID -> metadata link mapping(uint256 => uint256) public creationTs; // token ID -> creation Ts event PayingTokenChanged( address oldToken, address newToken, uint256 oldPrice, uint256 newPrice, uint256 oldWLPrice, uint256 newWLPrice ); modifier onlyCreator() { require(_msgSender() == creator, "not creator"); _; } /** * @dev called by factory when instance deployed * @param _params Collection parameters */ function initialize( Parameters memory _params ) external initializer { __ERC721_init(_params.erc721name, _params.erc721shortName); __Ownable_init(); __ERC2981_init(); __DefaultOperatorFilterer_init(); require(_params.payingToken != address(0), "incorrect paying token address"); require(_params.storageContract != address(0), "incorrect storage contract address"); require(_params.feeReceiver != address(0), "incorrect fee receiver address"); require(_params.creator != address(0), "incorrect creator address"); payingToken = _params.payingToken; mintPrice = _params.mintPrice; whitelistMintPrice = _params.whitelistMintPrice; contractURI = _params.contractURI; storageContract = _params.storageContract; transferable = _params.transferable; maxTotalSupply = _params.maxTotalSupply; _setDefaultRoyalty(_params.feeReceiver, _params.feeNumerator); totalRoyalty = _params.feeNumerator; creator = _params.creator; collectionExpire = _params.collectionExpire; } /** * @notice Mints new NFT * @dev Requires a signature from the trusted address * @param reciever Address that gets ERC721 token * @param tokenId ID of a ERC721 token to mint * @param tokenUri Metadata URI of the ERC721 token * @param whitelisted A flag if the user whitelisted or not * @param signature Signature of the trusted address */ function mint( address reciever, uint256 tokenId, string calldata tokenUri, bool whitelisted, bytes calldata signature, uint256 _expectedMintPrice, address _expectedPayingToken ) external payable nonReentrant { require( _verifySignature(reciever, tokenId, tokenUri, whitelisted, signature), "Invalid signature" ); require(totalSupply + 1 <= maxTotalSupply, "limit exceeded"); _mint(reciever, tokenId); totalSupply++; metadataUri[tokenId] = tokenUri; creationTs[tokenId] = block.timestamp; uint256 amount; address payingToken_ = payingToken; uint256 fee; uint8 feeBPs = IFactory(IStorageContract(storageContract).factory()) .platformCommission(); uint256 price = whitelisted ? whitelistMintPrice : mintPrice; require(_expectedMintPrice == price, "price changed"); require(_expectedPayingToken == payingToken_, "token changed"); address platformAddress = IFactory(IStorageContract(storageContract).factory()).platformAddress(); if (payingToken_ == ETH) { require(msg.value == price, "Not enough ether sent"); amount = msg.value; if (feeBPs == 0) { (bool success, ) = payable(creator).call{value: amount}(""); require(success, "Low-level call failed"); } else { fee = (amount * uint256(feeBPs)) / _feeDenominator(); (bool success1, ) = payable(platformAddress).call{value: fee}(""); (bool success2, ) = payable(creator).call{value: amount - fee}(""); require(success1 && success2, "Low-level call failed"); } } else { amount = price; if (feeBPs == 0) { IERC20(payingToken_).safeTransferFrom(msg.sender, creator, amount); } else { fee = (amount * uint256(feeBPs)) / _feeDenominator(); IERC20(payingToken_).safeTransferFrom(msg.sender, platformAddress, fee); IERC20(payingToken_).safeTransferFrom(msg.sender, creator, amount - fee); } } } /** * @notice Sets paying token * @param _payingToken New token address */ function setPayingToken( address _payingToken, uint256 _mintPrice, uint256 _whitelistMintPrice ) external onlyCreator { require(_payingToken != address(0), "incorrect paying token address"); address oldToken = payingToken; uint256 oldPrice = mintPrice; uint256 oldWLPrice = whitelistMintPrice; payingToken = _payingToken; mintPrice = _mintPrice; whitelistMintPrice = _whitelistMintPrice; emit PayingTokenChanged( oldToken, _payingToken, oldPrice, _mintPrice, oldWLPrice, _whitelistMintPrice ); } /** * @notice Returns if specified interface is supported or no * @param interfaceId Interface ID */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC2981Upgradeable, ERC721Upgradeable) returns (bool) { return ERC2981Upgradeable.supportsInterface(interfaceId) || ERC721Upgradeable.supportsInterface(interfaceId); } /** * @notice Returns metadata link for specified ID * @param _tokenId Token ID */ function tokenURI(uint256 _tokenId) public view override returns (string memory) { return metadataUri[_tokenId]; } /** * @notice owner() function overriding for OpenSea */ function owner() public view override returns (address) { return IFactory(IStorageContract(storageContract).factory()).platformAddress(); } /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. * Overridden with onlyAllowedOperatorApproval modifier to follow OpenSea royalties requirements. */ function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. * Overridden with onlyAllowedOperatorApproval modifier to follow OpenSea royalties requirements. */ function approve(address operator, uint256 tokenId) public override onlyAllowedOperatorApproval(operator) { super.approve(operator, tokenId); } /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. * Overridden with onlyAllowedOperator modifier to follow OpenSea royalties requirements. */ function transferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) { super.transferFrom(from, to, tokenId); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. * Overridden with onlyAllowedOperator modifier to follow OpenSea royalties requirements. */ function safeTransferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. * Overridden with onlyAllowedOperator modifier to follow OpenSea royalties requirements. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, data); } /** * @dev Transfers the token via ERC721's _transfer() function * if the collection is transferrable * @param from Inherited from ERC721's _transfer() function * @param to Inherited from ERC721's _transfer() function * @param tokenId Inherited from ERC721's _transfer() function */ function _transfer( address from, address to, uint256 tokenId ) internal virtual override { require(transferable, "token is not transferable"); super._transfer(from, to, tokenId); } /** * @dev Verifies if the signature belongs to the current signer address * @param receiver The token receiver * @param tokenId The token ID * @param tokenUri The token URI * @param whitelisted If the receiver is whitelisted or no * @param signature The signature to check */ function _verifySignature( address receiver, uint256 tokenId, string memory tokenUri, bool whitelisted, bytes memory signature ) internal view returns (bool) { return ECDSA.recover( keccak256( abi.encodePacked( receiver, tokenId, tokenUri, whitelisted, block.chainid ) ), signature ) == IFactory(IStorageContract(storageContract).factory()).signerAddress(); } } // File: contracts/Factory.sol pragma solidity 0.8.13; contract Factory is OwnableUpgradeable { struct InstanceInfo { string name; // name of a new collection string symbol; // symbol of a new collection string contractURI; // contract URI of a new collection address payingToken; // paying token of a new collection uint256 mintPrice; // mint price of a token from a new collection uint256 whitelistMintPrice; // mint price of a token from a new collection for whitelisted users bool transferable; // shows if tokens will be transferrable or not uint256 maxTotalSupply; // max total supply of a new collection uint96 feeNumerator; // total fee amount (in BPS) of a new collection address feeReceiver; // royalties receiver address uint256 collectionExpire; // The period of time in which collection is expired (for the BE) bytes signature; // BE's signature } address public platformAddress; // Address which is allowed to collect platform fee address public storageContract; // Storage contract address address public signerAddress; // Signer address uint8 public platformCommission; // Platform comission BPs event InstanceCreated( string name, string symbol, address instance, uint256 length ); event SignerSet(address newSigner); event PlatformComissionSet(uint8 newComission); event PlatformAddressSet(address newPlatformAddress); /** * @notice Initializes the contract * @param _signer The signer address * @param _platformAddress The platform address * @param _platformCommission The platform comission (BPs) * @param _storageContract The storage contract address */ function initialize( address _signer, address _platformAddress, uint8 _platformCommission, address _storageContract ) external initializer { __Ownable_init(); require(_signer != address(0), "incorrect signer address"); require(_platformAddress != address(0), "incorrect platform address"); require(_storageContract != address(0), "incorrect storage contract address"); signerAddress = _signer; platformAddress = _platformAddress; platformCommission = _platformCommission; storageContract = _storageContract; } /** * @notice Sets new platform comission * @dev Only owner can call it * @param _platformCommission The platform comission */ function setPlatformCommission(uint8 _platformCommission) external onlyOwner { platformCommission = _platformCommission; emit PlatformComissionSet(_platformCommission); } /** * @notice Sets new platform address * @dev Only owner can call it * @param _platformAddress The platform address */ function setPlatformAddress(address _platformAddress) external onlyOwner { require(_platformAddress != address(0), "incorrect address"); platformAddress = _platformAddress; emit PlatformAddressSet(_platformAddress); } /** * @notice Sets new signer address * @dev Only owner can call it * @param _signer The signer address */ function setSigner(address _signer) external onlyOwner { require(_signer != address(0), "incorrect address"); signerAddress = _signer; emit SignerSet(_signer); } /** * @notice produces new instance with defined name and symbol * @param _info The new instance's info * @return The new instance's address */ function produce( InstanceInfo memory _info ) external returns (address) { require( _verifySignature( _info.name, _info.symbol, _info.contractURI, _info.feeNumerator, _info.feeReceiver, _info.signature ), "Invalid signature" ); _createInstanceValidate(_info.name, _info.symbol); address instanceCreated = _createInstance(_info.name, _info.symbol); require( instanceCreated != address(0), "Factory: INSTANCE_CREATION_FAILED" ); NFT.Parameters memory params = NFT.Parameters( storageContract, _info.payingToken, _info.mintPrice, _info.whitelistMintPrice, _info.contractURI, _info.name, _info.symbol, _info.transferable, _info.maxTotalSupply, _info.feeReceiver, _info.feeNumerator, _info.collectionExpire, _msgSender() ); NFT(payable(instanceCreated)).initialize(params); return instanceCreated; } /** * @dev Creates a new instance of NFT and adds the info * into the Storage contract * @param name New instance's name * @param symbol New instance's symbol * @return instanceAddress The new instance's address */ function _createInstance(string memory name, string memory symbol) internal returns (address instanceAddress) { NFT instance = new NFT(); instanceAddress = address(instance); uint256 id = IStorageContract(storageContract).addInstance( instanceAddress, _msgSender(), name, symbol ); emit InstanceCreated(name, symbol, instanceAddress, id); } /** * @dev Checks if instance with specified name and symbol already exists * @param name New instance's name * @param symbol New instance's symbol */ function _createInstanceValidate(string memory name, string memory symbol) internal view { require((bytes(name)).length != 0, "Factory: EMPTY NAME"); require((bytes(symbol)).length != 0, "Factory: EMPTY SYMBOL"); require( IStorageContract(storageContract).getInstance( keccak256(abi.encodePacked(name, symbol)) ) == address(0), "Factory: ALREADY_EXISTS" ); } /** * @dev Verifies if the signature belongs to the current signer address * @param name New instance's name * @param symbol New instance's symbol * @param contractURI New instance's contract URI * @param feeNumerator Fee numerator for ERC2981 * @param feeReceiver Fee receiver for ERC2981 * @param signature The signature to check */ function _verifySignature( string memory name, string memory symbol, string memory contractURI, uint96 feeNumerator, address feeReceiver, bytes memory signature ) internal view returns (bool) { return ECDSA.recover( keccak256( abi.encodePacked( name, symbol, contractURI, feeNumerator, feeReceiver, block.chainid ) ), signature ) == signerAddress; } uint256[49] private __gap; }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"address","name":"instance","type":"address"},{"indexed":false,"internalType":"uint256","name":"length","type":"uint256"}],"name":"InstanceCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPlatformAddress","type":"address"}],"name":"PlatformAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"newComission","type":"uint8"}],"name":"PlatformComissionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"SignerSet","type":"event"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"},{"internalType":"address","name":"_platformAddress","type":"address"},{"internalType":"uint8","name":"_platformCommission","type":"uint8"},{"internalType":"address","name":"_storageContract","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformCommission","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"contractURI","type":"string"},{"internalType":"address","name":"payingToken","type":"address"},{"internalType":"uint256","name":"mintPrice","type":"uint256"},{"internalType":"uint256","name":"whitelistMintPrice","type":"uint256"},{"internalType":"bool","name":"transferable","type":"bool"},{"internalType":"uint256","name":"maxTotalSupply","type":"uint256"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"},{"internalType":"address","name":"feeReceiver","type":"address"},{"internalType":"uint256","name":"collectionExpire","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Factory.InstanceInfo","name":"_info","type":"tuple"}],"name":"produce","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_platformAddress","type":"address"}],"name":"setPlatformAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_platformCommission","type":"uint8"}],"name":"setPlatformCommission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"storageContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061500e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063715018a611610071578063715018a61461015d5780638da5cb5b14610165578063cc03c34214610176578063dbe55e5614610189578063f2fde38b1461019c578063ffea632b146101af57600080fd5b806311ce0267146100b9578063242494b8146100e95780635b7633d0146100fe5780636216557d14610111578063694e91b8146101245780636c19e7831461014a575b600080fd5b6066546100cc906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100fc6100f7366004610f16565b6101c2565b005b6067546100cc906001600160a01b031681565b6100cc61011f36600461104c565b61021f565b60675461013890600160a01b900460ff1681565b60405160ff90911681526020016100e0565b6100fc610158366004611199565b610452565b6100fc6104f2565b6033546001600160a01b03166100cc565b6100fc610184366004611199565b610506565b6065546100cc906001600160a01b031681565b6100fc6101aa366004611199565b6105a6565b6100fc6101bd3660046111b6565b61061f565b6101ca610896565b6067805460ff60a01b1916600160a01b60ff8416908102919091179091556040519081527f0acc3dd2571e3a1cfe25e8daf878fc868637bb75bd736d9d280c5f49996f48c7906020015b60405180910390a150565b600061024a8260000151836020015184604001518561010001518661012001518761016001516108f0565b61028f5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064015b60405180910390fd5b6102a182600001518360200151610950565b60006102b583600001518460200151610ad8565b90506001600160a01b0381166103175760405162461bcd60e51b815260206004820152602160248201527f466163746f72793a20494e5354414e43455f4352454154494f4e5f4641494c456044820152601160fa1b6064820152608401610286565b6000604051806101a00160405280606660009054906101000a90046001600160a01b03166001600160a01b0316815260200185606001516001600160a01b03168152602001856080015181526020018560a0015181526020018560400151815260200185600001518152602001856020015181526020018560c00151151581526020018560e0015181526020018561012001516001600160a01b031681526020018561010001516001600160601b0316815260200185610140015181526020016103de3390565b6001600160a01b03168152509050816001600160a01b031663c38fb8d7826040518263ffffffff1660e01b8152600401610418919061126c565b600060405180830381600087803b15801561043257600080fd5b505af1158015610446573d6000803e3d6000fd5b50939695505050505050565b61045a610896565b6001600160a01b0381166104a45760405162461bcd60e51b8152602060048201526011602482015270696e636f7272656374206164647265737360781b6044820152606401610286565b606780546001600160a01b0319166001600160a01b0383169081179091556040519081527f9eaa897564d022fb8c5efaf0acdb5d9d27b440b2aad44400b6e1c702e65b9ed390602001610214565b6104fa610896565b6105046000610bcb565b565b61050e610896565b6001600160a01b0381166105585760405162461bcd60e51b8152602060048201526011602482015270696e636f7272656374206164647265737360781b6044820152606401610286565b606580546001600160a01b0319166001600160a01b0383169081179091556040519081527fd22c5811315100afb9d8ffedcf57744c71fa573dc3d98daf03af5ae5134e740190602001610214565b6105ae610896565b6001600160a01b0381166106135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610286565b61061c81610bcb565b50565b600054610100900460ff161580801561063f5750600054600160ff909116105b806106595750303b158015610659575060005460ff166001145b6106bc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610286565b6000805460ff1916600117905580156106df576000805461ff0019166101001790555b6106e7610c1d565b6001600160a01b03851661073d5760405162461bcd60e51b815260206004820152601860248201527f696e636f7272656374207369676e6572206164647265737300000000000000006044820152606401610286565b6001600160a01b0384166107935760405162461bcd60e51b815260206004820152601a60248201527f696e636f727265637420706c6174666f726d20616464726573730000000000006044820152606401610286565b6001600160a01b0382166107f45760405162461bcd60e51b815260206004820152602260248201527f696e636f72726563742073746f7261676520636f6e7472616374206164647265604482015261737360f01b6064820152608401610286565b60678054606580546001600160a01b038881166001600160a01b03199283161790925560ff8716600160a01b026001600160a81b0319909316828a1617929092179092556066805492851692909116919091179055801561088f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6033546001600160a01b031633146105045760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610286565b6067546040516000916001600160a01b03169061093b9061091f908a908a908a908a908a904690602001611392565b6040516020818303038152906040528051906020012084610c4c565b6001600160a01b031614979650505050505050565b81516000036109975760405162461bcd60e51b8152602060048201526013602482015272466163746f72793a20454d505459204e414d4560681b6044820152606401610286565b80516000036109e05760405162461bcd60e51b8152602060048201526015602482015274119858dd1bdc9e4e8811535415164814d6535093d3605a1b6044820152606401610286565b6066546040516000916001600160a01b03169063624a23e090610a09908690869060200161140b565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610a3d91815260200190565b602060405180830381865afa158015610a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7e919061143a565b6001600160a01b031614610ad45760405162461bcd60e51b815260206004820152601760248201527f466163746f72793a20414c52454144595f4558495354530000000000000000006044820152606401610286565b5050565b600080604051610ae790610ef3565b604051809103906000f080158015610b03573d6000803e3d6000fd5b506066549092508291506000906001600160a01b031663cca12e5f833388886040518563ffffffff1660e01b8152600401610b419493929190611457565b6020604051808303816000875af1158015610b60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8491906114a0565b90507fd72ed290f33fdcda2caebbec226872d6e876f58141ddbf9c58624a34605da16c85858584604051610bbb94939291906114b9565b60405180910390a1505092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610c445760405162461bcd60e51b8152600401610286906114fb565b610504610c70565b6000806000610c5b8585610ca0565b91509150610c6881610ce5565b509392505050565b600054610100900460ff16610c975760405162461bcd60e51b8152600401610286906114fb565b61050433610bcb565b6000808251604103610cd65760208301516040840151606085015160001a610cca87828585610e2f565b94509450505050610cde565b506000905060025b9250929050565b6000816004811115610cf957610cf9611546565b03610d015750565b6001816004811115610d1557610d15611546565b03610d625760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610286565b6002816004811115610d7657610d76611546565b03610dc35760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610286565b6003816004811115610dd757610dd7611546565b0361061c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610286565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610e665750600090506003610eea565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610eba573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610ee357600060019250925050610eea565b9150600090505b94509492505050565b613a7c8061155d83390190565b803560ff81168114610f1157600080fd5b919050565b600060208284031215610f2857600080fd5b610f3182610f00565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff81118282101715610f7257610f72610f38565b60405290565b600082601f830112610f8957600080fd5b813567ffffffffffffffff80821115610fa457610fa4610f38565b604051601f8301601f19908116603f01168101908282118183101715610fcc57610fcc610f38565b81604052838152866020858801011115610fe557600080fd5b836020870160208301376000602085830101528094505050505092915050565b6001600160a01b038116811461061c57600080fd5b8035610f1181611005565b80358015158114610f1157600080fd5b80356001600160601b0381168114610f1157600080fd5b60006020828403121561105e57600080fd5b813567ffffffffffffffff8082111561107657600080fd5b90830190610180828603121561108b57600080fd5b611093610f4e565b8235828111156110a257600080fd5b6110ae87828601610f78565b8252506020830135828111156110c357600080fd5b6110cf87828601610f78565b6020830152506040830135828111156110e757600080fd5b6110f387828601610f78565b6040830152506111056060840161101a565b60608201526080830135608082015260a083013560a082015261112a60c08401611025565b60c082015260e083013560e0820152610100611147818501611035565b9082015261012061115984820161101a565b908201526101408381013590820152610160808401358381111561117c57600080fd5b61118888828701610f78565b918301919091525095945050505050565b6000602082840312156111ab57600080fd5b8135610f3181611005565b600080600080608085870312156111cc57600080fd5b84356111d781611005565b935060208501356111e781611005565b92506111f560408601610f00565b9150606085013561120581611005565b939692955090935050565b60005b8381101561122b578181015183820152602001611213565b8381111561123a576000848401525b50505050565b60008151808452611258816020860160208601611210565b601f01601f19169290920160200192915050565b602081526112866020820183516001600160a01b03169052565b600060208301516112a260408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516101a08060a08501526112d36101c0850183611240565b915060a0850151601f19808685030160c08701526112f18483611240565b935060c08701519150808685030160e08701525061130f8382611240565b92505060e08501516101006113278187018315159052565b860151610120868101919091528601519050610140611350818701836001600160a01b03169052565b860151905061016061136c868201836001600160601b03169052565b86015161018086810191909152909501516001600160a01b031693019290925250919050565b600087516113a4818460208c01611210565b8751908301906113b8818360208c01611210565b87519101906113cb818360208b01611210565b60a09690961b6001600160a01b0319169501948552505060609190911b6bffffffffffffffffffffffff1916600c83015260208201526040019392505050565b6000835161141d818460208801611210565b835190830190611431818360208801611210565b01949350505050565b60006020828403121561144c57600080fd5b8151610f3181611005565b6001600160a01b0385811682528416602082015260806040820181905260009061148390830185611240565b82810360608401526114958185611240565b979650505050505050565b6000602082840312156114b257600080fd5b5051919050565b6080815260006114cc6080830187611240565b82810360208401526114de8187611240565b6001600160a01b0395909516604084015250506060015292915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052602160045260246000fdfe608060405234801561001057600080fd5b50600160c955613a57806100256000396000f3fe6080604052600436106101f95760003560e01c80636e44628d1161010d578063a22cb465116100a0578063da11bf051161006f578063da11bf05146105de578063e8a3d485146105f1578063e985e9c514610606578063ed5dafcf1461064f578063f2fde38b1461066f57600080fd5b8063a22cb4651461055e578063b88d4fde1461057e578063c38fb8d71461059e578063c87b56dd146105be57600080fd5b80638322fff2116100dc5780638322fff2146104f15780638da5cb5b1461051957806392ff0d311461052e57806395d89b411461054957600080fd5b80636e44628d1461048557806370a082311461049c578063715018a6146104bc57806380a7589b146104d157600080fd5b806323b872dd1161019057806342842e0e1161015f57806342842e0e146103d6578063555d6331146103f65780635a998a09146104165780636352211e1461044f5780636817c76c1461046f57600080fd5b806323b872dd1461034a5780632a55205a1461036a5780632ab4d052146103a957806335c6aaf8146103c057600080fd5b8063095ea7b3116101cc578063095ea7b3146102b5578063112016d5146102d757806311ce02671461031357806318160ddd1461033357600080fd5b806301ffc9a7146101fe57806302d05d3f1461023357806306fdde0314610273578063081812fc14610295575b600080fd5b34801561020a57600080fd5b5061021e6102193660046130f3565b61068f565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b506101035461025b90600160601b90046001600160a01b031681565b6040516001600160a01b03909116815260200161022a565b34801561027f57600080fd5b506102886106af565b60405161022a919061316f565b3480156102a157600080fd5b5061025b6102b0366004613182565b610741565b3480156102c157600080fd5b506102d56102d03660046131c0565b610768565b005b3480156102e357600080fd5b506103056102f2366004613182565b6101076020526000908152604090205481565b60405190815260200161022a565b34801561031f57600080fd5b5060fd5461025b906001600160a01b031681565b34801561033f57600080fd5b506103056101015481565b34801561035657600080fd5b506102d56103653660046131ec565b610836565b34801561037657600080fd5b5061038a61038536600461322d565b61090f565b604080516001600160a01b03909316835260208301919091520161022a565b3480156103b557600080fd5b506103056101025481565b3480156103cc57600080fd5b5061030560ff5481565b3480156103e257600080fd5b506102d56103f13660046131ec565b6109bd565b34801561040257600080fd5b5060fc5461025b906001600160a01b031681565b34801561042257600080fd5b5061010354610437906001600160601b031681565b6040516001600160601b03909116815260200161022a565b34801561045b57600080fd5b5061025b61046a366004613182565b610a8b565b34801561047b57600080fd5b5061030560fe5481565b34801561049157600080fd5b506103056101045481565b3480156104a857600080fd5b506103056104b736600461324f565b610aeb565b3480156104c857600080fd5b506102d5610b71565b3480156104dd57600080fd5b506102d56104ec36600461326c565b610b85565b3480156104fd57600080fd5b5061025b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561052557600080fd5b5061025b610cc8565b34801561053a57600080fd5b506101005461021e9060ff1681565b34801561055557600080fd5b50610288610d9c565b34801561056a57600080fd5b506102d56105793660046132ba565b610dab565b34801561058a57600080fd5b506102d56105993660046133a9565b610e6f565b3480156105aa57600080fd5b506102d56105b9366004613460565b610f4b565b3480156105ca57600080fd5b506102886105d9366004613182565b6112c7565b6102d56105ec3660046135f5565b61136a565b3480156105fd57600080fd5b50610288611a21565b34801561061257600080fd5b5061021e6106213660046136b2565b6001600160a01b039182166000908152606a6020908152604080832093909416825291909152205460ff1690565b34801561065b57600080fd5b5061028861066a366004613182565b611ab0565b34801561067b57600080fd5b506102d561068a36600461324f565b611aca565b600061069a82611b43565b806106a957506106a982611b64565b92915050565b6060606580546106be906136e0565b80601f01602080910402602001604051908101604052809291908181526020018280546106ea906136e0565b80156107375780601f1061070c57610100808354040283529160200191610737565b820191906000526020600020905b81548152906001019060200180831161071a57829003601f168201915b5050505050905090565b600061074c82611bb4565b506000908152606960205260409020546001600160a01b031690565b816daaeb6d7670e522a718067333cd4e3b1561082757604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156107d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fa919061371a565b61082757604051633b79c77360e21b81526001600160a01b03821660048201526024015b60405180910390fd5b6108318383611c13565b505050565b826daaeb6d7670e522a718067333cd4e3b156108fe57336001600160a01b0382160361086c57610867848484611d23565b610909565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156108bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108df919061371a565b6108fe57604051633b79c77360e21b815233600482015260240161081e565b610909848484611d23565b50505050565b600082815260cb602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161098457506040805180820190915260ca546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906109a3906001600160601b03168761374d565b6109ad919061376c565b91519350909150505b9250929050565b826daaeb6d7670e522a718067333cd4e3b15610a8057336001600160a01b038216036109ee57610867848484611d54565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a61919061371a565b610a8057604051633b79c77360e21b815233600482015260240161081e565b610909848484611d54565b6000818152606760205260408120546001600160a01b0316806106a95760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161081e565b60006001600160a01b038216610b555760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161081e565b506001600160a01b031660009081526068602052604090205490565b610b79611d6f565b610b836000611dce565b565b61010354600160601b90046001600160a01b0316336001600160a01b031614610bde5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1031b932b0ba37b960a91b604482015260640161081e565b6001600160a01b038316610c345760405162461bcd60e51b815260206004820152601e60248201527f696e636f727265637420706179696e6720746f6b656e20616464726573730000604482015260640161081e565b60fc805460fe805460ff80546001600160a01b038981166001600160a01b031987168117909755938890559086905560408051939094168084526020840195909552928201819052606082018690526080820183905260a0820185905291907fbbbff5c0dc1bc311b7bdc812eb330c1ec3c2709fee18227781838688a3800a799060c00160405180910390a1505050505050565b60fd546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa158015610d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d36919061378e565b6001600160a01b031663dbe55e566040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d97919061378e565b905090565b6060606680546106be906136e0565b816daaeb6d7670e522a718067333cd4e3b15610e6557604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d919061371a565b610e6557604051633b79c77360e21b81526001600160a01b038216600482015260240161081e565b6108318383611e20565b836daaeb6d7670e522a718067333cd4e3b15610f3857336001600160a01b03821603610ea657610ea185858585611e2b565b610f44565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f19919061371a565b610f3857604051633b79c77360e21b815233600482015260240161081e565b610f4485858585611e2b565b5050505050565b600054610100900460ff1615808015610f6b5750600054600160ff909116105b80610f855750303b158015610f85575060005460ff166001145b610fe85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161081e565b6000805460ff19166001179055801561100b576000805461ff0019166101001790555b61101d8260a001518360c00151611e5d565b611025611e8e565b61102d611ebd565b611035611ee4565b60208201516001600160a01b031661108f5760405162461bcd60e51b815260206004820152601e60248201527f696e636f727265637420706179696e6720746f6b656e20616464726573730000604482015260640161081e565b81516001600160a01b03166110f15760405162461bcd60e51b815260206004820152602260248201527f696e636f72726563742073746f7261676520636f6e7472616374206164647265604482015261737360f01b606482015260840161081e565b6101208201516001600160a01b031661114c5760405162461bcd60e51b815260206004820152601e60248201527f696e636f72726563742066656520726563656976657220616464726573730000604482015260640161081e565b6101808201516001600160a01b03166111a75760405162461bcd60e51b815260206004820152601960248201527f696e636f72726563742063726561746f72206164647265737300000000000000604482015260640161081e565b60208281015160fc80546001600160a01b0319166001600160a01b03909216919091179055604083015160fe55606083015160ff55608083015180516111f292610105920190612fd0565b50815160fd80546001600160a01b0319166001600160a01b0390921691909117905560e0820151610100805460ff1916911515919091178155820151610102556101208201516101408301516112489190611f2a565b6101408201516101808301516001600160a01b0316600160601b026001600160601b0390911617610103556101608201516101045580156112c3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000818152610106602052604090208054606091906112e5906136e0565b80601f0160208091040260200160405190810160405280929190818152602001828054611311906136e0565b801561135e5780601f106113335761010080835404028352916020019161135e565b820191906000526020600020905b81548152906001019060200180831161134157829003601f168201915b50505050509050919050565b611372612027565b6113e9898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a81528c935091508a908a908190840183828082843760009201919091525061208092505050565b6114295760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b604482015260640161081e565b610102546101015461143c9060016137ab565b111561147b5760405162461bcd60e51b815260206004820152600e60248201526d1b1a5b5a5d08195e18d95959195960921b604482015260640161081e565b61148589896121a4565b6101018054906000611496836137c3565b90915550506000888152610106602052604090206114b5908888613054565b5060008881526101076020908152604080832042905560fc5460fd54825163c45a015560e01b815292516001600160a01b0392831694869485949093169263c45a015592600480830193928290030181865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d919061378e565b6001600160a01b031663694e91b86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561157a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159e91906137dc565b90506000896115af5760fe546115b3565b60ff545b90508087146115f45760405162461bcd60e51b815260206004820152600d60248201526c1c1c9a58d94818da185b99d959609a1b604482015260640161081e565b836001600160a01b0316866001600160a01b0316146116455760405162461bcd60e51b815260206004820152600d60248201526c1d1bdad95b8818da185b99d959609a1b604482015260640161081e565b60fd546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa15801561168f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b3919061378e565b6001600160a01b031663dbe55e566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611714919061378e565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601611967578134146117825760405162461bcd60e51b8152602060048201526015602482015274139bdd08195b9bdd59da08195d1a195c881cd95b9d605a1b604482015260640161081e565b3495508260ff166000036118395761010354604051600091600160601b90046001600160a01b03169088908381818185875af1925050503d80600081146117e5576040519150601f19603f3d011682016040523d82523d6000602084013e6117ea565b606091505b50509050806118335760405162461bcd60e51b8152602060048201526015602482015274131bddcb5b195d995b0818d85b1b0819985a5b1959605a1b604482015260640161081e565b50611a06565b61271061184960ff85168861374d565b611853919061376c565b93506000816001600160a01b03168560405160006040518083038185875af1925050503d80600081146118a2576040519150601f19603f3d011682016040523d82523d6000602084013e6118a7565b606091505b505061010354909150600090600160601b90046001600160a01b03166118cd878a6137ff565b604051600081818185875af1925050503d8060008114611909576040519150601f19603f3d011682016040523d82523d6000602084013e61190e565b606091505b5050905081801561191c5750805b6119605760405162461bcd60e51b8152602060048201526015602482015274131bddcb5b195d995b0818d85b1b0819985a5b1959605a1b604482015260640161081e565b5050611a06565b8195508260ff1660000361199f576101035461199a906001600160a01b03878116913391600160601b909104168961233d565b611a06565b6127106119af60ff85168861374d565b6119b9919061376c565b93506119d06001600160a01b03861633838761233d565b61010354611a06903390600160601b90046001600160a01b03166119f4878a6137ff565b6001600160a01b03891692919061233d565b505050505050611a16600160c955565b505050505050505050565b6101058054611a2f906136e0565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5b906136e0565b8015611aa85780601f10611a7d57610100808354040283529160200191611aa8565b820191906000526020600020905b815481529060010190602001808311611a8b57829003601f168201915b505050505081565b6101066020526000908152604090208054611a2f906136e0565b611ad2611d6f565b6001600160a01b038116611b375760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161081e565b611b4081611dce565b50565b60006001600160e01b0319821663152a902d60e11b14806106a957506106a9825b60006001600160e01b031982166380ac58cd60e01b1480611b9557506001600160e01b03198216635b5e139f60e01b145b806106a957506301ffc9a760e01b6001600160e01b03198316146106a9565b6000818152606760205260409020546001600160a01b0316611b405760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161081e565b6000611c1e82610a8b565b9050806001600160a01b0316836001600160a01b031603611c8b5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161081e565b336001600160a01b0382161480611ca75750611ca78133610621565b611d195760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161081e565b6108318383612397565b611d2d3382612405565b611d495760405162461bcd60e51b815260040161081e90613816565b610831838383612484565b61083183838360405180602001604052806000815250610e6f565b33611d78610cc8565b6001600160a01b031614610b835760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161081e565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6112c33383836124e2565b611e353383612405565b611e515760405162461bcd60e51b815260040161081e90613816565b610909848484846125b0565b600054610100900460ff16611e845760405162461bcd60e51b815260040161081e90613863565b6112c382826125e3565b600054610100900460ff16611eb55760405162461bcd60e51b815260040161081e90613863565b610b83612631565b600054610100900460ff16610b835760405162461bcd60e51b815260040161081e90613863565b600054610100900460ff16611f0b5760405162461bcd60e51b815260040161081e90613863565b610b83733cc6cdda760b79bafa08df41ecfa224f810dceb66001612661565b6127106001600160601b0382161115611f985760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b606482015260840161081e565b6001600160a01b038216611fee5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640161081e565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760ca55565b600260c954036120795760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161081e565b600260c955565b60fd546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee919061378e565b6001600160a01b0316635b7633d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561212b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214f919061378e565b6001600160a01b031661219087878787466040516020016121749594939291906138ae565b6040516020818303038152906040528051906020012084612808565b6001600160a01b0316149695505050505050565b6001600160a01b0382166121fa5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161081e565b6000818152606760205260409020546001600160a01b03161561225f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161081e565b61226d60008383600161282c565b6000818152606760205260409020546001600160a01b0316156122d25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161081e565b6001600160a01b038216600081815260686020908152604080832080546001019055848352606790915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526109099085906128b4565b600081815260696020526040902080546001600160a01b0319166001600160a01b03841690811790915581906123cc82610a8b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061241183610a8b565b9050806001600160a01b0316846001600160a01b0316148061245857506001600160a01b038082166000908152606a602090815260408083209388168352929052205460ff165b8061247c5750836001600160a01b031661247184610741565b6001600160a01b0316145b949350505050565b6101005460ff166124d75760405162461bcd60e51b815260206004820152601960248201527f746f6b656e206973206e6f74207472616e7366657261626c6500000000000000604482015260640161081e565b610831838383612986565b816001600160a01b0316836001600160a01b0316036125435760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161081e565b6001600160a01b038381166000818152606a6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6125bb848484612484565b6125c784848484612af7565b6109095760405162461bcd60e51b815260040161081e906138fe565b600054610100900460ff1661260a5760405162461bcd60e51b815260040161081e90613863565b815161261d906065906020850190612fd0565b508051610831906066906020840190612fd0565b600054610100900460ff166126585760405162461bcd60e51b815260040161081e90613863565b610b8333611dce565b600054610100900460ff166126885760405162461bcd60e51b815260040161081e90613863565b6daaeb6d7670e522a718067333cd4e3b156112c35760405163c3c5a54760e01b81523060048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af11580156126e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270c919061371a565b6112c357801561278857604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b15801561276c57600080fd5b505af1158015612780573d6000803e3d6000fd5b505050505050565b6001600160a01b038216156127d75760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af290390604401612752565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401612752565b60008060006128178585612bf8565b9150915061282481612c3a565b509392505050565b6001811115610909576001600160a01b03841615612872576001600160a01b0384166000908152606860205260408120805483929061286c9084906137ff565b90915550505b6001600160a01b03831615610909576001600160a01b038316600090815260686020526040812080548392906128a99084906137ab565b909155505050505050565b6000612909826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d849092919063ffffffff16565b8051909150156108315780806020019051810190612927919061371a565b6108315760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161081e565b826001600160a01b031661299982610a8b565b6001600160a01b0316146129bf5760405162461bcd60e51b815260040161081e90613950565b6001600160a01b038216612a215760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161081e565b612a2e838383600161282c565b826001600160a01b0316612a4182610a8b565b6001600160a01b031614612a675760405162461bcd60e51b815260040161081e90613950565b600081815260696020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260688552838620805460001901905590871680865283862080546001019055868652606790945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006001600160a01b0384163b15612bed57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b3b903390899088908890600401613995565b6020604051808303816000875af1925050508015612b76575060408051601f3d908101601f19168201909252612b73918101906139d2565b60015b612bd3573d808015612ba4576040519150601f19603f3d011682016040523d82523d6000602084013e612ba9565b606091505b508051600003612bcb5760405162461bcd60e51b815260040161081e906138fe565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061247c565b506001949350505050565b6000808251604103612c2e5760208301516040840151606085015160001a612c2287828585612d93565b945094505050506109b6565b506000905060026109b6565b6000816004811115612c4e57612c4e6139ef565b03612c565750565b6001816004811115612c6a57612c6a6139ef565b03612cb75760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161081e565b6002816004811115612ccb57612ccb6139ef565b03612d185760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161081e565b6003816004811115612d2c57612d2c6139ef565b03611b405760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161081e565b606061247c8484600085612e57565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612dca5750600090506003612e4e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612e1e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612e4757600060019250925050612e4e565b9150600090505b94509492505050565b606082471015612eb85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161081e565b600080866001600160a01b03168587604051612ed49190613a05565b60006040518083038185875af1925050503d8060008114612f11576040519150601f19603f3d011682016040523d82523d6000602084013e612f16565b606091505b5091509150612f2787838387612f32565b979650505050505050565b60608315612fa1578251600003612f9a576001600160a01b0385163b612f9a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161081e565b508161247c565b61247c8383815115612fb65781518083602001fd5b8060405162461bcd60e51b815260040161081e919061316f565b828054612fdc906136e0565b90600052602060002090601f016020900481019282612ffe5760008555613044565b82601f1061301757805160ff1916838001178555613044565b82800160010185558215613044579182015b82811115613044578251825591602001919060010190613029565b506130509291506130c8565b5090565b828054613060906136e0565b90600052602060002090601f0160209004810192826130825760008555613044565b82601f1061309b5782800160ff19823516178555613044565b82800160010185558215613044579182015b828111156130445782358255916020019190600101906130ad565b5b8082111561305057600081556001016130c9565b6001600160e01b031981168114611b4057600080fd5b60006020828403121561310557600080fd5b8135613110816130dd565b9392505050565b60005b8381101561313257818101518382015260200161311a565b838111156109095750506000910152565b6000815180845261315b816020860160208601613117565b601f01601f19169290920160200192915050565b6020815260006131106020830184613143565b60006020828403121561319457600080fd5b5035919050565b6001600160a01b0381168114611b4057600080fd5b80356131bb8161319b565b919050565b600080604083850312156131d357600080fd5b82356131de8161319b565b946020939093013593505050565b60008060006060848603121561320157600080fd5b833561320c8161319b565b9250602084013561321c8161319b565b929592945050506040919091013590565b6000806040838503121561324057600080fd5b50508035926020909101359150565b60006020828403121561326157600080fd5b81356131108161319b565b60008060006060848603121561328157600080fd5b833561328c8161319b565b95602085013595506040909401359392505050565b8015158114611b4057600080fd5b80356131bb816132a1565b600080604083850312156132cd57600080fd5b82356132d88161319b565b915060208301356132e8816132a1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6040516101a0810167ffffffffffffffff8111828210171561332d5761332d6132f3565b60405290565b600067ffffffffffffffff8084111561334e5761334e6132f3565b604051601f8501601f19908116603f01168101908282118183101715613376576133766132f3565b8160405280935085815286868601111561338f57600080fd5b858560208301376000602087830101525050509392505050565b600080600080608085870312156133bf57600080fd5b84356133ca8161319b565b935060208501356133da8161319b565b925060408501359150606085013567ffffffffffffffff8111156133fd57600080fd5b8501601f8101871361340e57600080fd5b61341d87823560208401613333565b91505092959194509250565b600082601f83011261343a57600080fd5b61311083833560208501613333565b80356001600160601b03811681146131bb57600080fd5b60006020828403121561347257600080fd5b813567ffffffffffffffff8082111561348a57600080fd5b908301906101a0828603121561349f57600080fd5b6134a7613309565b6134b0836131b0565b81526134be602084016131b0565b602082015260408301356040820152606083013560608201526080830135828111156134e957600080fd5b6134f587828601613429565b60808301525060a08301358281111561350d57600080fd5b61351987828601613429565b60a08301525060c08301358281111561353157600080fd5b61353d87828601613429565b60c08301525061354f60e084016132af565b60e08201526101008381013590820152610120915061356f8284016131b0565b828201526101409150613583828401613449565b828201526101609150818301358282015261018091506135a48284016131b0565b91810191909152949350505050565b60008083601f8401126135c557600080fd5b50813567ffffffffffffffff8111156135dd57600080fd5b6020830191508360208285010111156109b657600080fd5b600080600080600080600080600060e08a8c03121561361357600080fd5b893561361e8161319b565b985060208a0135975060408a013567ffffffffffffffff8082111561364257600080fd5b61364e8d838e016135b3565b909950975060608c01359150613663826132a1565b90955060808b0135908082111561367957600080fd5b506136868c828d016135b3565b90955093505060a08a0135915060c08a01356136a18161319b565b809150509295985092959850929598565b600080604083850312156136c557600080fd5b82356136d08161319b565b915060208301356132e88161319b565b600181811c908216806136f457607f821691505b60208210810361371457634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561372c57600080fd5b8151613110816132a1565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561376757613767613737565b500290565b60008261378957634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156137a057600080fd5b81516131108161319b565b600082198211156137be576137be613737565b500190565b6000600182016137d5576137d5613737565b5060010190565b6000602082840312156137ee57600080fd5b815160ff8116811461311057600080fd5b60008282101561381157613811613737565b500390565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160601b03198660601b168152846014820152600084516138d9816034850160208901613117565b93151560f81b9190930160348101919091526035810191909152605501949350505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906139c890830184613143565b9695505050505050565b6000602082840312156139e457600080fd5b8151613110816130dd565b634e487b7160e01b600052602160045260246000fd5b60008251613a17818460208701613117565b919091019291505056fea26469706673582212201fc6d9c9e3c5ce4a92f1a7d723419ef366ade8c62dcdb50ebac98bc5d2ddc25064736f6c634300080d0033a264697066735822122044800346286f1d75b8c4a86f3bb27ea1ef4de37f126f66f5f025c864421aadd964736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063715018a611610071578063715018a61461015d5780638da5cb5b14610165578063cc03c34214610176578063dbe55e5614610189578063f2fde38b1461019c578063ffea632b146101af57600080fd5b806311ce0267146100b9578063242494b8146100e95780635b7633d0146100fe5780636216557d14610111578063694e91b8146101245780636c19e7831461014a575b600080fd5b6066546100cc906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100fc6100f7366004610f16565b6101c2565b005b6067546100cc906001600160a01b031681565b6100cc61011f36600461104c565b61021f565b60675461013890600160a01b900460ff1681565b60405160ff90911681526020016100e0565b6100fc610158366004611199565b610452565b6100fc6104f2565b6033546001600160a01b03166100cc565b6100fc610184366004611199565b610506565b6065546100cc906001600160a01b031681565b6100fc6101aa366004611199565b6105a6565b6100fc6101bd3660046111b6565b61061f565b6101ca610896565b6067805460ff60a01b1916600160a01b60ff8416908102919091179091556040519081527f0acc3dd2571e3a1cfe25e8daf878fc868637bb75bd736d9d280c5f49996f48c7906020015b60405180910390a150565b600061024a8260000151836020015184604001518561010001518661012001518761016001516108f0565b61028f5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064015b60405180910390fd5b6102a182600001518360200151610950565b60006102b583600001518460200151610ad8565b90506001600160a01b0381166103175760405162461bcd60e51b815260206004820152602160248201527f466163746f72793a20494e5354414e43455f4352454154494f4e5f4641494c456044820152601160fa1b6064820152608401610286565b6000604051806101a00160405280606660009054906101000a90046001600160a01b03166001600160a01b0316815260200185606001516001600160a01b03168152602001856080015181526020018560a0015181526020018560400151815260200185600001518152602001856020015181526020018560c00151151581526020018560e0015181526020018561012001516001600160a01b031681526020018561010001516001600160601b0316815260200185610140015181526020016103de3390565b6001600160a01b03168152509050816001600160a01b031663c38fb8d7826040518263ffffffff1660e01b8152600401610418919061126c565b600060405180830381600087803b15801561043257600080fd5b505af1158015610446573d6000803e3d6000fd5b50939695505050505050565b61045a610896565b6001600160a01b0381166104a45760405162461bcd60e51b8152602060048201526011602482015270696e636f7272656374206164647265737360781b6044820152606401610286565b606780546001600160a01b0319166001600160a01b0383169081179091556040519081527f9eaa897564d022fb8c5efaf0acdb5d9d27b440b2aad44400b6e1c702e65b9ed390602001610214565b6104fa610896565b6105046000610bcb565b565b61050e610896565b6001600160a01b0381166105585760405162461bcd60e51b8152602060048201526011602482015270696e636f7272656374206164647265737360781b6044820152606401610286565b606580546001600160a01b0319166001600160a01b0383169081179091556040519081527fd22c5811315100afb9d8ffedcf57744c71fa573dc3d98daf03af5ae5134e740190602001610214565b6105ae610896565b6001600160a01b0381166106135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610286565b61061c81610bcb565b50565b600054610100900460ff161580801561063f5750600054600160ff909116105b806106595750303b158015610659575060005460ff166001145b6106bc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610286565b6000805460ff1916600117905580156106df576000805461ff0019166101001790555b6106e7610c1d565b6001600160a01b03851661073d5760405162461bcd60e51b815260206004820152601860248201527f696e636f7272656374207369676e6572206164647265737300000000000000006044820152606401610286565b6001600160a01b0384166107935760405162461bcd60e51b815260206004820152601a60248201527f696e636f727265637420706c6174666f726d20616464726573730000000000006044820152606401610286565b6001600160a01b0382166107f45760405162461bcd60e51b815260206004820152602260248201527f696e636f72726563742073746f7261676520636f6e7472616374206164647265604482015261737360f01b6064820152608401610286565b60678054606580546001600160a01b038881166001600160a01b03199283161790925560ff8716600160a01b026001600160a81b0319909316828a1617929092179092556066805492851692909116919091179055801561088f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6033546001600160a01b031633146105045760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610286565b6067546040516000916001600160a01b03169061093b9061091f908a908a908a908a908a904690602001611392565b6040516020818303038152906040528051906020012084610c4c565b6001600160a01b031614979650505050505050565b81516000036109975760405162461bcd60e51b8152602060048201526013602482015272466163746f72793a20454d505459204e414d4560681b6044820152606401610286565b80516000036109e05760405162461bcd60e51b8152602060048201526015602482015274119858dd1bdc9e4e8811535415164814d6535093d3605a1b6044820152606401610286565b6066546040516000916001600160a01b03169063624a23e090610a09908690869060200161140b565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610a3d91815260200190565b602060405180830381865afa158015610a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7e919061143a565b6001600160a01b031614610ad45760405162461bcd60e51b815260206004820152601760248201527f466163746f72793a20414c52454144595f4558495354530000000000000000006044820152606401610286565b5050565b600080604051610ae790610ef3565b604051809103906000f080158015610b03573d6000803e3d6000fd5b506066549092508291506000906001600160a01b031663cca12e5f833388886040518563ffffffff1660e01b8152600401610b419493929190611457565b6020604051808303816000875af1158015610b60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8491906114a0565b90507fd72ed290f33fdcda2caebbec226872d6e876f58141ddbf9c58624a34605da16c85858584604051610bbb94939291906114b9565b60405180910390a1505092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610c445760405162461bcd60e51b8152600401610286906114fb565b610504610c70565b6000806000610c5b8585610ca0565b91509150610c6881610ce5565b509392505050565b600054610100900460ff16610c975760405162461bcd60e51b8152600401610286906114fb565b61050433610bcb565b6000808251604103610cd65760208301516040840151606085015160001a610cca87828585610e2f565b94509450505050610cde565b506000905060025b9250929050565b6000816004811115610cf957610cf9611546565b03610d015750565b6001816004811115610d1557610d15611546565b03610d625760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610286565b6002816004811115610d7657610d76611546565b03610dc35760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610286565b6003816004811115610dd757610dd7611546565b0361061c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610286565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610e665750600090506003610eea565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610eba573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610ee357600060019250925050610eea565b9150600090505b94509492505050565b613a7c8061155d83390190565b803560ff81168114610f1157600080fd5b919050565b600060208284031215610f2857600080fd5b610f3182610f00565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff81118282101715610f7257610f72610f38565b60405290565b600082601f830112610f8957600080fd5b813567ffffffffffffffff80821115610fa457610fa4610f38565b604051601f8301601f19908116603f01168101908282118183101715610fcc57610fcc610f38565b81604052838152866020858801011115610fe557600080fd5b836020870160208301376000602085830101528094505050505092915050565b6001600160a01b038116811461061c57600080fd5b8035610f1181611005565b80358015158114610f1157600080fd5b80356001600160601b0381168114610f1157600080fd5b60006020828403121561105e57600080fd5b813567ffffffffffffffff8082111561107657600080fd5b90830190610180828603121561108b57600080fd5b611093610f4e565b8235828111156110a257600080fd5b6110ae87828601610f78565b8252506020830135828111156110c357600080fd5b6110cf87828601610f78565b6020830152506040830135828111156110e757600080fd5b6110f387828601610f78565b6040830152506111056060840161101a565b60608201526080830135608082015260a083013560a082015261112a60c08401611025565b60c082015260e083013560e0820152610100611147818501611035565b9082015261012061115984820161101a565b908201526101408381013590820152610160808401358381111561117c57600080fd5b61118888828701610f78565b918301919091525095945050505050565b6000602082840312156111ab57600080fd5b8135610f3181611005565b600080600080608085870312156111cc57600080fd5b84356111d781611005565b935060208501356111e781611005565b92506111f560408601610f00565b9150606085013561120581611005565b939692955090935050565b60005b8381101561122b578181015183820152602001611213565b8381111561123a576000848401525b50505050565b60008151808452611258816020860160208601611210565b601f01601f19169290920160200192915050565b602081526112866020820183516001600160a01b03169052565b600060208301516112a260408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516101a08060a08501526112d36101c0850183611240565b915060a0850151601f19808685030160c08701526112f18483611240565b935060c08701519150808685030160e08701525061130f8382611240565b92505060e08501516101006113278187018315159052565b860151610120868101919091528601519050610140611350818701836001600160a01b03169052565b860151905061016061136c868201836001600160601b03169052565b86015161018086810191909152909501516001600160a01b031693019290925250919050565b600087516113a4818460208c01611210565b8751908301906113b8818360208c01611210565b87519101906113cb818360208b01611210565b60a09690961b6001600160a01b0319169501948552505060609190911b6bffffffffffffffffffffffff1916600c83015260208201526040019392505050565b6000835161141d818460208801611210565b835190830190611431818360208801611210565b01949350505050565b60006020828403121561144c57600080fd5b8151610f3181611005565b6001600160a01b0385811682528416602082015260806040820181905260009061148390830185611240565b82810360608401526114958185611240565b979650505050505050565b6000602082840312156114b257600080fd5b5051919050565b6080815260006114cc6080830187611240565b82810360208401526114de8187611240565b6001600160a01b0395909516604084015250506060015292915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052602160045260246000fdfe608060405234801561001057600080fd5b50600160c955613a57806100256000396000f3fe6080604052600436106101f95760003560e01c80636e44628d1161010d578063a22cb465116100a0578063da11bf051161006f578063da11bf05146105de578063e8a3d485146105f1578063e985e9c514610606578063ed5dafcf1461064f578063f2fde38b1461066f57600080fd5b8063a22cb4651461055e578063b88d4fde1461057e578063c38fb8d71461059e578063c87b56dd146105be57600080fd5b80638322fff2116100dc5780638322fff2146104f15780638da5cb5b1461051957806392ff0d311461052e57806395d89b411461054957600080fd5b80636e44628d1461048557806370a082311461049c578063715018a6146104bc57806380a7589b146104d157600080fd5b806323b872dd1161019057806342842e0e1161015f57806342842e0e146103d6578063555d6331146103f65780635a998a09146104165780636352211e1461044f5780636817c76c1461046f57600080fd5b806323b872dd1461034a5780632a55205a1461036a5780632ab4d052146103a957806335c6aaf8146103c057600080fd5b8063095ea7b3116101cc578063095ea7b3146102b5578063112016d5146102d757806311ce02671461031357806318160ddd1461033357600080fd5b806301ffc9a7146101fe57806302d05d3f1461023357806306fdde0314610273578063081812fc14610295575b600080fd5b34801561020a57600080fd5b5061021e6102193660046130f3565b61068f565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b506101035461025b90600160601b90046001600160a01b031681565b6040516001600160a01b03909116815260200161022a565b34801561027f57600080fd5b506102886106af565b60405161022a919061316f565b3480156102a157600080fd5b5061025b6102b0366004613182565b610741565b3480156102c157600080fd5b506102d56102d03660046131c0565b610768565b005b3480156102e357600080fd5b506103056102f2366004613182565b6101076020526000908152604090205481565b60405190815260200161022a565b34801561031f57600080fd5b5060fd5461025b906001600160a01b031681565b34801561033f57600080fd5b506103056101015481565b34801561035657600080fd5b506102d56103653660046131ec565b610836565b34801561037657600080fd5b5061038a61038536600461322d565b61090f565b604080516001600160a01b03909316835260208301919091520161022a565b3480156103b557600080fd5b506103056101025481565b3480156103cc57600080fd5b5061030560ff5481565b3480156103e257600080fd5b506102d56103f13660046131ec565b6109bd565b34801561040257600080fd5b5060fc5461025b906001600160a01b031681565b34801561042257600080fd5b5061010354610437906001600160601b031681565b6040516001600160601b03909116815260200161022a565b34801561045b57600080fd5b5061025b61046a366004613182565b610a8b565b34801561047b57600080fd5b5061030560fe5481565b34801561049157600080fd5b506103056101045481565b3480156104a857600080fd5b506103056104b736600461324f565b610aeb565b3480156104c857600080fd5b506102d5610b71565b3480156104dd57600080fd5b506102d56104ec36600461326c565b610b85565b3480156104fd57600080fd5b5061025b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561052557600080fd5b5061025b610cc8565b34801561053a57600080fd5b506101005461021e9060ff1681565b34801561055557600080fd5b50610288610d9c565b34801561056a57600080fd5b506102d56105793660046132ba565b610dab565b34801561058a57600080fd5b506102d56105993660046133a9565b610e6f565b3480156105aa57600080fd5b506102d56105b9366004613460565b610f4b565b3480156105ca57600080fd5b506102886105d9366004613182565b6112c7565b6102d56105ec3660046135f5565b61136a565b3480156105fd57600080fd5b50610288611a21565b34801561061257600080fd5b5061021e6106213660046136b2565b6001600160a01b039182166000908152606a6020908152604080832093909416825291909152205460ff1690565b34801561065b57600080fd5b5061028861066a366004613182565b611ab0565b34801561067b57600080fd5b506102d561068a36600461324f565b611aca565b600061069a82611b43565b806106a957506106a982611b64565b92915050565b6060606580546106be906136e0565b80601f01602080910402602001604051908101604052809291908181526020018280546106ea906136e0565b80156107375780601f1061070c57610100808354040283529160200191610737565b820191906000526020600020905b81548152906001019060200180831161071a57829003601f168201915b5050505050905090565b600061074c82611bb4565b506000908152606960205260409020546001600160a01b031690565b816daaeb6d7670e522a718067333cd4e3b1561082757604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156107d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fa919061371a565b61082757604051633b79c77360e21b81526001600160a01b03821660048201526024015b60405180910390fd5b6108318383611c13565b505050565b826daaeb6d7670e522a718067333cd4e3b156108fe57336001600160a01b0382160361086c57610867848484611d23565b610909565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156108bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108df919061371a565b6108fe57604051633b79c77360e21b815233600482015260240161081e565b610909848484611d23565b50505050565b600082815260cb602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161098457506040805180820190915260ca546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906109a3906001600160601b03168761374d565b6109ad919061376c565b91519350909150505b9250929050565b826daaeb6d7670e522a718067333cd4e3b15610a8057336001600160a01b038216036109ee57610867848484611d54565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a61919061371a565b610a8057604051633b79c77360e21b815233600482015260240161081e565b610909848484611d54565b6000818152606760205260408120546001600160a01b0316806106a95760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161081e565b60006001600160a01b038216610b555760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161081e565b506001600160a01b031660009081526068602052604090205490565b610b79611d6f565b610b836000611dce565b565b61010354600160601b90046001600160a01b0316336001600160a01b031614610bde5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1031b932b0ba37b960a91b604482015260640161081e565b6001600160a01b038316610c345760405162461bcd60e51b815260206004820152601e60248201527f696e636f727265637420706179696e6720746f6b656e20616464726573730000604482015260640161081e565b60fc805460fe805460ff80546001600160a01b038981166001600160a01b031987168117909755938890559086905560408051939094168084526020840195909552928201819052606082018690526080820183905260a0820185905291907fbbbff5c0dc1bc311b7bdc812eb330c1ec3c2709fee18227781838688a3800a799060c00160405180910390a1505050505050565b60fd546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa158015610d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d36919061378e565b6001600160a01b031663dbe55e566040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d97919061378e565b905090565b6060606680546106be906136e0565b816daaeb6d7670e522a718067333cd4e3b15610e6557604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d919061371a565b610e6557604051633b79c77360e21b81526001600160a01b038216600482015260240161081e565b6108318383611e20565b836daaeb6d7670e522a718067333cd4e3b15610f3857336001600160a01b03821603610ea657610ea185858585611e2b565b610f44565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f19919061371a565b610f3857604051633b79c77360e21b815233600482015260240161081e565b610f4485858585611e2b565b5050505050565b600054610100900460ff1615808015610f6b5750600054600160ff909116105b80610f855750303b158015610f85575060005460ff166001145b610fe85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161081e565b6000805460ff19166001179055801561100b576000805461ff0019166101001790555b61101d8260a001518360c00151611e5d565b611025611e8e565b61102d611ebd565b611035611ee4565b60208201516001600160a01b031661108f5760405162461bcd60e51b815260206004820152601e60248201527f696e636f727265637420706179696e6720746f6b656e20616464726573730000604482015260640161081e565b81516001600160a01b03166110f15760405162461bcd60e51b815260206004820152602260248201527f696e636f72726563742073746f7261676520636f6e7472616374206164647265604482015261737360f01b606482015260840161081e565b6101208201516001600160a01b031661114c5760405162461bcd60e51b815260206004820152601e60248201527f696e636f72726563742066656520726563656976657220616464726573730000604482015260640161081e565b6101808201516001600160a01b03166111a75760405162461bcd60e51b815260206004820152601960248201527f696e636f72726563742063726561746f72206164647265737300000000000000604482015260640161081e565b60208281015160fc80546001600160a01b0319166001600160a01b03909216919091179055604083015160fe55606083015160ff55608083015180516111f292610105920190612fd0565b50815160fd80546001600160a01b0319166001600160a01b0390921691909117905560e0820151610100805460ff1916911515919091178155820151610102556101208201516101408301516112489190611f2a565b6101408201516101808301516001600160a01b0316600160601b026001600160601b0390911617610103556101608201516101045580156112c3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000818152610106602052604090208054606091906112e5906136e0565b80601f0160208091040260200160405190810160405280929190818152602001828054611311906136e0565b801561135e5780601f106113335761010080835404028352916020019161135e565b820191906000526020600020905b81548152906001019060200180831161134157829003601f168201915b50505050509050919050565b611372612027565b6113e9898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a81528c935091508a908a908190840183828082843760009201919091525061208092505050565b6114295760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b604482015260640161081e565b610102546101015461143c9060016137ab565b111561147b5760405162461bcd60e51b815260206004820152600e60248201526d1b1a5b5a5d08195e18d95959195960921b604482015260640161081e565b61148589896121a4565b6101018054906000611496836137c3565b90915550506000888152610106602052604090206114b5908888613054565b5060008881526101076020908152604080832042905560fc5460fd54825163c45a015560e01b815292516001600160a01b0392831694869485949093169263c45a015592600480830193928290030181865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d919061378e565b6001600160a01b031663694e91b86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561157a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159e91906137dc565b90506000896115af5760fe546115b3565b60ff545b90508087146115f45760405162461bcd60e51b815260206004820152600d60248201526c1c1c9a58d94818da185b99d959609a1b604482015260640161081e565b836001600160a01b0316866001600160a01b0316146116455760405162461bcd60e51b815260206004820152600d60248201526c1d1bdad95b8818da185b99d959609a1b604482015260640161081e565b60fd546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa15801561168f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b3919061378e565b6001600160a01b031663dbe55e566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611714919061378e565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601611967578134146117825760405162461bcd60e51b8152602060048201526015602482015274139bdd08195b9bdd59da08195d1a195c881cd95b9d605a1b604482015260640161081e565b3495508260ff166000036118395761010354604051600091600160601b90046001600160a01b03169088908381818185875af1925050503d80600081146117e5576040519150601f19603f3d011682016040523d82523d6000602084013e6117ea565b606091505b50509050806118335760405162461bcd60e51b8152602060048201526015602482015274131bddcb5b195d995b0818d85b1b0819985a5b1959605a1b604482015260640161081e565b50611a06565b61271061184960ff85168861374d565b611853919061376c565b93506000816001600160a01b03168560405160006040518083038185875af1925050503d80600081146118a2576040519150601f19603f3d011682016040523d82523d6000602084013e6118a7565b606091505b505061010354909150600090600160601b90046001600160a01b03166118cd878a6137ff565b604051600081818185875af1925050503d8060008114611909576040519150601f19603f3d011682016040523d82523d6000602084013e61190e565b606091505b5050905081801561191c5750805b6119605760405162461bcd60e51b8152602060048201526015602482015274131bddcb5b195d995b0818d85b1b0819985a5b1959605a1b604482015260640161081e565b5050611a06565b8195508260ff1660000361199f576101035461199a906001600160a01b03878116913391600160601b909104168961233d565b611a06565b6127106119af60ff85168861374d565b6119b9919061376c565b93506119d06001600160a01b03861633838761233d565b61010354611a06903390600160601b90046001600160a01b03166119f4878a6137ff565b6001600160a01b03891692919061233d565b505050505050611a16600160c955565b505050505050505050565b6101058054611a2f906136e0565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5b906136e0565b8015611aa85780601f10611a7d57610100808354040283529160200191611aa8565b820191906000526020600020905b815481529060010190602001808311611a8b57829003601f168201915b505050505081565b6101066020526000908152604090208054611a2f906136e0565b611ad2611d6f565b6001600160a01b038116611b375760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161081e565b611b4081611dce565b50565b60006001600160e01b0319821663152a902d60e11b14806106a957506106a9825b60006001600160e01b031982166380ac58cd60e01b1480611b9557506001600160e01b03198216635b5e139f60e01b145b806106a957506301ffc9a760e01b6001600160e01b03198316146106a9565b6000818152606760205260409020546001600160a01b0316611b405760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161081e565b6000611c1e82610a8b565b9050806001600160a01b0316836001600160a01b031603611c8b5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161081e565b336001600160a01b0382161480611ca75750611ca78133610621565b611d195760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161081e565b6108318383612397565b611d2d3382612405565b611d495760405162461bcd60e51b815260040161081e90613816565b610831838383612484565b61083183838360405180602001604052806000815250610e6f565b33611d78610cc8565b6001600160a01b031614610b835760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161081e565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6112c33383836124e2565b611e353383612405565b611e515760405162461bcd60e51b815260040161081e90613816565b610909848484846125b0565b600054610100900460ff16611e845760405162461bcd60e51b815260040161081e90613863565b6112c382826125e3565b600054610100900460ff16611eb55760405162461bcd60e51b815260040161081e90613863565b610b83612631565b600054610100900460ff16610b835760405162461bcd60e51b815260040161081e90613863565b600054610100900460ff16611f0b5760405162461bcd60e51b815260040161081e90613863565b610b83733cc6cdda760b79bafa08df41ecfa224f810dceb66001612661565b6127106001600160601b0382161115611f985760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b606482015260840161081e565b6001600160a01b038216611fee5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640161081e565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b9091021760ca55565b600260c954036120795760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161081e565b600260c955565b60fd546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee919061378e565b6001600160a01b0316635b7633d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561212b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214f919061378e565b6001600160a01b031661219087878787466040516020016121749594939291906138ae565b6040516020818303038152906040528051906020012084612808565b6001600160a01b0316149695505050505050565b6001600160a01b0382166121fa5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161081e565b6000818152606760205260409020546001600160a01b03161561225f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161081e565b61226d60008383600161282c565b6000818152606760205260409020546001600160a01b0316156122d25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161081e565b6001600160a01b038216600081815260686020908152604080832080546001019055848352606790915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526109099085906128b4565b600081815260696020526040902080546001600160a01b0319166001600160a01b03841690811790915581906123cc82610a8b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061241183610a8b565b9050806001600160a01b0316846001600160a01b0316148061245857506001600160a01b038082166000908152606a602090815260408083209388168352929052205460ff165b8061247c5750836001600160a01b031661247184610741565b6001600160a01b0316145b949350505050565b6101005460ff166124d75760405162461bcd60e51b815260206004820152601960248201527f746f6b656e206973206e6f74207472616e7366657261626c6500000000000000604482015260640161081e565b610831838383612986565b816001600160a01b0316836001600160a01b0316036125435760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161081e565b6001600160a01b038381166000818152606a6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6125bb848484612484565b6125c784848484612af7565b6109095760405162461bcd60e51b815260040161081e906138fe565b600054610100900460ff1661260a5760405162461bcd60e51b815260040161081e90613863565b815161261d906065906020850190612fd0565b508051610831906066906020840190612fd0565b600054610100900460ff166126585760405162461bcd60e51b815260040161081e90613863565b610b8333611dce565b600054610100900460ff166126885760405162461bcd60e51b815260040161081e90613863565b6daaeb6d7670e522a718067333cd4e3b156112c35760405163c3c5a54760e01b81523060048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af11580156126e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270c919061371a565b6112c357801561278857604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b15801561276c57600080fd5b505af1158015612780573d6000803e3d6000fd5b505050505050565b6001600160a01b038216156127d75760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af290390604401612752565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401612752565b60008060006128178585612bf8565b9150915061282481612c3a565b509392505050565b6001811115610909576001600160a01b03841615612872576001600160a01b0384166000908152606860205260408120805483929061286c9084906137ff565b90915550505b6001600160a01b03831615610909576001600160a01b038316600090815260686020526040812080548392906128a99084906137ab565b909155505050505050565b6000612909826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d849092919063ffffffff16565b8051909150156108315780806020019051810190612927919061371a565b6108315760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161081e565b826001600160a01b031661299982610a8b565b6001600160a01b0316146129bf5760405162461bcd60e51b815260040161081e90613950565b6001600160a01b038216612a215760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161081e565b612a2e838383600161282c565b826001600160a01b0316612a4182610a8b565b6001600160a01b031614612a675760405162461bcd60e51b815260040161081e90613950565b600081815260696020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260688552838620805460001901905590871680865283862080546001019055868652606790945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006001600160a01b0384163b15612bed57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b3b903390899088908890600401613995565b6020604051808303816000875af1925050508015612b76575060408051601f3d908101601f19168201909252612b73918101906139d2565b60015b612bd3573d808015612ba4576040519150601f19603f3d011682016040523d82523d6000602084013e612ba9565b606091505b508051600003612bcb5760405162461bcd60e51b815260040161081e906138fe565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061247c565b506001949350505050565b6000808251604103612c2e5760208301516040840151606085015160001a612c2287828585612d93565b945094505050506109b6565b506000905060026109b6565b6000816004811115612c4e57612c4e6139ef565b03612c565750565b6001816004811115612c6a57612c6a6139ef565b03612cb75760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161081e565b6002816004811115612ccb57612ccb6139ef565b03612d185760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161081e565b6003816004811115612d2c57612d2c6139ef565b03611b405760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161081e565b606061247c8484600085612e57565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612dca5750600090506003612e4e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612e1e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612e4757600060019250925050612e4e565b9150600090505b94509492505050565b606082471015612eb85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161081e565b600080866001600160a01b03168587604051612ed49190613a05565b60006040518083038185875af1925050503d8060008114612f11576040519150601f19603f3d011682016040523d82523d6000602084013e612f16565b606091505b5091509150612f2787838387612f32565b979650505050505050565b60608315612fa1578251600003612f9a576001600160a01b0385163b612f9a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161081e565b508161247c565b61247c8383815115612fb65781518083602001fd5b8060405162461bcd60e51b815260040161081e919061316f565b828054612fdc906136e0565b90600052602060002090601f016020900481019282612ffe5760008555613044565b82601f1061301757805160ff1916838001178555613044565b82800160010185558215613044579182015b82811115613044578251825591602001919060010190613029565b506130509291506130c8565b5090565b828054613060906136e0565b90600052602060002090601f0160209004810192826130825760008555613044565b82601f1061309b5782800160ff19823516178555613044565b82800160010185558215613044579182015b828111156130445782358255916020019190600101906130ad565b5b8082111561305057600081556001016130c9565b6001600160e01b031981168114611b4057600080fd5b60006020828403121561310557600080fd5b8135613110816130dd565b9392505050565b60005b8381101561313257818101518382015260200161311a565b838111156109095750506000910152565b6000815180845261315b816020860160208601613117565b601f01601f19169290920160200192915050565b6020815260006131106020830184613143565b60006020828403121561319457600080fd5b5035919050565b6001600160a01b0381168114611b4057600080fd5b80356131bb8161319b565b919050565b600080604083850312156131d357600080fd5b82356131de8161319b565b946020939093013593505050565b60008060006060848603121561320157600080fd5b833561320c8161319b565b9250602084013561321c8161319b565b929592945050506040919091013590565b6000806040838503121561324057600080fd5b50508035926020909101359150565b60006020828403121561326157600080fd5b81356131108161319b565b60008060006060848603121561328157600080fd5b833561328c8161319b565b95602085013595506040909401359392505050565b8015158114611b4057600080fd5b80356131bb816132a1565b600080604083850312156132cd57600080fd5b82356132d88161319b565b915060208301356132e8816132a1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6040516101a0810167ffffffffffffffff8111828210171561332d5761332d6132f3565b60405290565b600067ffffffffffffffff8084111561334e5761334e6132f3565b604051601f8501601f19908116603f01168101908282118183101715613376576133766132f3565b8160405280935085815286868601111561338f57600080fd5b858560208301376000602087830101525050509392505050565b600080600080608085870312156133bf57600080fd5b84356133ca8161319b565b935060208501356133da8161319b565b925060408501359150606085013567ffffffffffffffff8111156133fd57600080fd5b8501601f8101871361340e57600080fd5b61341d87823560208401613333565b91505092959194509250565b600082601f83011261343a57600080fd5b61311083833560208501613333565b80356001600160601b03811681146131bb57600080fd5b60006020828403121561347257600080fd5b813567ffffffffffffffff8082111561348a57600080fd5b908301906101a0828603121561349f57600080fd5b6134a7613309565b6134b0836131b0565b81526134be602084016131b0565b602082015260408301356040820152606083013560608201526080830135828111156134e957600080fd5b6134f587828601613429565b60808301525060a08301358281111561350d57600080fd5b61351987828601613429565b60a08301525060c08301358281111561353157600080fd5b61353d87828601613429565b60c08301525061354f60e084016132af565b60e08201526101008381013590820152610120915061356f8284016131b0565b828201526101409150613583828401613449565b828201526101609150818301358282015261018091506135a48284016131b0565b91810191909152949350505050565b60008083601f8401126135c557600080fd5b50813567ffffffffffffffff8111156135dd57600080fd5b6020830191508360208285010111156109b657600080fd5b600080600080600080600080600060e08a8c03121561361357600080fd5b893561361e8161319b565b985060208a0135975060408a013567ffffffffffffffff8082111561364257600080fd5b61364e8d838e016135b3565b909950975060608c01359150613663826132a1565b90955060808b0135908082111561367957600080fd5b506136868c828d016135b3565b90955093505060a08a0135915060c08a01356136a18161319b565b809150509295985092959850929598565b600080604083850312156136c557600080fd5b82356136d08161319b565b915060208301356132e88161319b565b600181811c908216806136f457607f821691505b60208210810361371457634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561372c57600080fd5b8151613110816132a1565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561376757613767613737565b500290565b60008261378957634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156137a057600080fd5b81516131108161319b565b600082198211156137be576137be613737565b500190565b6000600182016137d5576137d5613737565b5060010190565b6000602082840312156137ee57600080fd5b815160ff8116811461311057600080fd5b60008282101561381157613811613737565b500390565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160601b03198660601b168152846014820152600084516138d9816034850160208901613117565b93151560f81b9190930160348101919091526035810191909152605501949350505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906139c890830184613143565b9695505050505050565b6000602082840312156139e457600080fd5b8151613110816130dd565b634e487b7160e01b600052602160045260246000fd5b60008251613a17818460208701613117565b919091019291505056fea26469706673582212201fc6d9c9e3c5ce4a92f1a7d723419ef366ade8c62dcdb50ebac98bc5d2ddc25064736f6c634300080d0033a264697066735822122044800346286f1d75b8c4a86f3bb27ea1ef4de37f126f66f5f025c864421aadd964736f6c634300080d0033
Deployed Bytecode Sourcemap
134837:7460:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135877:30;;;;;-1:-1:-1;;;;;135877:30:0;;;;;;-1:-1:-1;;;;;287:32:1;;;269:51;;257:2;242:18;135877:30:0;;;;;;;;137427:193;;;;;;:::i;:::-;;:::i;:::-;;135943:28;;;;;-1:-1:-1;;;;;135943:28:0;;;138544:1243;;;;;;:::i;:::-;;:::i;135998:31::-;;;;;-1:-1:-1;;;135998:31:0;;;;;;;;;4301:4:1;4289:17;;;4271:36;;4259:2;4244:18;135998:31:0;4129:184:1;138170:193:0;;;;;;:::i;:::-;;:::i;119814:103::-;;;:::i;119166:87::-;119239:6;;-1:-1:-1;;;;;119239:6:0;119166:87;;137777:249;;;;;;:::i;:::-;;:::i;135788:30::-;;;;;-1:-1:-1;;;;;135788:30:0;;;120072:201;;;;;;:::i;:::-;;:::i;136636:627::-;;;;;;:::i;:::-;;:::i;137427:193::-;119052:13;:11;:13::i;:::-;137515:18:::1;:40:::0;;-1:-1:-1;;;;137515:40:0::1;-1:-1:-1::0;;;137515:40:0::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;137571:41:::1;::::0;4271:36:1;;;137571:41:0::1;::::0;4259:2:1;4244:18;137571:41:0::1;;;;;;;;137427:193:::0;:::o;138544:1243::-;138622:7;138664:238;138699:5;:10;;;138729:5;:12;;;138761:5;:17;;;138797:5;:18;;;138835:5;:17;;;138872:5;:15;;;138664:16;:238::i;:::-;138642:305;;;;-1:-1:-1;;;138642:305:0;;5377:2:1;138642:305:0;;;5359:21:1;5416:2;5396:18;;;5389:30;-1:-1:-1;;;5435:18:1;;;5428:47;5492:18;;138642:305:0;;;;;;;;;138958:49;138982:5;:10;;;138994:5;:12;;;138958:23;:49::i;:::-;139018:23;139044:41;139060:5;:10;;;139072:5;:12;;;139044:15;:41::i;:::-;139018:67;-1:-1:-1;;;;;;139118:29:0;;139096:112;;;;-1:-1:-1;;;139096:112:0;;5723:2:1;139096:112:0;;;5705:21:1;5762:2;5742:18;;;5735:30;5801:34;5781:18;;;5774:62;-1:-1:-1;;;5852:18:1;;;5845:31;5893:19;;139096:112:0;5521:397:1;139096:112:0;139219:28;139250:437;;;;;;;;139279:15;;;;;;;;;-1:-1:-1;;;;;139279:15:0;-1:-1:-1;;;;;139250:437:0;;;;;139309:5;:17;;;-1:-1:-1;;;;;139250:437:0;;;;;139341:5;:15;;;139250:437;;;;139371:5;:24;;;139250:437;;;;139410:5;:17;;;139250:437;;;;139442:5;:10;;;139250:437;;;;139467:5;:12;;;139250:437;;;;139494:5;:18;;;139250:437;;;;;;139527:5;:20;;;139250:437;;;;139562:5;:17;;;-1:-1:-1;;;;;139250:437:0;;;;;139594:5;:18;;;-1:-1:-1;;;;;139250:437:0;;;;;139627:5;:22;;;139250:437;;;;139664:12;99273:10;;99193:98;139664:12;-1:-1:-1;;;;;139250:437:0;;;;139219:468;;139710:15;-1:-1:-1;;;;;139698:40:0;;139739:6;139698:48;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;139764:15:0;;138544:1243;-1:-1:-1;;;;;;138544:1243:0:o;138170:193::-;119052:13;:11;:13::i;:::-;-1:-1:-1;;;;;138244:21:0;::::1;138236:51;;;::::0;-1:-1:-1;;;138236:51:0;;8704:2:1;138236:51:0::1;::::0;::::1;8686:21:1::0;8743:2;8723:18;;;8716:30;-1:-1:-1;;;8762:18:1;;;8755:47;8819:18;;138236:51:0::1;8502:341:1::0;138236:51:0::1;138298:13;:23:::0;;-1:-1:-1;;;;;;138298:23:0::1;-1:-1:-1::0;;;;;138298:23:0;::::1;::::0;;::::1;::::0;;;138337:18:::1;::::0;269:51:1;;;138337:18:0::1;::::0;257:2:1;242:18;138337::0::1;123:203:1::0;119814:103:0;119052:13;:11;:13::i;:::-;119879:30:::1;119906:1;119879:18;:30::i;:::-;119814:103::o:0;137777:249::-;119052:13;:11;:13::i;:::-;-1:-1:-1;;;;;137869:30:0;::::1;137861:60;;;::::0;-1:-1:-1;;;137861:60:0;;8704:2:1;137861:60:0::1;::::0;::::1;8686:21:1::0;8743:2;8723:18;;;8716:30;-1:-1:-1;;;8762:18:1;;;8755:47;8819:18;;137861:60:0::1;8502:341:1::0;137861:60:0::1;137932:15;:34:::0;;-1:-1:-1;;;;;;137932:34:0::1;-1:-1:-1::0;;;;;137932:34:0;::::1;::::0;;::::1;::::0;;;137982:36:::1;::::0;269:51:1;;;137982:36:0::1;::::0;257:2:1;242:18;137982:36:0::1;123:203:1::0;120072:201:0;119052:13;:11;:13::i;:::-;-1:-1:-1;;;;;120161:22:0;::::1;120153:73;;;::::0;-1:-1:-1;;;120153:73:0;;9050:2:1;120153:73:0::1;::::0;::::1;9032:21:1::0;9089:2;9069:18;;;9062:30;9128:34;9108:18;;;9101:62;-1:-1:-1;;;9179:18:1;;;9172:36;9225:19;;120153:73:0::1;8848:402:1::0;120153:73:0::1;120237:28;120256:8;120237:18;:28::i;:::-;120072:201:::0;:::o;136636:627::-;85480:19;85503:13;;;;;;85502:14;;85550:34;;;;-1:-1:-1;85568:12:0;;85583:1;85568:12;;;;:16;85550:34;85549:108;;;-1:-1:-1;85629:4:0;75141:19;:23;;;85590:66;;-1:-1:-1;85639:12:0;;;;;:17;85590:66;85527:204;;;;-1:-1:-1;;;85527:204:0;;9457:2:1;85527:204:0;;;9439:21:1;9496:2;9476:18;;;9469:30;9535:34;9515:18;;;9508:62;-1:-1:-1;;;9586:18:1;;;9579:44;9640:19;;85527:204:0;9255:410:1;85527:204:0;85742:12;:16;;-1:-1:-1;;85742:16:0;85757:1;85742:16;;;85769:67;;;;85804:13;:20;;-1:-1:-1;;85804:20:0;;;;;85769:67;136827:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;136862:21:0;::::1;136854:58;;;::::0;-1:-1:-1;;;136854:58:0;;9872:2:1;136854:58:0::1;::::0;::::1;9854:21:1::0;9911:2;9891:18;;;9884:30;9950:26;9930:18;;;9923:54;9994:18;;136854:58:0::1;9670:348:1::0;136854:58:0::1;-1:-1:-1::0;;;;;136931:30:0;::::1;136923:69;;;::::0;-1:-1:-1;;;136923:69:0;;10225:2:1;136923:69:0::1;::::0;::::1;10207:21:1::0;10264:2;10244:18;;;10237:30;10303:28;10283:18;;;10276:56;10349:18;;136923:69:0::1;10023:350:1::0;136923:69:0::1;-1:-1:-1::0;;;;;137011:30:0;::::1;137003:77;;;::::0;-1:-1:-1;;;137003:77:0;;10580:2:1;137003:77:0::1;::::0;::::1;10562:21:1::0;10619:2;10599:18;;;10592:30;10658:34;10638:18;;;10631:62;-1:-1:-1;;;10709:18:1;;;10702:32;10751:19;;137003:77:0::1;10378:398:1::0;137003:77:0::1;137091:13;:23:::0;;137125:15:::1;:34:::0;;-1:-1:-1;;;;;137125:34:0;;::::1;-1:-1:-1::0;;;;;;137125:34:0;;::::1;;::::0;;;137170:40:::1;::::0;::::1;-1:-1:-1::0;;;137170:40:0::1;-1:-1:-1::0;;;;;;137170:40:0;;;137091:23;;::::1;137170:40:::0;;;;::::1;::::0;;;137221:15:::1;:34:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;85858:102;;;;85909:5;85893:21;;-1:-1:-1;;85893:21:0;;;85934:14;;-1:-1:-1;4271:36:1;;85934:14:0;;4259:2:1;4244:18;85934:14:0;;;;;;;85858:102;85469:498;136636:627;;;;:::o;119331:132::-;119239:6;;-1:-1:-1;;;;;119239:6:0;99273:10;119395:23;119387:68;;;;-1:-1:-1;;;119387:68:0;;11182:2:1;119387:68:0;;;11164:21:1;;;11201:18;;;11194:30;11260:34;11240:18;;;11233:62;11312:18;;119387:68:0;10980:356:1;141580:678:0;142237:13;;141929:259;;141828:4;;-1:-1:-1;;;;;142237:13:0;;141865:368;;141929:259;;141972:4;;142004:6;;142037:11;;142075:12;;142114:11;;142152:13;;141929:259;;;:::i;:::-;;;;;;;;;;;;;141897:310;;;;;;142209:9;141865:13;:368::i;:::-;-1:-1:-1;;;;;141865:385:0;;;141580:678;-1:-1:-1;;;;;;;141580:678:0:o;140705:478::-;140843:4;140836:20;140860:1;140836:25;140828:57;;;;-1:-1:-1;;;140828:57:0;;12540:2:1;140828:57:0;;;12522:21:1;12579:2;12559:18;;;12552:30;-1:-1:-1;;;12598:18:1;;;12591:49;12657:18;;140828:57:0;12338:343:1;140828:57:0;140911:6;140904:22;140930:1;140904:27;140896:61;;;;-1:-1:-1;;;140896:61:0;;12888:2:1;140896:61:0;;;12870:21:1;12927:2;12907:18;;;12900:30;-1:-1:-1;;;12946:18:1;;;12939:51;13007:18;;140896:61:0;12686:345:1;140896:61:0;141007:15;;141064:30;;141122:1;;-1:-1:-1;;;;;141007:15:0;;140990:45;;141064:30;;141081:4;;141087:6;;141064:30;;;:::i;:::-;;;;;;;;;;;;;141054:41;;;;;;140990:120;;;;;;;;;;;;;13657:25:1;;13645:2;13630:18;;13511:177;140990:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;140990:134:0;;140968:207;;;;-1:-1:-1;;;140968:207:0;;14151:2:1;140968:207:0;;;14133:21:1;14190:2;14170:18;;;14163:30;14229:25;14209:18;;;14202:53;14272:18;;140968:207:0;13949:347:1;140968:207:0;140705:478;;:::o;140052:465::-;140155:23;140196:12;140211:9;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;140307:15:0;;140196:24;;-1:-1:-1;140196:24:0;;-1:-1:-1;140277:10:0;;-1:-1:-1;;;;;140307:15:0;140290:45;140196:24;99273:10;140407:4;140426:6;140290:153;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140277:166;;140459:50;140475:4;140481:6;140489:15;140506:2;140459:50;;;;;;;;;:::i;:::-;;;;;;;;140185:332;;140052:465;;;;:::o;120433:191::-;120526:6;;;-1:-1:-1;;;;;120543:17:0;;;-1:-1:-1;;;;;;120543:17:0;;;;;;;120576:40;;120526:6;;;120543:17;120526:6;;120576:40;;120507:16;;120576:40;120496:128;120433:191;:::o;118709:97::-;87623:13;;;;;;;87615:69;;;;-1:-1:-1;;;87615:69:0;;;;;;;:::i;:::-;118772:26:::1;:24;:26::i;22174:231::-:0;22252:7;22273:17;22292:18;22314:27;22325:4;22331:9;22314:10;:27::i;:::-;22272:69;;;;22352:18;22364:5;22352:11;:18::i;:::-;-1:-1:-1;22388:9:0;22174:231;-1:-1:-1;;;22174:231:0:o;118814:113::-;87623:13;;;;;;;87615:69;;;;-1:-1:-1;;;87615:69:0;;;;;;;:::i;:::-;118887:32:::1;99273:10:::0;118887:18:::1;:32::i;20625:747::-:0;20706:7;20715:12;20744:9;:16;20764:2;20744:22;20740:625;;21088:4;21073:20;;21067:27;21138:4;21123:20;;21117:27;21196:4;21181:20;;21175:27;20783:9;21167:36;21239:25;21250:4;21167:36;21067:27;21117;21239:10;:25::i;:::-;21232:32;;;;;;;;;20740:625;-1:-1:-1;21313:1:0;;-1:-1:-1;21317:35:0;20740:625;20625:747;;;;;:::o;19018:521::-;19096:20;19087:5;:29;;;;;;;;:::i;:::-;;19083:449;;19018:521;:::o;19083:449::-;19194:29;19185:5;:38;;;;;;;;:::i;:::-;;19181:351;;19240:34;;-1:-1:-1;;;19240:34:0;;16382:2:1;19240:34:0;;;16364:21:1;16421:2;16401:18;;;16394:30;16460:26;16440:18;;;16433:54;16504:18;;19240:34:0;16180:348:1;19181:351:0;19305:35;19296:5;:44;;;;;;;;:::i;:::-;;19292:240;;19357:41;;-1:-1:-1;;;19357:41:0;;16735:2:1;19357:41:0;;;16717:21:1;16774:2;16754:18;;;16747:30;16813:33;16793:18;;;16786:61;16864:18;;19357:41:0;16533:355:1;19292:240:0;19429:30;19420:5;:39;;;;;;;;:::i;:::-;;19416:116;;19476:44;;-1:-1:-1;;;19476:44:0;;17095:2:1;19476:44:0;;;17077:21:1;17134:2;17114:18;;;17107:30;17173:34;17153:18;;;17146:62;-1:-1:-1;;;17224:18:1;;;17217:32;17266:19;;19476:44:0;16893:398:1;23626:1520:0;23757:7;;24691:66;24678:79;;24674:163;;;-1:-1:-1;24790:1:0;;-1:-1:-1;24794:30:0;24774:51;;24674:163;24951:24;;;24934:14;24951:24;;;;;;;;;17523:25:1;;;17596:4;17584:17;;17564:18;;;17557:45;;;;17618:18;;;17611:34;;;17661:18;;;17654:34;;;24951:24:0;;17495:19:1;;24951:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;24951:24:0;;-1:-1:-1;;24951:24:0;;;-1:-1:-1;;;;;;;24990:20:0;;24986:103;;25043:1;25047:29;25027:50;;;;;;;24986:103;25109:6;-1:-1:-1;25117:20:0;;-1:-1:-1;23626:1520:0;;;;;;;;:::o;-1:-1:-1:-;;;;;;;;:::o;331:156:1:-;397:20;;457:4;446:16;;436:27;;426:55;;477:1;474;467:12;426:55;331:156;;;:::o;492:182::-;549:6;602:2;590:9;581:7;577:23;573:32;570:52;;;618:1;615;608:12;570:52;641:27;658:9;641:27;:::i;:::-;631:37;492:182;-1:-1:-1;;;492:182:1:o;679:127::-;740:10;735:3;731:20;728:1;721:31;771:4;768:1;761:15;795:4;792:1;785:15;811:250;878:2;872:9;920:6;908:19;;957:18;942:34;;978:22;;;939:62;936:88;;;1004:18;;:::i;:::-;1040:2;1033:22;811:250;:::o;1066:719::-;1109:5;1162:3;1155:4;1147:6;1143:17;1139:27;1129:55;;1180:1;1177;1170:12;1129:55;1216:6;1203:20;1242:18;1279:2;1275;1272:10;1269:36;;;1285:18;;:::i;:::-;1360:2;1354:9;1328:2;1414:13;;-1:-1:-1;;1410:22:1;;;1434:2;1406:31;1402:40;1390:53;;;1458:18;;;1478:22;;;1455:46;1452:72;;;1504:18;;:::i;:::-;1544:10;1540:2;1533:22;1579:2;1571:6;1564:18;1625:3;1618:4;1613:2;1605:6;1601:15;1597:26;1594:35;1591:55;;;1642:1;1639;1632:12;1591:55;1706:2;1699:4;1691:6;1687:17;1680:4;1672:6;1668:17;1655:54;1753:1;1746:4;1741:2;1733:6;1729:15;1725:26;1718:37;1773:6;1764:15;;;;;;1066:719;;;;:::o;1790:131::-;-1:-1:-1;;;;;1865:31:1;;1855:42;;1845:70;;1911:1;1908;1901:12;1926:134;1994:20;;2023:31;1994:20;2023:31;:::i;2065:160::-;2130:20;;2186:13;;2179:21;2169:32;;2159:60;;2215:1;2212;2205:12;2230:179;2297:20;;-1:-1:-1;;;;;2346:38:1;;2336:49;;2326:77;;2399:1;2396;2389:12;2414:1710;2503:6;2556:2;2544:9;2535:7;2531:23;2527:32;2524:52;;;2572:1;2569;2562:12;2524:52;2612:9;2599:23;2641:18;2682:2;2674:6;2671:14;2668:34;;;2698:1;2695;2688:12;2668:34;2721:22;;;;2777:6;2759:16;;;2755:29;2752:49;;;2797:1;2794;2787:12;2752:49;2823:17;;:::i;:::-;2878:2;2865:16;2906:2;2896:8;2893:16;2890:36;;;2922:1;2919;2912:12;2890:36;2949:45;2986:7;2975:8;2971:2;2967:17;2949:45;:::i;:::-;2942:5;2935:60;;3041:2;3037;3033:11;3020:25;3070:2;3060:8;3057:16;3054:36;;;3086:1;3083;3076:12;3054:36;3122:45;3159:7;3148:8;3144:2;3140:17;3122:45;:::i;:::-;3117:2;3110:5;3106:14;3099:69;;3214:2;3210;3206:11;3193:25;3243:2;3233:8;3230:16;3227:36;;;3259:1;3256;3249:12;3227:36;3295:45;3332:7;3321:8;3317:2;3313:17;3295:45;:::i;:::-;3290:2;3283:5;3279:14;3272:69;;3373:31;3400:2;3396;3392:11;3373:31;:::i;:::-;3368:2;3361:5;3357:14;3350:55;3459:3;3455:2;3451:12;3438:26;3432:3;3425:5;3421:15;3414:51;3519:3;3515:2;3511:12;3498:26;3492:3;3485:5;3481:15;3474:51;3558:29;3582:3;3578:2;3574:12;3558:29;:::i;:::-;3552:3;3545:5;3541:15;3534:54;3642:3;3638:2;3634:12;3621:26;3615:3;3608:5;3604:15;3597:51;3667:3;3702:30;3728:2;3724;3720:11;3702:30;:::i;:::-;3686:14;;;3679:54;3752:3;3787:31;3806:11;;;3787:31;:::i;:::-;3771:14;;;3764:55;3838:3;3886:11;;;3873:25;3857:14;;;3850:49;3918:3;3959:11;;;3946:25;3983:16;;;3980:36;;;4012:1;4009;4002:12;3980:36;4048:45;4085:7;4074:8;4070:2;4066:17;4048:45;:::i;:::-;4032:14;;;4025:69;;;;-1:-1:-1;4036:5:1;2414:1710;-1:-1:-1;;;;;2414:1710:1:o;4318:247::-;4377:6;4430:2;4418:9;4409:7;4405:23;4401:32;4398:52;;;4446:1;4443;4436:12;4398:52;4485:9;4472:23;4504:31;4529:5;4504:31;:::i;4570:600::-;4654:6;4662;4670;4678;4731:3;4719:9;4710:7;4706:23;4702:33;4699:53;;;4748:1;4745;4738:12;4699:53;4787:9;4774:23;4806:31;4831:5;4806:31;:::i;:::-;4856:5;-1:-1:-1;4913:2:1;4898:18;;4885:32;4926:33;4885:32;4926:33;:::i;:::-;4978:7;-1:-1:-1;5004:36:1;5036:2;5021:18;;5004:36;:::i;:::-;4994:46;;5092:2;5081:9;5077:18;5064:32;5105:33;5130:7;5105:33;:::i;:::-;4570:600;;;;-1:-1:-1;4570:600:1;;-1:-1:-1;;4570:600:1:o;5923:258::-;5995:1;6005:113;6019:6;6016:1;6013:13;6005:113;;;6095:11;;;6089:18;6076:11;;;6069:39;6041:2;6034:10;6005:113;;;6136:6;6133:1;6130:13;6127:48;;;6171:1;6162:6;6157:3;6153:16;6146:27;6127:48;;5923:258;;;:::o;6186:::-;6228:3;6266:5;6260:12;6293:6;6288:3;6281:19;6309:63;6365:6;6358:4;6353:3;6349:14;6342:4;6335:5;6331:16;6309:63;:::i;:::-;6426:2;6405:15;-1:-1:-1;;6401:29:1;6392:39;;;;6433:4;6388:50;;6186:258;-1:-1:-1;;6186:258:1:o;6660:1837::-;6845:2;6834:9;6827:21;6857:53;6906:2;6895:9;6891:18;6882:6;6876:13;-1:-1:-1;;;;;80:31:1;68:44;;14:104;6857:53;6808:4;6957:2;6949:6;6945:15;6939:22;6970:52;7018:2;7007:9;7003:18;6989:12;-1:-1:-1;;;;;80:31:1;68:44;;14:104;6970:52;;7076:2;7068:6;7064:15;7058:22;7053:2;7042:9;7038:18;7031:50;7136:2;7128:6;7124:15;7118:22;7112:3;7101:9;7097:19;7090:51;7190:3;7182:6;7178:16;7172:23;7214:6;7257:2;7251:3;7240:9;7236:19;7229:31;7283:54;7332:3;7321:9;7317:19;7301:14;7283:54;:::i;:::-;7269:68;;7386:3;7378:6;7374:16;7368:23;7414:2;7410:7;7482:2;7470:9;7462:6;7458:22;7454:31;7448:3;7437:9;7433:19;7426:60;7509:41;7543:6;7527:14;7509:41;:::i;:::-;7495:55;;7599:3;7591:6;7587:16;7581:23;7559:45;;7669:2;7657:9;7649:6;7645:22;7641:31;7635:3;7624:9;7620:19;7613:60;;7696:41;7730:6;7714:14;7696:41;:::i;:::-;7682:55;;;7786:3;7778:6;7774:16;7768:23;7810:3;7822:51;7869:2;7858:9;7854:18;7838:14;6519:13;6512:21;6500:34;;6449:91;7822:51;7898:15;;7892:22;7933:3;7952:18;;;7945:30;;;;8012:15;;8006:22;;-1:-1:-1;8047:3:1;8059:54;8094:18;;;8006:22;-1:-1:-1;;;;;80:31:1;68:44;;14:104;8059:54;8150:15;;8144:22;;-1:-1:-1;8185:3:1;8197:53;8231:18;;;8144:22;-1:-1:-1;;;;;6610:38:1;6598:51;;6545:110;8197:53;8275:15;;8269:22;8310:3;8329:18;;;8322:30;;;;8389:15;;;8383:22;-1:-1:-1;;;;;80:31:1;8449:18;;68:44;;;;-1:-1:-1;8485:6:1;;-1:-1:-1;6660:1837:1:o;11341:992::-;11650:3;11688:6;11682:13;11704:53;11750:6;11745:3;11738:4;11730:6;11726:17;11704:53;:::i;:::-;11820:13;;11779:16;;;;11842:57;11820:13;11779:16;11876:4;11864:17;;11842:57;:::i;:::-;11966:13;;11921:20;;;11988:57;11966:13;11921:20;12022:4;12010:17;;11988:57;:::i;:::-;12136:3;12114:16;;;;-1:-1:-1;;;;;;12110:59:1;12067:20;;12096:74;;;-1:-1:-1;;12210:2:1;12206:15;;;;-1:-1:-1;;12202:53:1;12197:2;12186:14;;12179:77;12283:4;12272:16;;12265:32;12324:2;12313:14;;11341:992;-1:-1:-1;;;11341:992:1:o;13036:470::-;13215:3;13253:6;13247:13;13269:53;13315:6;13310:3;13303:4;13295:6;13291:17;13269:53;:::i;:::-;13385:13;;13344:16;;;;13407:57;13385:13;13344:16;13441:4;13429:17;;13407:57;:::i;:::-;13480:20;;13036:470;-1:-1:-1;;;;13036:470:1:o;13693:251::-;13763:6;13816:2;13804:9;13795:7;13791:23;13787:32;13784:52;;;13832:1;13829;13822:12;13784:52;13864:9;13858:16;13883:31;13908:5;13883:31;:::i;14301:583::-;-1:-1:-1;;;;;14592:15:1;;;14574:34;;14644:15;;14639:2;14624:18;;14617:43;14696:3;14691:2;14676:18;;14669:31;;;14517:4;;14723:46;;14749:19;;14741:6;14723:46;:::i;:::-;14817:9;14809:6;14805:22;14800:2;14789:9;14785:18;14778:50;14845:33;14871:6;14863;14845:33;:::i;:::-;14837:41;14301:583;-1:-1:-1;;;;;;;14301:583:1:o;14889:184::-;14959:6;15012:2;15000:9;14991:7;14987:23;14983:32;14980:52;;;15028:1;15025;15018:12;14980:52;-1:-1:-1;15051:16:1;;14889:184;-1:-1:-1;14889:184:1:o;15078:553::-;15331:3;15320:9;15313:22;15294:4;15358:46;15399:3;15388:9;15384:19;15376:6;15358:46;:::i;:::-;15452:9;15444:6;15440:22;15435:2;15424:9;15420:18;15413:50;15480:33;15506:6;15498;15480:33;:::i;:::-;-1:-1:-1;;;;;15549:32:1;;;;15544:2;15529:18;;15522:60;-1:-1:-1;;15613:2:1;15598:18;15591:34;15472:41;15078:553;-1:-1:-1;;15078:553:1:o;15636:407::-;15838:2;15820:21;;;15877:2;15857:18;;;15850:30;15916:34;15911:2;15896:18;;15889:62;-1:-1:-1;;;15982:2:1;15967:18;;15960:41;16033:3;16018:19;;15636:407::o;16048:127::-;16109:10;16104:3;16100:20;16097:1;16090:31;16140:4;16137:1;16130:15;16164:4;16161:1;16154:15
Swarm Source
ipfs://44800346286f1d75b8c4a86f3bb27ea1ef4de37f126f66f5f025c864421aadd9
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.