Feature Tip: Add private address tag to any address under My Name Tag !
Overview
TokenID
212
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
NFiniTiMembership
Compiler Version
v0.8.25+commit.b61c2a91
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-05-27 */ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @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 } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile 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 {MessageHashUtils-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] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { 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, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); 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] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. 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. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // 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, s); } // 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, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @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, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); 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 if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // 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; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } } // File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the 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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (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 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 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. uint256 twos = denominator & (0 - denominator); 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 (unsignedRoundsUp(rounding) && 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 * towards zero. * * 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @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), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; 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] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; /** * @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. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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 { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _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); } } // File: @openzeppelin/contracts/access/Ownable2Step.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @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/utils/introspection/IERC165.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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 IERC165 { /** * @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/utils/introspection/ERC165.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; /** * @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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/token/ERC721/IERC721.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @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 address zero. * * 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/token/ERC721/extensions/IERC721Enumerable.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.20; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.20; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @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/token/ERC721/ERC721.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.20; /** * @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}. */ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors { using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; mapping(uint256 tokenId => address) private _owners; mapping(address owner => uint256) private _balances; mapping(uint256 tokenId => address) private _tokenApprovals; mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual returns (uint256) { if (owner == address(0)) { revert ERC721InvalidOwner(address(0)); } return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual returns (address) { return _requireOwned(tokenId); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual returns (string memory) { _requireOwned(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string.concat(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 { _approve(to, tokenId, _msgSender()); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual returns (address) { _requireOwned(tokenId); return _getApproved(tokenId); } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. address previousOwner = _update(to, tokenId, _msgSender()); if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { transferFrom(from, to, tokenId); _checkOnERC721Received(from, to, tokenId, data); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist * * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`. */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. */ function _getApproved(uint256 tokenId) internal view virtual returns (address) { return _tokenApprovals[tokenId]; } /** * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in * particular (ignoring whether it is owned by `owner`). * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) { return spender != address(0) && (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender); } /** * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner. * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets * the `spender` for the specific `tokenId`. * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual { if (!_isAuthorized(owner, spender, tokenId)) { if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } else { revert ERC721InsufficientApproval(spender, tokenId); } } } /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that * a uint256 would ever overflow from increments when these increments are bounded to uint128 values. * * WARNING: Increasing an account's balance using this function tends to be paired with an override of the * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership * remain consistent with one another. */ function _increaseBalance(address account, uint128 value) internal virtual { unchecked { _balances[account] += value; } } /** * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update. * * The `auth` argument is optional. If the value passed is non 0, then this function will check that * `auth` is either the owner of the token, or approved to operate on the token (by the owner). * * Emits a {Transfer} event. * * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}. */ function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) { address from = _ownerOf(tokenId); // Perform (optional) operator check if (auth != address(0)) { _checkAuthorized(from, auth, tokenId); } // Execute the update if (from != address(0)) { // Clear approval. No need to re-authorize or emit the Approval event _approve(address(0), tokenId, address(0), false); unchecked { _balances[from] -= 1; } } if (to != address(0)) { unchecked { _balances[to] += 1; } } _owners[tokenId] = to; emit Transfer(from, to, tokenId); return from; } /** * @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 { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner != address(0)) { revert ERC721InvalidSender(address(0)); } } /** * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance. * * 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 { _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); _checkOnERC721Received(address(0), to, tokenId, data); } /** * @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 { address previousOwner = _update(address(0), tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } } /** * @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 { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } else if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients * are aware of the ERC721 standard 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 like {safeTransferFrom} in the sense that it invokes * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `tokenId` token must exist and be owned by `from`. * - `to` cannot be the zero address. * - `from` cannot be the zero address. * - 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) internal { _safeTransfer(from, to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); _checkOnERC721Received(from, to, tokenId, data); } /** * @dev Approve `to` to operate on `tokenId` * * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is * either the owner of the token, or approved to operate on all tokens held by this owner. * * Emits an {Approval} event. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address to, uint256 tokenId, address auth) internal { _approve(to, tokenId, auth, true); } /** * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not * emitted in the context of transfers. */ function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual { // Avoid reading the owner unless necessary if (emitEvent || auth != address(0)) { address owner = _requireOwned(tokenId); // We do not use _isAuthorized because single-token approvals should not be able to call approve if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) { revert ERC721InvalidApprover(auth); } if (emitEvent) { emit Approval(owner, to, tokenId); } } _tokenApprovals[tokenId] = to; } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Requirements: * - operator can't be the address zero. * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC721InvalidOperator(operator); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). * Returns the owner. * * Overrides to ownership logic should be done to {_ownerOf}. */ function _requireOwned(uint256 tokenId) internal view returns (address) { address owner = _ownerOf(tokenId); if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } return owner; } /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the * recipient doesn't accept the token transfer. 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 */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private { if (to.code.length > 0) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { if (retval != IERC721Receiver.onERC721Received.selector) { revert ERC721InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { revert ERC721InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } } // File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.20; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability * of all the token ids in the contract as well as all token ids owned by each account. * * CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`, * interfere with enumerability and should not be used together with `ERC721Enumerable`. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens; mapping(uint256 tokenId => uint256) private _ownedTokensIndex; uint256[] private _allTokens; mapping(uint256 tokenId => uint256) private _allTokensIndex; /** * @dev An `owner`'s token query was out of bounds for `index`. * * NOTE: The owner being `address(0)` indicates a global out of bounds index. */ error ERC721OutOfBoundsIndex(address owner, uint256 index); /** * @dev Batch mint is not allowed. */ error ERC721EnumerableForbiddenBatchMint(); /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) { if (index >= balanceOf(owner)) { revert ERC721OutOfBoundsIndex(owner, index); } return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual returns (uint256) { if (index >= totalSupply()) { revert ERC721OutOfBoundsIndex(address(0), index); } return _allTokens[index]; } /** * @dev See {ERC721-_update}. */ function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) { address previousOwner = super._update(to, tokenId, auth); if (previousOwner == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (previousOwner != to) { _removeTokenFromOwnerEnumeration(previousOwner, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (previousOwner != to) { _addTokenToOwnerEnumeration(to, tokenId); } return previousOwner; } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = balanceOf(to) - 1; _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = balanceOf(from); uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } /** * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch */ function _increaseBalance(address account, uint128 amount) internal virtual override { if (amount > 0) { revert ERC721EnumerableForbiddenBatchMint(); } super._increaseBalance(account, amount); } } // File: contracts/NFiniTiMembership.sol pragma solidity ^0.8.24; /** * @title NFiniTi Membership NFT Contract * * @dev This contract manages the issuance and administration of NFiniTi * Membership NFTs. * * It supports controlled minting of NFTs across different levels, with each * NFT representing a tier of membership within the NFiniTi ecosystem. * * Minting a Membership NFT require a signature-based minting authorization * */ contract NFiniTiMembership is ERC721, ReentrancyGuard, ERC721Enumerable, Ownable2Step { using Address for address; using Strings for uint256; using ECDSA for bytes32; /// @notice event emitted when the contract is paused event Paused(); /// @notice event emitted when the contract is unpaused event Unpaused(); /// @notice event emitted when the funds are withdrawn event WithdrawCalled(address indexed to, uint256 amount); /// @notice event emitted when the contract base URI is updated event BaseURIUpdated(string baseURI); /// @notice event emitted when the withdrawal address is updated event WithdrawalAddressUpdated(address withdrawalAddress); /// @notice event emitted when the authorized signer is updated event AuthorizedSignerUpdated(address authorizedSigner); /// @notice event emitted when the authorized signer is updated event MembershipMinted(address minter, uint256 tokenId); /// @notice Address authorized to mint NFTs address public authorizedSigner; /// @notice Address where funds will be sent upon withdrawal address public withdrawalAddress; /// @notice Base URI for NFT metadata string public baseURI; /// @notice variable to store the paused state of the contract bool public paused; struct LevelInfo { uint256 mintCount; // Current number of mints for this level } /// @dev Array of maximum mints allowed per level, index 0 is level 1 uint256[] public maxMintsPerLevel; /// @notice Mapping of the token levels mapping(uint256 level => LevelInfo) public levelInfos; // Mapping from token ID to its level mapping(uint256 tokenId => uint256 level) private tokenLevels; /// @dev Custom errors error InvalidLevelError(); error InvalidPriceError(); error InvalidRecipientError(); error InvalidSignatureError(); error MintLimitReachedError(); error MintPausedError(); error NoAddressZeroError(); error NoFundsToWithdrawError(); error NotAuthorizedError(); /** * @dev Sets the initial values for the contract * @param authorizedSigner_ Address authorized to mint NFTs * @param withdrawalAddress_ Address where funds will be withdrawn to * @param maxMintsPerLevel_ Array specifying the max NFTs per level * @param baseURI_ Base URI for NFT metadata */ constructor( address initialOwner_, address authorizedSigner_, address withdrawalAddress_, string memory baseURI_, uint256[] memory maxMintsPerLevel_ ) ERC721("NFiniTi Membership", "NFTM") Ownable(initialOwner_) { authorizedSigner = authorizedSigner_; withdrawalAddress = withdrawalAddress_; baseURI = baseURI_; // Set the maximum mints for each level, only 3 levels are supported maxMintsPerLevel = maxMintsPerLevel_; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. * @param tokenId_ The token ID for which to return the URI. * @return A string representing the URI for the metadata of the given token ID. */ function tokenURI( uint256 tokenId_ ) public view override returns (string memory) { // Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). _requireOwned(tokenId_); return string( abi.encodePacked(baseURI, "/", tokenId_.toString(), ".json") ); } /** * @dev Safely mints a new token. * Requirements: * - `tokenId` must not exist. * @param to_ address to which the token will be minted * @param tokenId_ token ID to mint * @param level_ level of the token to mint * @param price_ price of the token to mint * @param signature_ signature to validate */ function mint( address to_, uint256 tokenId_, uint256 level_, uint256 price_, bytes memory signature_ ) external payable nonReentrant { // Revert if contract is paused if (paused) { revert MintPausedError(); } // Perform the signature validation check if (!_isValidSignature(to_, tokenId_, level_, price_, signature_)) { revert InvalidSignatureError(); } // If to_ != address(0) and user is not the contract owner check that msg.sender == to_ if (to_ != address(0) && msg.sender != to_ && msg.sender != owner()) { revert InvalidRecipientError(); } // check that the level is valid, must be between 1 and 3 if (level_ < 1 || level_ > 3) { revert InvalidLevelError(); } // check that the mint limit has not been reached for that level if (levelInfos[level_].mintCount >= maxMintsPerLevel[level_ - 1]) { revert MintLimitReachedError(); } // check that the value sent is the same than the price_ parameter if (msg.value != price_) { revert InvalidPriceError(); } // Update the mint count for the level LevelInfo storage level = levelInfos[level_]; level.mintCount += 1; // Store the level of the minted token tokenLevels[tokenId_] = level_; // Set the correct address to mint the new token address mintTo = to_ == address(0) ? msg.sender : to_; emit MembershipMinted(mintTo, tokenId_); _safeMint(mintTo, tokenId_); } /** * @dev Returns the highest level of membership for the given wallet address. * @param wallet The address to check for membership level. * @return The highest membership level of the given wallet address. */ function getHighestMembershipLevel( address wallet ) external view returns (uint256) { uint256 highestLevel = 0; uint256 balance = balanceOf(wallet); for (uint256 i = 0; i < balance; i++) { uint256 tokenId = tokenOfOwnerByIndex(wallet, i); uint256 level = getLevel(tokenId); if (level > highestLevel) { highestLevel = level; } } return highestLevel; } function getLevel(uint256 tokenId_) public view returns (uint256) { // Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). _requireOwned(tokenId_); return tokenLevels[tokenId_]; } /** * @dev Updates the address authorized to mint new tokens. * @param authorizedSigner_ new authorized signer */ function updateAuthorizedSigner( address authorizedSigner_ ) external onlyOwner { if (authorizedSigner_ == address(0)) { revert NoAddressZeroError(); } emit AuthorizedSignerUpdated(authorizedSigner_); authorizedSigner = authorizedSigner_; } /** * @dev Updates the withdrawal address for funds. * @param withdrawalAddress_ new withdrawal address */ function updateWithdrawalAddress( address withdrawalAddress_ ) external onlyOwner { if (withdrawalAddress_ == address(0)) { revert NoAddressZeroError(); } emit WithdrawalAddressUpdated(withdrawalAddress_); withdrawalAddress = withdrawalAddress_; } /** * @dev Updates the base URI for NFT metadata. * @param baseURI_ new base URI */ function setBaseURI(string memory baseURI_) external onlyOwner { emit BaseURIUpdated(baseURI_); baseURI = baseURI_; } /** * @dev Pauses minting */ function pause() external onlyOwner { paused = true; emit Paused(); } /** * @dev Unpauses minting */ function unpause() external onlyOwner { paused = false; emit Unpaused(); } /** * @notice Validates the signature provided * @param to_ The address of the recipient. * @param tokenId_ The token ID to mint. * @param level_ The level of the token to mint. * @param price_ The price of the token to mint. * @param signature_ The signature to validate. * @return Returns true if the signature is valid, otherwise false. */ function _isValidSignature( address to_, uint256 tokenId_, uint256 level_, uint256 price_, bytes memory signature_ ) internal view returns (bool) { // prefixed message hash bytes32 messageHash = keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", keccak256( abi.encodePacked( address(this), // address of the current smart-contract to_, tokenId_, level_, price_ ) ) ) ); // use ECDSA.recover to recover signer address from signature address signer = ECDSA.recover(messageHash, signature_); return (signer == authorizedSigner); } /// @notice Transfer pending balance to the withdrawal address. function withdraw() external nonReentrant { // Only withdrawalAddress is allowed to withdraw funds if (msg.sender != withdrawalAddress) { revert NotAuthorizedError(); } uint256 balance = address(this).balance; if (balance == 0) revert NoFundsToWithdrawError(); Address.sendValue(payable(withdrawalAddress), balance); emit WithdrawCalled(msg.sender, balance); } // The following functions are overrides required by Solidity. function _update( address to, uint256 tokenId, address auth ) internal override(ERC721, ERC721Enumerable) returns (address) { return super._update(to, tokenId, auth); } function supportsInterface( bytes4 interfaceId ) public view override(ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } function _increaseBalance( address account, uint128 value ) internal override(ERC721, ERC721Enumerable) { super._increaseBalance(account, value); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"initialOwner_","type":"address"},{"internalType":"address","name":"authorizedSigner_","type":"address"},{"internalType":"address","name":"withdrawalAddress_","type":"address"},{"internalType":"string","name":"baseURI_","type":"string"},{"internalType":"uint256[]","name":"maxMintsPerLevel_","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidLevelError","type":"error"},{"inputs":[],"name":"InvalidPriceError","type":"error"},{"inputs":[],"name":"InvalidRecipientError","type":"error"},{"inputs":[],"name":"InvalidSignatureError","type":"error"},{"inputs":[],"name":"MintLimitReachedError","type":"error"},{"inputs":[],"name":"MintPausedError","type":"error"},{"inputs":[],"name":"NoAddressZeroError","type":"error"},{"inputs":[],"name":"NoFundsToWithdrawError","type":"error"},{"inputs":[],"name":"NotAuthorizedError","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"authorizedSigner","type":"address"}],"name":"AuthorizedSignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"MembershipMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawCalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"withdrawalAddress","type":"address"}],"name":"WithdrawalAddressUpdated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authorizedSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getHighestMembershipLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"levelInfos","outputs":[{"internalType":"uint256","name":"mintCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxMintsPerLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"level_","type":"uint256"},{"internalType":"uint256","name":"price_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"authorizedSigner_","type":"address"}],"name":"updateAuthorizedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"withdrawalAddress_","type":"address"}],"name":"updateWithdrawalAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b5060405161288338038061288383398101604081905261002e916102d1565b846040518060400160405280601281526020017104e46696e695469204d656d626572736869760741b815250604051806040016040528060048152602001634e46544d60e01b815250815f90816100859190610434565b5060016100928282610434565b50506001600655506001600160a01b0381166100c757604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100d08161012c565b50600d80546001600160a01b038087166001600160a01b031992831617909255600e805492861692909116919091179055600f61010d8382610434565b508051610121906011906020840190610199565b5050505050506104f3565b600c80546001600160a01b031916905561014581610148565b50565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b828054828255905f5260205f209081019282156101d2579160200282015b828111156101d25782518255916020019190600101906101b7565b506101de9291506101e2565b5090565b5b808211156101de575f81556001016101e3565b80516001600160a01b038116811461020c575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561024d5761024d610211565b604052919050565b5f82601f830112610264575f80fd5b815160206001600160401b0382111561027f5761027f610211565b8160051b61028e828201610225565b92835284810182019282810190878511156102a7575f80fd5b83870192505b848310156102c6578251825291830191908301906102ad565b979650505050505050565b5f805f805f60a086880312156102e5575f80fd5b6102ee866101f6565b945060206102fd8188016101f6565b945061030b604088016101f6565b60608801519094506001600160401b0380821115610327575f80fd5b818901915089601f83011261033a575f80fd5b81518181111561034c5761034c610211565b61035e601f8201601f19168501610225565b8181528b85838601011115610371575f80fd5b818585018683015e5f91810190940152608089015192945080831115610395575f80fd5b50506103a388828901610255565b9150509295509295909350565b600181811c908216806103c457607f821691505b6020821081036103e257634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561042f57805f5260205f20601f840160051c8101602085101561040d5750805b601f840160051c820191505b8181101561042c575f8155600101610419565b50505b505050565b81516001600160401b0381111561044d5761044d610211565b6104618161045b84546103b0565b846103e8565b602080601f831160018114610494575f841561047d5750858301515b5f19600386901b1c1916600185901b1785556104eb565b5f85815260208120601f198616915b828110156104c2578886015182559484019460019091019084016104a3565b50858210156104df57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b612383806105005f395ff3fe608060405260043610610207575f3560e01c80636c0360eb11610113578063b49c99b81161009d578063c87b56dd1161006d578063c87b56dd146105a7578063e30c3978146105c6578063e985e9c5146105e3578063f2bcd02214610602578063f2fde38b14610621575f80fd5b8063b49c99b814610537578063b88d4fde1461054a578063baef27b814610569578063c771909c14610588575f80fd5b80638456cb59116100e35780638456cb59146104b457806386481d40146104c85780638da5cb5b146104e757806395d89b4114610504578063a22cb46514610518575f80fd5b80636c0360eb1461045957806370a082311461046d578063715018a61461048c57806379ba5097146104a0575f80fd5b80633ccfd60b1161019457806355f804b31161016457806355f804b3146103c45780635c975abb146103e35780635e72fc5d146103fc5780636352211e1461041b578063669ed9351461043a575f80fd5b80633ccfd60b1461035e5780633f4ba83a1461037257806342842e0e146103865780634f6ccce7146103a5575f80fd5b806318160ddd116101da57806318160ddd146102b857806321117695146102d657806323b872dd146102f557806326c0aba2146103145780632f745c591461033f575f80fd5b806301ffc9a71461020b57806306fdde031461023f578063081812fc14610260578063095ea7b314610297575b5f80fd5b348015610216575f80fd5b5061022a610225366004611d7d565b610640565b60405190151581526020015b60405180910390f35b34801561024a575f80fd5b50610253610650565b6040516102369190611dcd565b34801561026b575f80fd5b5061027f61027a366004611ddf565b6106df565b6040516001600160a01b039091168152602001610236565b3480156102a2575f80fd5b506102b66102b1366004611e11565b610706565b005b3480156102c3575f80fd5b506009545b604051908152602001610236565b3480156102e1575f80fd5b506102c86102f0366004611e39565b610715565b348015610300575f80fd5b506102b661030f366004611e52565b610765565b34801561031f575f80fd5b506102c861032e366004611ddf565b60126020525f908152604090205481565b34801561034a575f80fd5b506102c8610359366004611e11565b6107f3565b348015610369575f80fd5b506102b6610856565b34801561037d575f80fd5b506102b6610903565b348015610391575f80fd5b506102b66103a0366004611e52565b61093f565b3480156103b0575f80fd5b506102c86103bf366004611ddf565b61095e565b3480156103cf575f80fd5b506102b66103de366004611f12565b6109b3565b3480156103ee575f80fd5b5060105461022a9060ff1681565b348015610407575f80fd5b506102b6610416366004611e39565b6109fe565b348015610426575f80fd5b5061027f610435366004611ddf565b610a8b565b348015610445575f80fd5b506102b6610454366004611e39565b610a95565b348015610464575f80fd5b50610253610b22565b348015610478575f80fd5b506102c8610487366004611e39565b610bae565b348015610497575f80fd5b506102b6610bf3565b3480156104ab575f80fd5b506102b6610c04565b3480156104bf575f80fd5b506102b6610c48565b3480156104d3575f80fd5b506102c86104e2366004611ddf565b610c87565b3480156104f2575f80fd5b50600b546001600160a01b031661027f565b34801561050f575f80fd5b50610253610ca4565b348015610523575f80fd5b506102b6610532366004611f57565b610cb3565b6102b6610545366004611fae565b610cbe565b348015610555575f80fd5b506102b6610564366004612014565b610ebd565b348015610574575f80fd5b506102c8610583366004611ddf565b610ed4565b348015610593575f80fd5b50600d5461027f906001600160a01b031681565b3480156105b2575f80fd5b506102536105c1366004611ddf565b610ef3565b3480156105d1575f80fd5b50600c546001600160a01b031661027f565b3480156105ee575f80fd5b5061022a6105fd366004612078565b610f31565b34801561060d575f80fd5b50600e5461027f906001600160a01b031681565b34801561062c575f80fd5b506102b661063b366004611e39565b610f5e565b5f61064a82610fcf565b92915050565b60605f805461065e906120a9565b80601f016020809104026020016040519081016040528092919081815260200182805461068a906120a9565b80156106d55780601f106106ac576101008083540402835291602001916106d5565b820191905f5260205f20905b8154815290600101906020018083116106b857829003601f168201915b5050505050905090565b5f6106e982610ff3565b505f828152600460205260409020546001600160a01b031661064a565b61071182823361102b565b5050565b5f808061072184610bae565b90505f5b8181101561075c575f61073886836107f3565b90505f61074482610c87565b905084811115610752578094505b5050600101610725565b50909392505050565b6001600160a01b03821661079357604051633250574960e11b81525f60048201526024015b60405180910390fd5b5f61079f838333611038565b9050836001600160a01b0316816001600160a01b0316146107ed576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161078a565b50505050565b5f6107fd83610bae565b821061082e5760405163295f44f760e21b81526001600160a01b03841660048201526024810183905260440161078a565b506001600160a01b03919091165f908152600760209081526040808320938352929052205490565b61085e61104c565b600e546001600160a01b03163314610889576040516379b798cf60e11b815260040160405180910390fd5b475f8190036108ab5760405163e168e91760e01b815260040160405180910390fd5b600e546108c1906001600160a01b031682611076565b60405181815233907f26d04682db6b10c93d5d39df697547e7f39badb6e2927e68323333e1afa795c29060200160405180910390a2506109016001600655565b565b61090b611109565b6010805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b61095983838360405180602001604052805f815250610ebd565b505050565b5f61096860095490565b82106109905760405163295f44f760e21b81525f60048201526024810183905260440161078a565b600982815481106109a3576109a36120e1565b905f5260205f2001549050919050565b6109bb611109565b7f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad816040516109ea9190611dcd565b60405180910390a1600f6107118282612139565b610a06611109565b6001600160a01b038116610a2d576040516301e8bbc160e31b815260040160405180910390fd5b6040516001600160a01b03821681527f227cb3c52b593782f40ecef3ba6f526592f2abe6ef6c34128c20b9dddf58ce639060200160405180910390a1600e80546001600160a01b0319166001600160a01b0392909216919091179055565b5f61064a82610ff3565b610a9d611109565b6001600160a01b038116610ac4576040516301e8bbc160e31b815260040160405180910390fd5b6040516001600160a01b03821681527f24bada2c0d54dfcadf1a6b7d7c4528c4219c6fffcce683ca9f39a8441947c63e9060200160405180910390a1600d80546001600160a01b0319166001600160a01b0392909216919091179055565b600f8054610b2f906120a9565b80601f0160208091040260200160405190810160405280929190818152602001828054610b5b906120a9565b8015610ba65780601f10610b7d57610100808354040283529160200191610ba6565b820191905f5260205f20905b815481529060010190602001808311610b8957829003601f168201915b505050505081565b5f6001600160a01b038216610bd8576040516322718ad960e21b81525f600482015260240161078a565b506001600160a01b03165f9081526003602052604090205490565b610bfb611109565b6109015f611136565b600c5433906001600160a01b03168114610c3c5760405163118cdaa760e01b81526001600160a01b038216600482015260240161078a565b610c4581611136565b50565b610c50611109565b6010805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b5f610c9182610ff3565b50505f9081526013602052604090205490565b60606001805461065e906120a9565b61071133838361114f565b610cc661104c565b60105460ff1615610cea5760405163c1cffd2f60e01b815260040160405180910390fd5b610cf785858585856111ed565b610d1457604051636cb40d4360e11b815260040160405180910390fd5b6001600160a01b03851615801590610d355750336001600160a01b03861614155b8015610d4c5750600b546001600160a01b03163314155b15610d6a57604051637192f5b760e11b815260040160405180910390fd5b6001831080610d795750600383115b15610d97576040516304b3136f60e11b815260040160405180910390fd5b6011610da460018561220d565b81548110610db457610db46120e1565b5f918252602080832090910154858352601290915260409091205410610ded5760405163d17b0b9f60e01b815260040160405180910390fd5b813414610e0d576040516380c00e2560e01b815260040160405180910390fd5b5f83815260126020526040812080549091600191839190610e2f908490612220565b90915550505f8581526013602052604081208590556001600160a01b03871615610e595786610e5b565b335b604080516001600160a01b0383168152602081018990529192507fbab4562ae868d1765ed8452e98bba908a974596c4babc3ada5e90e05e3f433fb910160405180910390a1610eaa81876112b9565b5050610eb66001600655565b5050505050565b610ec8848484610765565b6107ed848484846112d2565b60118181548110610ee3575f80fd5b5f91825260209091200154905081565b6060610efe82610ff3565b50600f610f0a836113f1565b604051602001610f1b929190612233565b6040516020818303038152906040529050919050565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b610f66611109565b600c80546001600160a01b0383166001600160a01b03199091168117909155610f97600b546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b0319821663780e9d6360e01b148061064a575061064a82611481565b5f818152600260205260408120546001600160a01b03168061064a57604051637e27328960e01b81526004810184905260240161078a565b61095983838360016114d0565b5f6110448484846115d4565b949350505050565b60026006540361106f57604051633ee5aeb560e01b815260040160405180910390fd5b6002600655565b804710156110995760405163cd78605960e01b815230600482015260240161078a565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146110e2576040519150601f19603f3d011682016040523d82523d5f602084013e6110e7565b606091505b505090508061095957604051630a12f52160e11b815260040160405180910390fd5b600b546001600160a01b031633146109015760405163118cdaa760e01b815233600482015260240161078a565b600c80546001600160a01b0319169055610c458161169f565b6001600160a01b03821661118157604051630b61174360e31b81526001600160a01b038316600482015260240161078a565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6040516bffffffffffffffffffffffff1930606090811b8216602084015287901b1660348201526048810185905260688101849052608881018390525f90819060a80160408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c016040516020818303038152906040528051906020012090505f61129c82856116f0565b600d546001600160a01b0390811691161498975050505050505050565b610711828260405180602001604052805f815250611718565b6001600160a01b0383163b156107ed57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906113149033908890879087906004016122ce565b6020604051808303815f875af192505050801561134e575060408051601f3d908101601f1916820190925261134b9181019061230a565b60015b6113b5573d80801561137b576040519150601f19603f3d011682016040523d82523d5f602084013e611380565b606091505b5080515f036113ad57604051633250574960e11b81526001600160a01b038516600482015260240161078a565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610eb657604051633250574960e11b81526001600160a01b038516600482015260240161078a565b60605f6113fd8361172e565b60010190505f8167ffffffffffffffff81111561141c5761141c611e8b565b6040519080825280601f01601f191660200182016040528015611446576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461145057509392505050565b5f6001600160e01b031982166380ac58cd60e01b14806114b157506001600160e01b03198216635b5e139f60e01b145b8061064a57506301ffc9a760e01b6001600160e01b031983161461064a565b80806114e457506001600160a01b03821615155b156115a5575f6114f384610ff3565b90506001600160a01b0383161580159061151f5750826001600160a01b0316816001600160a01b031614155b801561153257506115308184610f31565b155b1561155b5760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161078a565b81156115a35783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f806115e1858585611805565b90506001600160a01b03811661163d5761163884600980545f838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b611660565b846001600160a01b0316816001600160a01b0316146116605761166081856118f7565b6001600160a01b03851661167c5761167784611984565b611044565b846001600160a01b0316816001600160a01b031614611044576110448585611a2b565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f805f806116fe8686611a79565b92509250925061170e8282611ac2565b5090949350505050565b6117228383611b7a565b6109595f8484846112d2565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061176c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611798576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106117b657662386f26fc10000830492506010015b6305f5e10083106117ce576305f5e100830492506008015b61271083106117e257612710830492506004015b606483106117f4576064830492506002015b600a831061064a5760010192915050565b5f828152600260205260408120546001600160a01b039081169083161561183157611831818486611bdb565b6001600160a01b0381161561186b5761184c5f855f806114d0565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b03851615611899576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f61190183610bae565b5f83815260086020526040902054909150808214611952576001600160a01b0384165f9081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b505f9182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009545f906119959060019061220d565b5f838152600a6020526040812054600980549394509092849081106119bc576119bc6120e1565b905f5260205f200154905080600983815481106119db576119db6120e1565b5f918252602080832090910192909255828152600a90915260408082208490558582528120556009805480611a1257611a12612325565b600190038181905f5260205f20015f9055905550505050565b5f6001611a3784610bae565b611a41919061220d565b6001600160a01b039093165f908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b5f805f8351604103611ab0576020840151604085015160608601515f1a611aa288828585611c3f565b955095509550505050611abb565b505081515f91506002905b9250925092565b5f826003811115611ad557611ad5612339565b03611ade575050565b6001826003811115611af257611af2612339565b03611b105760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115611b2457611b24612339565b03611b455760405163fce698f760e01b81526004810182905260240161078a565b6003826003811115611b5957611b59612339565b03610711576040516335e2f38360e21b81526004810182905260240161078a565b6001600160a01b038216611ba357604051633250574960e11b81525f600482015260240161078a565b5f611baf83835f611038565b90506001600160a01b03811615610959576040516339e3563760e11b81525f600482015260240161078a565b611be6838383611d07565b610959576001600160a01b038316611c1457604051637e27328960e01b81526004810182905260240161078a565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161078a565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611c7857505f91506003905082611cfd565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611cc9573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116611cf457505f925060019150829050611cfd565b92505f91508190505b9450945094915050565b5f6001600160a01b038316158015906110445750826001600160a01b0316846001600160a01b03161480611d405750611d408484610f31565b806110445750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610c45575f80fd5b5f60208284031215611d8d575f80fd5b8135611d9881611d68565b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611d986020830184611d9f565b5f60208284031215611def575f80fd5b5035919050565b80356001600160a01b0381168114611e0c575f80fd5b919050565b5f8060408385031215611e22575f80fd5b611e2b83611df6565b946020939093013593505050565b5f60208284031215611e49575f80fd5b611d9882611df6565b5f805f60608486031215611e64575f80fd5b611e6d84611df6565b9250611e7b60208501611df6565b9150604084013590509250925092565b634e487b7160e01b5f52604160045260245ffd5b5f67ffffffffffffffff80841115611eb957611eb9611e8b565b604051601f8501601f19908116603f01168101908282118183101715611ee157611ee1611e8b565b81604052809350858152868686011115611ef9575f80fd5b858560208301375f602087830101525050509392505050565b5f60208284031215611f22575f80fd5b813567ffffffffffffffff811115611f38575f80fd5b8201601f81018413611f48575f80fd5b61104484823560208401611e9f565b5f8060408385031215611f68575f80fd5b611f7183611df6565b915060208301358015158114611f85575f80fd5b809150509250929050565b5f82601f830112611f9f575f80fd5b611d9883833560208501611e9f565b5f805f805f60a08688031215611fc2575f80fd5b611fcb86611df6565b9450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115611ffb575f80fd5b61200788828901611f90565b9150509295509295909350565b5f805f8060808587031215612027575f80fd5b61203085611df6565b935061203e60208601611df6565b925060408501359150606085013567ffffffffffffffff811115612060575f80fd5b61206c87828801611f90565b91505092959194509250565b5f8060408385031215612089575f80fd5b61209283611df6565b91506120a060208401611df6565b90509250929050565b600181811c908216806120bd57607f821691505b6020821081036120db57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b601f82111561095957805f5260205f20601f840160051c8101602085101561211a5750805b601f840160051c820191505b81811015610eb6575f8155600101612126565b815167ffffffffffffffff81111561215357612153611e8b565b6121678161216184546120a9565b846120f5565b602080601f83116001811461219a575f84156121835750858301515b5f19600386901b1c1916600185901b1785556121f1565b5f85815260208120601f198616915b828110156121c8578886015182559484019460019091019084016121a9565b50858210156121e557878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561064a5761064a6121f9565b8082018082111561064a5761064a6121f9565b5f808454612240816120a9565b60018281168015612258576001811461226d57612299565b60ff1984168752821515830287019450612299565b885f526020805f205f5b858110156122905781548a820152908401908201612277565b50505082870194505b50505050602f60f81b815283518060208601600184015e64173539b7b760d91b91016001810191825260060195945050505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061230090830184611d9f565b9695505050505050565b5f6020828403121561231a575f80fd5b8151611d9881611d68565b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220e932a2916064214be22aa725ba4d4b36c0f61d51acb0555a41ca0b3fda292cfd64736f6c63430008190033000000000000000000000000dd8d662e9b077d1fc9fa009c0ffab5d695d00db000000000000000000000000039f0cd0a98f3f700c9a0d5e828799fec4cec1b35000000000000000000000000651d7e02053e77de61247fd331cc102535c6885000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d567737546b474d475259457735454d56316a55335265385838724a4377394a725358516b4751676f7a424c6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000064
Deployed Bytecode
0x608060405260043610610207575f3560e01c80636c0360eb11610113578063b49c99b81161009d578063c87b56dd1161006d578063c87b56dd146105a7578063e30c3978146105c6578063e985e9c5146105e3578063f2bcd02214610602578063f2fde38b14610621575f80fd5b8063b49c99b814610537578063b88d4fde1461054a578063baef27b814610569578063c771909c14610588575f80fd5b80638456cb59116100e35780638456cb59146104b457806386481d40146104c85780638da5cb5b146104e757806395d89b4114610504578063a22cb46514610518575f80fd5b80636c0360eb1461045957806370a082311461046d578063715018a61461048c57806379ba5097146104a0575f80fd5b80633ccfd60b1161019457806355f804b31161016457806355f804b3146103c45780635c975abb146103e35780635e72fc5d146103fc5780636352211e1461041b578063669ed9351461043a575f80fd5b80633ccfd60b1461035e5780633f4ba83a1461037257806342842e0e146103865780634f6ccce7146103a5575f80fd5b806318160ddd116101da57806318160ddd146102b857806321117695146102d657806323b872dd146102f557806326c0aba2146103145780632f745c591461033f575f80fd5b806301ffc9a71461020b57806306fdde031461023f578063081812fc14610260578063095ea7b314610297575b5f80fd5b348015610216575f80fd5b5061022a610225366004611d7d565b610640565b60405190151581526020015b60405180910390f35b34801561024a575f80fd5b50610253610650565b6040516102369190611dcd565b34801561026b575f80fd5b5061027f61027a366004611ddf565b6106df565b6040516001600160a01b039091168152602001610236565b3480156102a2575f80fd5b506102b66102b1366004611e11565b610706565b005b3480156102c3575f80fd5b506009545b604051908152602001610236565b3480156102e1575f80fd5b506102c86102f0366004611e39565b610715565b348015610300575f80fd5b506102b661030f366004611e52565b610765565b34801561031f575f80fd5b506102c861032e366004611ddf565b60126020525f908152604090205481565b34801561034a575f80fd5b506102c8610359366004611e11565b6107f3565b348015610369575f80fd5b506102b6610856565b34801561037d575f80fd5b506102b6610903565b348015610391575f80fd5b506102b66103a0366004611e52565b61093f565b3480156103b0575f80fd5b506102c86103bf366004611ddf565b61095e565b3480156103cf575f80fd5b506102b66103de366004611f12565b6109b3565b3480156103ee575f80fd5b5060105461022a9060ff1681565b348015610407575f80fd5b506102b6610416366004611e39565b6109fe565b348015610426575f80fd5b5061027f610435366004611ddf565b610a8b565b348015610445575f80fd5b506102b6610454366004611e39565b610a95565b348015610464575f80fd5b50610253610b22565b348015610478575f80fd5b506102c8610487366004611e39565b610bae565b348015610497575f80fd5b506102b6610bf3565b3480156104ab575f80fd5b506102b6610c04565b3480156104bf575f80fd5b506102b6610c48565b3480156104d3575f80fd5b506102c86104e2366004611ddf565b610c87565b3480156104f2575f80fd5b50600b546001600160a01b031661027f565b34801561050f575f80fd5b50610253610ca4565b348015610523575f80fd5b506102b6610532366004611f57565b610cb3565b6102b6610545366004611fae565b610cbe565b348015610555575f80fd5b506102b6610564366004612014565b610ebd565b348015610574575f80fd5b506102c8610583366004611ddf565b610ed4565b348015610593575f80fd5b50600d5461027f906001600160a01b031681565b3480156105b2575f80fd5b506102536105c1366004611ddf565b610ef3565b3480156105d1575f80fd5b50600c546001600160a01b031661027f565b3480156105ee575f80fd5b5061022a6105fd366004612078565b610f31565b34801561060d575f80fd5b50600e5461027f906001600160a01b031681565b34801561062c575f80fd5b506102b661063b366004611e39565b610f5e565b5f61064a82610fcf565b92915050565b60605f805461065e906120a9565b80601f016020809104026020016040519081016040528092919081815260200182805461068a906120a9565b80156106d55780601f106106ac576101008083540402835291602001916106d5565b820191905f5260205f20905b8154815290600101906020018083116106b857829003601f168201915b5050505050905090565b5f6106e982610ff3565b505f828152600460205260409020546001600160a01b031661064a565b61071182823361102b565b5050565b5f808061072184610bae565b90505f5b8181101561075c575f61073886836107f3565b90505f61074482610c87565b905084811115610752578094505b5050600101610725565b50909392505050565b6001600160a01b03821661079357604051633250574960e11b81525f60048201526024015b60405180910390fd5b5f61079f838333611038565b9050836001600160a01b0316816001600160a01b0316146107ed576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161078a565b50505050565b5f6107fd83610bae565b821061082e5760405163295f44f760e21b81526001600160a01b03841660048201526024810183905260440161078a565b506001600160a01b03919091165f908152600760209081526040808320938352929052205490565b61085e61104c565b600e546001600160a01b03163314610889576040516379b798cf60e11b815260040160405180910390fd5b475f8190036108ab5760405163e168e91760e01b815260040160405180910390fd5b600e546108c1906001600160a01b031682611076565b60405181815233907f26d04682db6b10c93d5d39df697547e7f39badb6e2927e68323333e1afa795c29060200160405180910390a2506109016001600655565b565b61090b611109565b6010805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b61095983838360405180602001604052805f815250610ebd565b505050565b5f61096860095490565b82106109905760405163295f44f760e21b81525f60048201526024810183905260440161078a565b600982815481106109a3576109a36120e1565b905f5260205f2001549050919050565b6109bb611109565b7f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad816040516109ea9190611dcd565b60405180910390a1600f6107118282612139565b610a06611109565b6001600160a01b038116610a2d576040516301e8bbc160e31b815260040160405180910390fd5b6040516001600160a01b03821681527f227cb3c52b593782f40ecef3ba6f526592f2abe6ef6c34128c20b9dddf58ce639060200160405180910390a1600e80546001600160a01b0319166001600160a01b0392909216919091179055565b5f61064a82610ff3565b610a9d611109565b6001600160a01b038116610ac4576040516301e8bbc160e31b815260040160405180910390fd5b6040516001600160a01b03821681527f24bada2c0d54dfcadf1a6b7d7c4528c4219c6fffcce683ca9f39a8441947c63e9060200160405180910390a1600d80546001600160a01b0319166001600160a01b0392909216919091179055565b600f8054610b2f906120a9565b80601f0160208091040260200160405190810160405280929190818152602001828054610b5b906120a9565b8015610ba65780601f10610b7d57610100808354040283529160200191610ba6565b820191905f5260205f20905b815481529060010190602001808311610b8957829003601f168201915b505050505081565b5f6001600160a01b038216610bd8576040516322718ad960e21b81525f600482015260240161078a565b506001600160a01b03165f9081526003602052604090205490565b610bfb611109565b6109015f611136565b600c5433906001600160a01b03168114610c3c5760405163118cdaa760e01b81526001600160a01b038216600482015260240161078a565b610c4581611136565b50565b610c50611109565b6010805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b5f610c9182610ff3565b50505f9081526013602052604090205490565b60606001805461065e906120a9565b61071133838361114f565b610cc661104c565b60105460ff1615610cea5760405163c1cffd2f60e01b815260040160405180910390fd5b610cf785858585856111ed565b610d1457604051636cb40d4360e11b815260040160405180910390fd5b6001600160a01b03851615801590610d355750336001600160a01b03861614155b8015610d4c5750600b546001600160a01b03163314155b15610d6a57604051637192f5b760e11b815260040160405180910390fd5b6001831080610d795750600383115b15610d97576040516304b3136f60e11b815260040160405180910390fd5b6011610da460018561220d565b81548110610db457610db46120e1565b5f918252602080832090910154858352601290915260409091205410610ded5760405163d17b0b9f60e01b815260040160405180910390fd5b813414610e0d576040516380c00e2560e01b815260040160405180910390fd5b5f83815260126020526040812080549091600191839190610e2f908490612220565b90915550505f8581526013602052604081208590556001600160a01b03871615610e595786610e5b565b335b604080516001600160a01b0383168152602081018990529192507fbab4562ae868d1765ed8452e98bba908a974596c4babc3ada5e90e05e3f433fb910160405180910390a1610eaa81876112b9565b5050610eb66001600655565b5050505050565b610ec8848484610765565b6107ed848484846112d2565b60118181548110610ee3575f80fd5b5f91825260209091200154905081565b6060610efe82610ff3565b50600f610f0a836113f1565b604051602001610f1b929190612233565b6040516020818303038152906040529050919050565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b610f66611109565b600c80546001600160a01b0383166001600160a01b03199091168117909155610f97600b546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b0319821663780e9d6360e01b148061064a575061064a82611481565b5f818152600260205260408120546001600160a01b03168061064a57604051637e27328960e01b81526004810184905260240161078a565b61095983838360016114d0565b5f6110448484846115d4565b949350505050565b60026006540361106f57604051633ee5aeb560e01b815260040160405180910390fd5b6002600655565b804710156110995760405163cd78605960e01b815230600482015260240161078a565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146110e2576040519150601f19603f3d011682016040523d82523d5f602084013e6110e7565b606091505b505090508061095957604051630a12f52160e11b815260040160405180910390fd5b600b546001600160a01b031633146109015760405163118cdaa760e01b815233600482015260240161078a565b600c80546001600160a01b0319169055610c458161169f565b6001600160a01b03821661118157604051630b61174360e31b81526001600160a01b038316600482015260240161078a565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6040516bffffffffffffffffffffffff1930606090811b8216602084015287901b1660348201526048810185905260688101849052608881018390525f90819060a80160408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c016040516020818303038152906040528051906020012090505f61129c82856116f0565b600d546001600160a01b0390811691161498975050505050505050565b610711828260405180602001604052805f815250611718565b6001600160a01b0383163b156107ed57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906113149033908890879087906004016122ce565b6020604051808303815f875af192505050801561134e575060408051601f3d908101601f1916820190925261134b9181019061230a565b60015b6113b5573d80801561137b576040519150601f19603f3d011682016040523d82523d5f602084013e611380565b606091505b5080515f036113ad57604051633250574960e11b81526001600160a01b038516600482015260240161078a565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610eb657604051633250574960e11b81526001600160a01b038516600482015260240161078a565b60605f6113fd8361172e565b60010190505f8167ffffffffffffffff81111561141c5761141c611e8b565b6040519080825280601f01601f191660200182016040528015611446576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461145057509392505050565b5f6001600160e01b031982166380ac58cd60e01b14806114b157506001600160e01b03198216635b5e139f60e01b145b8061064a57506301ffc9a760e01b6001600160e01b031983161461064a565b80806114e457506001600160a01b03821615155b156115a5575f6114f384610ff3565b90506001600160a01b0383161580159061151f5750826001600160a01b0316816001600160a01b031614155b801561153257506115308184610f31565b155b1561155b5760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161078a565b81156115a35783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f806115e1858585611805565b90506001600160a01b03811661163d5761163884600980545f838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b611660565b846001600160a01b0316816001600160a01b0316146116605761166081856118f7565b6001600160a01b03851661167c5761167784611984565b611044565b846001600160a01b0316816001600160a01b031614611044576110448585611a2b565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f805f806116fe8686611a79565b92509250925061170e8282611ac2565b5090949350505050565b6117228383611b7a565b6109595f8484846112d2565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061176c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611798576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106117b657662386f26fc10000830492506010015b6305f5e10083106117ce576305f5e100830492506008015b61271083106117e257612710830492506004015b606483106117f4576064830492506002015b600a831061064a5760010192915050565b5f828152600260205260408120546001600160a01b039081169083161561183157611831818486611bdb565b6001600160a01b0381161561186b5761184c5f855f806114d0565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b03851615611899576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f61190183610bae565b5f83815260086020526040902054909150808214611952576001600160a01b0384165f9081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b505f9182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009545f906119959060019061220d565b5f838152600a6020526040812054600980549394509092849081106119bc576119bc6120e1565b905f5260205f200154905080600983815481106119db576119db6120e1565b5f918252602080832090910192909255828152600a90915260408082208490558582528120556009805480611a1257611a12612325565b600190038181905f5260205f20015f9055905550505050565b5f6001611a3784610bae565b611a41919061220d565b6001600160a01b039093165f908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b5f805f8351604103611ab0576020840151604085015160608601515f1a611aa288828585611c3f565b955095509550505050611abb565b505081515f91506002905b9250925092565b5f826003811115611ad557611ad5612339565b03611ade575050565b6001826003811115611af257611af2612339565b03611b105760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115611b2457611b24612339565b03611b455760405163fce698f760e01b81526004810182905260240161078a565b6003826003811115611b5957611b59612339565b03610711576040516335e2f38360e21b81526004810182905260240161078a565b6001600160a01b038216611ba357604051633250574960e11b81525f600482015260240161078a565b5f611baf83835f611038565b90506001600160a01b03811615610959576040516339e3563760e11b81525f600482015260240161078a565b611be6838383611d07565b610959576001600160a01b038316611c1457604051637e27328960e01b81526004810182905260240161078a565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161078a565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611c7857505f91506003905082611cfd565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611cc9573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116611cf457505f925060019150829050611cfd565b92505f91508190505b9450945094915050565b5f6001600160a01b038316158015906110445750826001600160a01b0316846001600160a01b03161480611d405750611d408484610f31565b806110445750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610c45575f80fd5b5f60208284031215611d8d575f80fd5b8135611d9881611d68565b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611d986020830184611d9f565b5f60208284031215611def575f80fd5b5035919050565b80356001600160a01b0381168114611e0c575f80fd5b919050565b5f8060408385031215611e22575f80fd5b611e2b83611df6565b946020939093013593505050565b5f60208284031215611e49575f80fd5b611d9882611df6565b5f805f60608486031215611e64575f80fd5b611e6d84611df6565b9250611e7b60208501611df6565b9150604084013590509250925092565b634e487b7160e01b5f52604160045260245ffd5b5f67ffffffffffffffff80841115611eb957611eb9611e8b565b604051601f8501601f19908116603f01168101908282118183101715611ee157611ee1611e8b565b81604052809350858152868686011115611ef9575f80fd5b858560208301375f602087830101525050509392505050565b5f60208284031215611f22575f80fd5b813567ffffffffffffffff811115611f38575f80fd5b8201601f81018413611f48575f80fd5b61104484823560208401611e9f565b5f8060408385031215611f68575f80fd5b611f7183611df6565b915060208301358015158114611f85575f80fd5b809150509250929050565b5f82601f830112611f9f575f80fd5b611d9883833560208501611e9f565b5f805f805f60a08688031215611fc2575f80fd5b611fcb86611df6565b9450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115611ffb575f80fd5b61200788828901611f90565b9150509295509295909350565b5f805f8060808587031215612027575f80fd5b61203085611df6565b935061203e60208601611df6565b925060408501359150606085013567ffffffffffffffff811115612060575f80fd5b61206c87828801611f90565b91505092959194509250565b5f8060408385031215612089575f80fd5b61209283611df6565b91506120a060208401611df6565b90509250929050565b600181811c908216806120bd57607f821691505b6020821081036120db57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b601f82111561095957805f5260205f20601f840160051c8101602085101561211a5750805b601f840160051c820191505b81811015610eb6575f8155600101612126565b815167ffffffffffffffff81111561215357612153611e8b565b6121678161216184546120a9565b846120f5565b602080601f83116001811461219a575f84156121835750858301515b5f19600386901b1c1916600185901b1785556121f1565b5f85815260208120601f198616915b828110156121c8578886015182559484019460019091019084016121a9565b50858210156121e557878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561064a5761064a6121f9565b8082018082111561064a5761064a6121f9565b5f808454612240816120a9565b60018281168015612258576001811461226d57612299565b60ff1984168752821515830287019450612299565b885f526020805f205f5b858110156122905781548a820152908401908201612277565b50505082870194505b50505050602f60f81b815283518060208601600184015e64173539b7b760d91b91016001810191825260060195945050505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061230090830184611d9f565b9695505050505050565b5f6020828403121561231a575f80fd5b8151611d9881611d68565b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220e932a2916064214be22aa725ba4d4b36c0f61d51acb0555a41ca0b3fda292cfd64736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000dd8d662e9b077d1fc9fa009c0ffab5d695d00db000000000000000000000000039f0cd0a98f3f700c9a0d5e828799fec4cec1b35000000000000000000000000651d7e02053e77de61247fd331cc102535c6885000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d567737546b474d475259457735454d56316a55335265385838724a4377394a725358516b4751676f7a424c6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000064
-----Decoded View---------------
Arg [0] : initialOwner_ (address): 0xdD8D662E9b077D1fC9fA009C0FFab5D695d00dB0
Arg [1] : authorizedSigner_ (address): 0x39F0cD0A98F3F700C9a0d5E828799FEc4CeC1b35
Arg [2] : withdrawalAddress_ (address): 0x651D7E02053e77DE61247fD331cc102535C68850
Arg [3] : baseURI_ (string): ipfs://QmVw7TkGMGRYEw5EMV1jU3Re8X8rJCw9JrSXQkGQgozBLk
Arg [4] : maxMintsPerLevel_ (uint256[]): 2500,500,100
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 000000000000000000000000dd8d662e9b077d1fc9fa009c0ffab5d695d00db0
Arg [1] : 00000000000000000000000039f0cd0a98f3f700c9a0d5e828799fec4cec1b35
Arg [2] : 000000000000000000000000651d7e02053e77de61247fd331cc102535c68850
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000035
Arg [6] : 697066733a2f2f516d567737546b474d475259457735454d56316a5533526538
Arg [7] : 5838724a4377394a725358516b4751676f7a424c6b0000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [9] : 00000000000000000000000000000000000000000000000000000000000009c4
Arg [10] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000064
Deployed Bytecode Sourcemap
86242:10707:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96567:187;;;;;;;;;;-1:-1:-1;96567:187:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;96567:187:0;;;;;;;;62662:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;63834:158::-;;;;;;;;;;-1:-1:-1;63834:158:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1460:32:1;;;1442:51;;1430:2;1415:18;63834:158:0;1296:203:1;63653:115:0;;;;;;;;;;-1:-1:-1;63653:115:0;;;;;:::i;:::-;;:::i;:::-;;80418:104;;;;;;;;;;-1:-1:-1;80497:10:0;:17;80418:104;;;2087:25:1;;;2075:2;2060:18;80418:104:0;1941:177:1;92228:488:0;;;;;;;;;;-1:-1:-1;92228:488:0;;;;;:::i;:::-;;:::i;64503:588::-;;;;;;;;;;-1:-1:-1;64503:588:0;;;;;:::i;:::-;;:::i;87890:53::-;;;;;;;;;;-1:-1:-1;87890:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;80082:260;;;;;;;;;;-1:-1:-1;80082:260:0;;;;;:::i;:::-;;:::i;95824:443::-;;;;;;;;;;;;;:::i;94350:97::-;;;;;;;;;;;;;:::i;65162:134::-;;;;;;;;;;-1:-1:-1;65162:134:0;;;;;:::i;:::-;;:::i;80599:231::-;;;;;;;;;;-1:-1:-1;80599:231:0;;;;;:::i;:::-;;:::i;94008:140::-;;;;;;;;;;-1:-1:-1;94008:140:0;;;;;:::i;:::-;;:::i;87598:18::-;;;;;;;;;;-1:-1:-1;87598:18:0;;;;;;;;93578:315;;;;;;;;;;-1:-1:-1;93578:315:0;;;;;:::i;:::-;;:::i;62475:120::-;;;;;;;;;;-1:-1:-1;62475:120:0;;;;;:::i;:::-;;:::i;93130:310::-;;;;;;;;;;-1:-1:-1;93130:310:0;;;;;:::i;:::-;;:::i;87500:21::-;;;;;;;;;;;;;:::i;62200:213::-;;;;;;;;;;-1:-1:-1;62200:213:0;;;;;:::i;:::-;;:::i;47835:103::-;;;;;;;;;;;;;:::i;50472:235::-;;;;;;;;;;;;;:::i;94202:92::-;;;;;;;;;;;;;:::i;92724:261::-;;;;;;;;;;-1:-1:-1;92724:261:0;;;;;:::i;:::-;;:::i;47160:87::-;;;;;;;;;;-1:-1:-1;47233:6:0;;-1:-1:-1;;;;;47233:6:0;47160:87;;62822:95;;;;;;;;;;;;;:::i;64064:146::-;;;;;;;;;;-1:-1:-1;64064:146:0;;;;;:::i;:::-;;:::i;90272:1706::-;;;;;;:::i;:::-;;:::i;65367:211::-;;;;;;;;;;-1:-1:-1;65367:211:0;;;;;:::i;:::-;;:::i;87803:33::-;;;;;;;;;;-1:-1:-1;87803:33:0;;;;;:::i;:::-;;:::i;87310:31::-;;;;;;;;;;-1:-1:-1;87310:31:0;;;;-1:-1:-1;;;;;87310:31:0;;;89515:386;;;;;;;;;;-1:-1:-1;89515:386:0;;;;;:::i;:::-;;:::i;49560:101::-;;;;;;;;;;-1:-1:-1;49640:13:0;;-1:-1:-1;;;;;49640:13:0;49560:101;;64281:155;;;;;;;;;;-1:-1:-1;64281:155:0;;;;;:::i;:::-;;:::i;87416:32::-;;;;;;;;;;-1:-1:-1;87416:32:0;;;;-1:-1:-1;;;;;87416:32:0;;;49860:181;;;;;;;;;;-1:-1:-1;49860:181:0;;;;;:::i;:::-;;:::i;96567:187::-;96686:4;96710:36;96734:11;96710:23;:36::i;:::-;96703:43;96567:187;-1:-1:-1;;96567:187:0:o;62662:91::-;62707:13;62740:5;62733:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62662:91;:::o;63834:158::-;63901:7;63921:22;63935:7;63921:13;:22::i;:::-;-1:-1:-1;66410:7:0;66437:24;;;:15;:24;;;;;;-1:-1:-1;;;;;66437:24:0;63963:21;66340:129;63653:115;63725:35;63734:2;63738:7;45249:10;63725:8;:35::i;:::-;63653:115;;:::o;92228:488::-;92318:7;;;92391:17;92401:6;92391:9;:17::i;:::-;92373:35;;92426:9;92421:256;92445:7;92441:1;:11;92421:256;;;92474:15;92492:30;92512:6;92520:1;92492:19;:30::i;:::-;92474:48;;92537:13;92553:17;92562:7;92553:8;:17::i;:::-;92537:33;;92597:12;92589:5;:20;92585:81;;;92645:5;92630:20;;92585:81;-1:-1:-1;;92454:3:0;;92421:256;;;-1:-1:-1;92696:12:0;;92228:488;-1:-1:-1;;;92228:488:0:o;64503:588::-;-1:-1:-1;;;;;64598:16:0;;64594:89;;64638:33;;-1:-1:-1;;;64638:33:0;;64668:1;64638:33;;;1442:51:1;1415:18;;64638:33:0;;;;;;;;64594:89;64904:21;64928:34;64936:2;64940:7;45249:10;64928:7;:34::i;:::-;64904:58;;64994:4;-1:-1:-1;;;;;64977:21:0;:13;-1:-1:-1;;;;;64977:21:0;;64973:111;;65022:50;;-1:-1:-1;;;65022:50:0;;-1:-1:-1;;;;;6505:15:1;;;65022:50:0;;;6487:34:1;6537:18;;;6530:34;;;6600:15;;6580:18;;;6573:43;6422:18;;65022:50:0;6247:375:1;64973:111:0;64583:508;64503:588;;;:::o;80082:260::-;80170:7;80203:16;80213:5;80203:9;:16::i;:::-;80194:5;:25;80190:101;;80243:36;;-1:-1:-1;;;80243:36:0;;-1:-1:-1;;;;;6819:32:1;;80243:36:0;;;6801:51:1;6868:18;;;6861:34;;;6774:18;;80243:36:0;6627:274:1;80190:101:0;-1:-1:-1;;;;;;80308:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;80082:260::o;95824:443::-;16799:21;:19;:21::i;:::-;95959:17:::1;::::0;-1:-1:-1;;;;;95959:17:0::1;95945:10;:31;95941:91;;96000:20;;-1:-1:-1::0;;;96000:20:0::1;;;;;;;;;;;95941:91;96060:21;96042:15;96096:12:::0;;;96092:49:::1;;96117:24;;-1:-1:-1::0;;;96117:24:0::1;;;;;;;;;;;96092:49;96180:17;::::0;96154:54:::1;::::0;-1:-1:-1;;;;;96180:17:0::1;96200:7:::0;96154:17:::1;:54::i;:::-;96224:35;::::0;2087:25:1;;;96239:10:0::1;::::0;96224:35:::1;::::0;2075:2:1;2060:18;96224:35:0::1;;;;;;;95866:401;16843:20:::0;16134:1;17385:7;:21;17202:212;16843:20;95824:443::o;94350:97::-;47046:13;:11;:13::i;:::-;94399:6:::1;:14:::0;;-1:-1:-1;;94399:14:0::1;::::0;;94429:10:::1;::::0;::::1;::::0;94408:5:::1;::::0;94429:10:::1;94350:97::o:0;65162:134::-;65249:39;65266:4;65272:2;65276:7;65249:39;;;;;;;;;;;;:16;:39::i;:::-;65162:134;;;:::o;80599:231::-;80665:7;80698:13;80497:10;:17;;80418:104;80698:13;80689:5;:22;80685:103;;80735:41;;-1:-1:-1;;;80735:41:0;;80766:1;80735:41;;;6801:51:1;6868:18;;;6861:34;;;6774:18;;80735:41:0;6627:274:1;80685:103:0;80805:10;80816:5;80805:17;;;;;;;;:::i;:::-;;;;;;;;;80798:24;;80599:231;;;:::o;94008:140::-;47046:13;:11;:13::i;:::-;94087:24:::1;94102:8;94087:24;;;;;;:::i;:::-;;;;;;;;94122:7;:18;94132:8:::0;94122:7;:18:::1;:::i;93578:315::-:0;47046:13;:11;:13::i;:::-;-1:-1:-1;;;;;93689:32:0;::::1;93685:92;;93745:20;;-1:-1:-1::0;;;93745:20:0::1;;;;;;;;;;;93685:92;93792:44;::::0;-1:-1:-1;;;;;1460:32:1;;1442:51;;93792:44:0::1;::::0;1430:2:1;1415:18;93792:44:0::1;;;;;;;93847:17;:38:::0;;-1:-1:-1;;;;;;93847:38:0::1;-1:-1:-1::0;;;;;93847:38:0;;;::::1;::::0;;;::::1;::::0;;93578:315::o;62475:120::-;62538:7;62565:22;62579:7;62565:13;:22::i;93130:310::-;47046:13;:11;:13::i;:::-;-1:-1:-1;;;;;93239:31:0;::::1;93235:91;;93294:20;;-1:-1:-1::0;;;93294:20:0::1;;;;;;;;;;;93235:91;93341:42;::::0;-1:-1:-1;;;;;1460:32:1;;1442:51;;93341:42:0::1;::::0;1430:2:1;1415:18;93341:42:0::1;;;;;;;93396:16;:36:::0;;-1:-1:-1;;;;;;93396:36:0::1;-1:-1:-1::0;;;;;93396:36:0;;;::::1;::::0;;;::::1;::::0;;93130:310::o;87500:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;62200:213::-;62263:7;-1:-1:-1;;;;;62287:19:0;;62283:89;;62330:30;;-1:-1:-1;;;62330:30:0;;62357:1;62330:30;;;1442:51:1;1415:18;;62330:30:0;1296:203:1;62283:89:0;-1:-1:-1;;;;;;62389:16:0;;;;;:9;:16;;;;;;;62200:213::o;47835:103::-;47046:13;:11;:13::i;:::-;47900:30:::1;47927:1;47900:18;:30::i;50472:235::-:0;49640:13;;45249:10;;-1:-1:-1;;;;;49640:13:0;50569:24;;50565:98;;50617:34;;-1:-1:-1;;;50617:34:0;;-1:-1:-1;;;;;1460:32:1;;50617:34:0;;;1442:51:1;1415:18;;50617:34:0;1296:203:1;50565:98:0;50673:26;50692:6;50673:18;:26::i;:::-;50514:193;50472:235::o;94202:92::-;47046:13;:11;:13::i;:::-;94249:6:::1;:13:::0;;-1:-1:-1;;94249:13:0::1;94258:4;94249:13;::::0;;94278:8:::1;::::0;::::1;::::0;94249:6:::1;::::0;94278:8:::1;94202:92::o:0;92724:261::-;92781:7;92915:23;92929:8;92915:13;:23::i;:::-;-1:-1:-1;;92956:21:0;;;;:11;:21;;;;;;;92724:261::o;62822:95::-;62869:13;62902:7;62895:14;;;;;:::i;64064:146::-;64150:52;45249:10;64183:8;64193;64150:18;:52::i;90272:1706::-;16799:21;:19;:21::i;:::-;90512:6:::1;::::0;::::1;;90508:63;;;90542:17;;-1:-1:-1::0;;;90542:17:0::1;;;;;;;;;;;90508:63;90639:60;90657:3;90662:8;90672:6;90680;90688:10;90639:17;:60::i;:::-;90634:124;;90723:23;;-1:-1:-1::0;;;90723:23:0::1;;;;;;;;;;;90634:124;-1:-1:-1::0;;;;;90869:17:0;::::1;::::0;;::::1;::::0;:38:::1;;-1:-1:-1::0;90890:10:0::1;-1:-1:-1::0;;;;;90890:17:0;::::1;;;90869:38;:63;;;;-1:-1:-1::0;47233:6:0;;-1:-1:-1;;;;;47233:6:0;90911:10:::1;:21;;90869:63;90865:126;;;90956:23;;-1:-1:-1::0;;;90956:23:0::1;;;;;;;;;;;90865:126;91083:1;91074:6;:10;:24;;;;91097:1;91088:6;:10;91074:24;91070:83;;;91122:19;;-1:-1:-1::0;;;91122:19:0::1;;;;;;;;;;;91070:83;91275:16;91292:10;91301:1;91292:6:::0;:10:::1;:::i;:::-;91275:28;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;::::1;::::0;91243:18;;;:10:::1;:18:::0;;;;;;;:28;:60:::1;91239:123;;91327:23;;-1:-1:-1::0;;;91327:23:0::1;;;;;;;;;;;91239:123;91467:6;91454:9;:19;91450:78;;91497:19;;-1:-1:-1::0;;;91497:19:0::1;;;;;;;;;;;91450:78;91588:23;91614:18:::0;;;:10:::1;:18;::::0;;;;91643:20;;91614:18;;91662:1:::1;::::0;91614:18;;91588:23;91643:20:::1;::::0;91662:1;;91643:20:::1;:::i;:::-;::::0;;;-1:-1:-1;;91724:21:0::1;::::0;;;:11:::1;:21;::::0;;;;:30;;;-1:-1:-1;;;;;91842:17:0;::::1;::::0;:36:::1;;91875:3;91842:36;;;91862:10;91842:36;91896:34;::::0;;-1:-1:-1;;;;;6819:32:1;;6801:51;;6883:2;6868:18;;6861:34;;;91825:53:0;;-1:-1:-1;91896:34:0::1;::::0;6774:18:1;91896:34:0::1;;;;;;;91943:27;91953:6;91961:8;91943:9;:27::i;:::-;90456:1522;;16843:20:::0;16134:1;17385:7;:21;17202:212;16843:20;90272:1706;;;;;:::o;65367:211::-;65481:31;65494:4;65500:2;65504:7;65481:12;:31::i;:::-;65523:47;65546:4;65552:2;65556:7;65565:4;65523:22;:47::i;87803:33::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87803:33:0;:::o;89515:386::-;89597:13;89737:23;89751:8;89737:13;:23::i;:::-;;89835:7;89849:19;:8;:17;:19::i;:::-;89818:60;;;;;;;;;:::i;:::-;;;;;;;;;;;;;89773:120;;89515:386;;;:::o;64281:155::-;-1:-1:-1;;;;;64393:25:0;;;64369:4;64393:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;64281:155::o;49860:181::-;47046:13;:11;:13::i;:::-;49950::::1;:24:::0;;-1:-1:-1;;;;;49950:24:0;::::1;-1:-1:-1::0;;;;;;49950:24:0;;::::1;::::0;::::1;::::0;;;50015:7:::1;47233:6:::0;;-1:-1:-1;;;;;47233:6:0;;47160:87;50015:7:::1;-1:-1:-1::0;;;;;49990:43:0::1;;;;;;;;;;;49860:181:::0;:::o;79774:224::-;79876:4;-1:-1:-1;;;;;;79900:50:0;;-1:-1:-1;;;79900:50:0;;:90;;;79954:36;79978:11;79954:23;:36::i;76809:247::-;76872:7;66195:16;;;:7;:16;;;;;;-1:-1:-1;;;;;66195:16:0;;76936:90;;76983:31;;-1:-1:-1;;;76983:31:0;;;;;2087:25:1;;;2060:18;;76983:31:0;1941:177:1;75041:122:0;75122:33;75131:2;75135:7;75144:4;75150;75122:8;:33::i;96345:214::-;96492:7;96519:32;96533:2;96537:7;96546:4;96519:13;:32::i;:::-;96512:39;96345:214;-1:-1:-1;;;;96345:214:0:o;16879:315::-;16177:1;17008:7;;:18;17004:88;;17050:30;;-1:-1:-1;;;17050:30:0;;;;;;;;;;;17004:88;16177:1;17169:7;:17;16879:315::o;9505:340::-;9615:6;9591:21;:30;9587:111;;;9645:41;;-1:-1:-1;;;9645:41:0;;9680:4;9645:41;;;1442:51:1;1415:18;;9645:41:0;1296:203:1;9587:111:0;9711:12;9729:9;-1:-1:-1;;;;;9729:14:0;9751:6;9729:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9710:52;;;9778:7;9773:65;;9809:17;;-1:-1:-1;;;9809:17:0;;;;;;;;;;;47325:166;47233:6;;-1:-1:-1;;;;;47233:6:0;45249:10;47385:23;47381:103;;47432:40;;-1:-1:-1;;;47432:40:0;;45249:10;47432:40;;;1442:51:1;1415:18;;47432:40:0;1296:203:1;50231:156:0;50321:13;50314:20;;-1:-1:-1;;;;;;50314:20:0;;;50345:34;50370:8;50345:24;:34::i;76248:318::-;-1:-1:-1;;;;;76356:22:0;;76352:93;;76402:31;;-1:-1:-1;;;76402:31:0;;-1:-1:-1;;;;;1460:32:1;;76402:31:0;;;1442:51:1;1415:18;;76402:31:0;1296:203:1;76352:93:0;-1:-1:-1;;;;;76455:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;76455:46:0;;;;;;;;;;76517:41;;540::1;;;76517::0;;513:18:1;76517:41:0;;;;;;;76248:318;;;:::o;94851:896::-;95258:251;;-1:-1:-1;;95309:4:0;11551:2:1;11547:15;;;11543:24;;95258:251:0;;;11531:37:1;11602:15;;;11598:24;11584:12;;;11577:46;11639:12;;;11632:28;;;11676:12;;;11669:28;;;11713:13;;;11706:29;;;95041:4:0;;;;11751:13:1;;95258:251:0;;;-1:-1:-1;;95258:251:0;;;;;;;;;;95226:302;;95258:251;95226:302;;;;12017:66:1;95138:405:0;;;12005:79:1;;;;12100:12;;;12093:28;12137:12;;95138:405:0;;;;;;;;;;;;95114:440;;;;;;95092:462;;95636:14;95653:38;95667:11;95680:10;95653:13;:38::i;:::-;95722:16;;-1:-1:-1;;;;;95722:16:0;;;95712:26;;;;94851:896;-1:-1:-1;;;;;;;;94851:896:0:o;71160:102::-;71228:26;71238:2;71242:7;71228:26;;;;;;;;;;;;:9;:26::i;77606:799::-;-1:-1:-1;;;;;77723:14:0;;;:18;77719:679;;77762:71;;-1:-1:-1;;;77762:71:0;;-1:-1:-1;;;;;77762:36:0;;;;;:71;;45249:10;;77813:4;;77819:7;;77828:4;;77762:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;77762:71:0;;;;;;;;-1:-1:-1;;77762:71:0;;;;;;;;;;;;:::i;:::-;;;77758:629;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78076:6;:13;78093:1;78076:18;78072:300;;78126:25;;-1:-1:-1;;;78126:25:0;;-1:-1:-1;;;;;1460:32:1;;78126:25:0;;;1442:51:1;1415:18;;78126:25:0;1296:203:1;78072:300:0;78322:6;78316:13;78307:6;78303:2;78299:15;78292:38;77758:629;-1:-1:-1;;;;;;77881:51:0;;-1:-1:-1;;;77881:51:0;77877:132;;77964:25;;-1:-1:-1;;;77964:25:0;;-1:-1:-1;;;;;1460:32:1;;77964:25:0;;;1442:51:1;1415:18;;77964:25:0;1296:203:1;41939:718:0;41995:13;42046:14;42063:17;42074:5;42063:10;:17::i;:::-;42083:1;42063:21;42046:38;;42099:20;42133:6;42122:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42122:18:0;-1:-1:-1;42099:41:0;-1:-1:-1;42264:28:0;;;42280:2;42264:28;42321:290;-1:-1:-1;;42353:5:0;-1:-1:-1;;;42490:2:0;42479:14;;42474:32;42353:5;42461:46;42553:2;42544:11;;;-1:-1:-1;42574:21:0;42321:290;42574:21;-1:-1:-1;42632:6:0;41939:718;-1:-1:-1;;;41939:718:0:o;61831:305::-;61933:4;-1:-1:-1;;;;;;61970:40:0;;-1:-1:-1;;;61970:40:0;;:105;;-1:-1:-1;;;;;;;62027:48:0;;-1:-1:-1;;;62027:48:0;61970:105;:158;;;-1:-1:-1;;;;;;;;;;53591:40:0;;;62092:36;53491:148;75351:678;75513:9;:31;;;-1:-1:-1;;;;;;75526:18:0;;;;75513:31;75509:471;;;75561:13;75577:22;75591:7;75577:13;:22::i;:::-;75561:38;-1:-1:-1;;;;;;75730:18:0;;;;;;:35;;;75761:4;-1:-1:-1;;;;;75752:13:0;:5;-1:-1:-1;;;;;75752:13:0;;;75730:35;:69;;;;;75770:29;75787:5;75794:4;75770:16;:29::i;:::-;75769:30;75730:69;75726:144;;;75827:27;;-1:-1:-1;;;75827:27:0;;-1:-1:-1;;;;;1460:32:1;;75827:27:0;;;1442:51:1;1415:18;;75827:27:0;1296:203:1;75726:144:0;75890:9;75886:83;;;75945:7;75941:2;-1:-1:-1;;;;;75925:28:0;75934:5;-1:-1:-1;;;;;75925:28:0;;;;;;;;;;;75886:83;75546:434;75509:471;-1:-1:-1;;75992:24:0;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;75992:29:0;-1:-1:-1;;;;;75992:29:0;;;;;;;;;;75351:678::o;80891:640::-;80986:7;81006:21;81030:32;81044:2;81048:7;81057:4;81030:13;:32::i;:::-;81006:56;-1:-1:-1;;;;;;81079:27:0;;81075:214;;81123:40;81155:7;82355:10;:17;;82328:24;;;;:15;:24;;;;;:44;;;82383:24;;;;;;;;;;;;82251:164;81123:40;81075:214;;;81202:2;-1:-1:-1;;;;;81185:19:0;:13;-1:-1:-1;;;;;81185:19:0;;81181:108;;81221:56;81254:13;81269:7;81221:32;:56::i;:::-;-1:-1:-1;;;;;81303:16:0;;81299:192;;81336:45;81373:7;81336:36;:45::i;:::-;81299:192;;;81420:2;-1:-1:-1;;;;;81403:19:0;:13;-1:-1:-1;;;;;81403:19:0;;81399:92;;81439:40;81467:2;81471:7;81439:27;:40::i;48473:191::-;48566:6;;;-1:-1:-1;;;;;48583:17:0;;;-1:-1:-1;;;;;;48583:17:0;;;;;;;48616:40;;48566:6;;;48583:17;48566:6;;48616:40;;48547:16;;48616:40;48536:128;48473:191;:::o;3794:259::-;3872:7;3893:17;3912:18;3932:16;3952:27;3963:4;3969:9;3952:10;:27::i;:::-;3892:87;;;;;;3990:28;4002:5;4009:8;3990:11;:28::i;:::-;-1:-1:-1;4036:9:0;;3794:259;-1:-1:-1;;;;3794:259:0:o;71489:185::-;71584:18;71590:2;71594:7;71584:5;:18::i;:::-;71613:53;71644:1;71648:2;71652:7;71661:4;71613:22;:53::i;38343:948::-;38396:7;;-1:-1:-1;;;38474:17:0;;38470:106;;-1:-1:-1;;;38512:17:0;;;-1:-1:-1;38558:2:0;38548:12;38470:106;38603:8;38594:5;:17;38590:106;;38641:8;38632:17;;;-1:-1:-1;38678:2:0;38668:12;38590:106;38723:8;38714:5;:17;38710:106;;38761:8;38752:17;;;-1:-1:-1;38798:2:0;38788:12;38710:106;38843:7;38834:5;:16;38830:103;;38880:7;38871:16;;;-1:-1:-1;38916:1:0;38906:11;38830:103;38960:7;38951:5;:16;38947:103;;38997:7;38988:16;;;-1:-1:-1;39033:1:0;39023:11;38947:103;39077:7;39068:5;:16;39064:103;;39114:7;39105:16;;;-1:-1:-1;39150:1:0;39140:11;39064:103;39194:7;39185:5;:16;39181:68;;39232:1;39222:11;39277:6;38343:948;-1:-1:-1;;38343:948:0:o;69302:824::-;69388:7;66195:16;;;:7;:16;;;;;;-1:-1:-1;;;;;66195:16:0;;;;69503:18;;;69499:88;;69538:37;69555:4;69561;69567:7;69538:16;:37::i;:::-;-1:-1:-1;;;;;69634:18:0;;;69630:263;;69752:48;69769:1;69773:7;69790:1;69794:5;69752:8;:48::i;:::-;-1:-1:-1;;;;;69846:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;69846:20:0;;;69630:263;-1:-1:-1;;;;;69909:16:0;;;69905:111;;-1:-1:-1;;;;;69971:13:0;;;;;;:9;:13;;;;;:18;;69988:1;69971:18;;;69905:111;70028:16;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;70028:21:0;-1:-1:-1;;;;;70028:21:0;;;;;;;;;70067:27;;70028:16;;70067:27;;;;;;;70114:4;69302:824;-1:-1:-1;;;;69302:824:0:o;83042:977::-;83308:22;83333:15;83343:4;83333:9;:15::i;:::-;83359:18;83380:26;;;:17;:26;;;;;;83308:40;;-1:-1:-1;83513:28:0;;;83509:328;;-1:-1:-1;;;;;83580:18:0;;83558:19;83580:18;;;:12;:18;;;;;;;;:34;;;;;;;;;83631:30;;;;;;:44;;;83748:30;;:17;:30;;;;;:43;;;83509:328;-1:-1:-1;83933:26:0;;;;:17;:26;;;;;;;;83926:33;;;-1:-1:-1;;;;;83977:18:0;;;;;:12;:18;;;;;:34;;;;;;;83970:41;83042:977::o;84314:1079::-;84592:10;:17;84567:22;;84592:21;;84612:1;;84592:21;:::i;:::-;84624:18;84645:24;;;:15;:24;;;;;;85018:10;:26;;84567:46;;-1:-1:-1;84645:24:0;;84567:46;;85018:26;;;;;;:::i;:::-;;;;;;;;;84996:48;;85082:11;85057:10;85068;85057:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;85162:28;;;:15;:28;;;;;;;:41;;;85334:24;;;;;85327:31;85369:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;84385:1008;;;84314:1079;:::o;81832:218::-;81917:14;81950:1;81934:13;81944:2;81934:9;:13::i;:::-;:17;;;;:::i;:::-;-1:-1:-1;;;;;81962:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;82007:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;81832:218:0:o;2188:783::-;2269:7;2278:12;2292:7;2316:9;:16;2336:2;2316:22;2312:652;;2660:4;2645:20;;2639:27;2710:4;2695:20;;2689:27;2768:4;2753:20;;2747:27;2355:9;2739:36;2811:25;2822:4;2739:36;2639:27;2689;2811:10;:25::i;:::-;2804:32;;;;;;;;;;;2312:652;-1:-1:-1;;2934:16:0;;2885:1;;-1:-1:-1;2889:35:0;;2312:652;2188:783;;;;;:::o;7362:542::-;7458:20;7449:5;:29;;;;;;;;:::i;:::-;;7445:452;;7362:542;;:::o;7445:452::-;7556:29;7547:5;:38;;;;;;;;:::i;:::-;;7543:354;;7609:23;;-1:-1:-1;;;7609:23:0;;;;;;;;;;;7543:354;7663:35;7654:5;:44;;;;;;;;:::i;:::-;;7650:247;;7722:46;;-1:-1:-1;;;7722:46:0;;;;;2087:25:1;;;2060:18;;7722:46:0;1941:177:1;7650:247:0;7799:30;7790:5;:39;;;;;;;;:::i;:::-;;7786:111;;7853:32;;-1:-1:-1;;;7853:32:0;;;;;2087:25:1;;;2060:18;;7853:32:0;1941:177:1;70462:335:0;-1:-1:-1;;;;;70530:16:0;;70526:89;;70570:33;;-1:-1:-1;;;70570:33:0;;70600:1;70570:33;;;1442:51:1;1415:18;;70570:33:0;1296:203:1;70526:89:0;70625:21;70649:32;70657:2;70661:7;70678:1;70649:7;:32::i;:::-;70625:56;-1:-1:-1;;;;;;70696:27:0;;;70692:98;;70747:31;;-1:-1:-1;;;70747:31:0;;70775:1;70747:31;;;1442:51:1;1415:18;;70747:31:0;1296:203:1;67509:376:0;67622:38;67636:5;67643:7;67652;67622:13;:38::i;:::-;67617:261;;-1:-1:-1;;;;;67681:19:0;;67677:190;;67728:31;;-1:-1:-1;;;67728:31:0;;;;;2087:25:1;;;2060:18;;67728:31:0;1941:177:1;67677:190:0;67807:44;;-1:-1:-1;;;67807:44:0;;-1:-1:-1;;;;;6819:32:1;;67807:44:0;;;6801:51:1;6868:18;;;6861:34;;;6774:18;;67807:44:0;6627:274:1;5265:1556:0;5396:7;;;6339:66;6326:79;;6322:166;;;-1:-1:-1;6438:1:0;;-1:-1:-1;6442:30:0;;-1:-1:-1;6474:1:0;6422:54;;6322:166;6602:24;;;6585:14;6602:24;;;;;;;;;13713:25:1;;;13786:4;13774:17;;13754:18;;;13747:45;;;;13808:18;;;13801:34;;;13851:18;;;13844:34;;;6602:24:0;;13685:19:1;;6602:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6602:24:0;;-1:-1:-1;;6602:24:0;;;-1:-1:-1;;;;;;;6641:20:0;;6637:115;;-1:-1:-1;6694:1:0;;-1:-1:-1;6698:29:0;;-1:-1:-1;6694:1:0;;-1:-1:-1;6678:62:0;;6637:115;6772:6;-1:-1:-1;6780:20:0;;-1:-1:-1;6780:20:0;;-1:-1:-1;5265:1556:0;;;;;;;;;:::o;66789:276::-;66892:4;-1:-1:-1;;;;;66929:21:0;;;;;;:128;;;66977:7;-1:-1:-1;;;;;66968:16:0;:5;-1:-1:-1;;;;;66968:16:0;;:52;;;;66988:32;67005:5;67012:7;66988:16;:32::i;:::-;66968:88;;;-1:-1:-1;;66410:7:0;66437:24;;;:15;:24;;;;;;-1:-1:-1;;;;;66437:24:0;;;67024:32;;;;;-1:-1:-1;66789:276:0:o;14:131:1:-;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;:::-;384:5;150:245;-1:-1:-1;;;150:245:1:o;592:289::-;634:3;672:5;666:12;699:6;694:3;687:19;755:6;748:4;741:5;737:16;730:4;725:3;721:14;715:47;807:1;800:4;791:6;786:3;782:16;778:27;771:38;870:4;863:2;859:7;854:2;846:6;842:15;838:29;833:3;829:39;825:50;818:57;;;592:289;;;;:::o;886:220::-;1035:2;1024:9;1017:21;998:4;1055:45;1096:2;1085:9;1081:18;1073:6;1055:45;:::i;1111:180::-;1170:6;1223:2;1211:9;1202:7;1198:23;1194:32;1191:52;;;1239:1;1236;1229:12;1191:52;-1:-1:-1;1262:23:1;;1111:180;-1:-1:-1;1111:180:1:o;1504:173::-;1572:20;;-1:-1:-1;;;;;1621:31:1;;1611:42;;1601:70;;1667:1;1664;1657:12;1601:70;1504:173;;;:::o;1682:254::-;1750:6;1758;1811:2;1799:9;1790:7;1786:23;1782:32;1779:52;;;1827:1;1824;1817:12;1779:52;1850:29;1869:9;1850:29;:::i;:::-;1840:39;1926:2;1911:18;;;;1898:32;;-1:-1:-1;;;1682:254:1:o;2123:186::-;2182:6;2235:2;2223:9;2214:7;2210:23;2206:32;2203:52;;;2251:1;2248;2241:12;2203:52;2274:29;2293:9;2274:29;:::i;2314:328::-;2391:6;2399;2407;2460:2;2448:9;2439:7;2435:23;2431:32;2428:52;;;2476:1;2473;2466:12;2428:52;2499:29;2518:9;2499:29;:::i;:::-;2489:39;;2547:38;2581:2;2570:9;2566:18;2547:38;:::i;:::-;2537:48;;2632:2;2621:9;2617:18;2604:32;2594:42;;2314:328;;;;;:::o;2647:127::-;2708:10;2703:3;2699:20;2696:1;2689:31;2739:4;2736:1;2729:15;2763:4;2760:1;2753:15;2779:632;2844:5;2874:18;2915:2;2907:6;2904:14;2901:40;;;2921:18;;:::i;:::-;2996:2;2990:9;2964:2;3050:15;;-1:-1:-1;;3046:24:1;;;3072:2;3042:33;3038:42;3026:55;;;3096:18;;;3116:22;;;3093:46;3090:72;;;3142:18;;:::i;:::-;3182:10;3178:2;3171:22;3211:6;3202:15;;3241:6;3233;3226:22;3281:3;3272:6;3267:3;3263:16;3260:25;3257:45;;;3298:1;3295;3288:12;3257:45;3348:6;3343:3;3336:4;3328:6;3324:17;3311:44;3403:1;3396:4;3387:6;3379;3375:19;3371:30;3364:41;;;;2779:632;;;;;:::o;3416:451::-;3485:6;3538:2;3526:9;3517:7;3513:23;3509:32;3506:52;;;3554:1;3551;3544:12;3506:52;3594:9;3581:23;3627:18;3619:6;3616:30;3613:50;;;3659:1;3656;3649:12;3613:50;3682:22;;3735:4;3727:13;;3723:27;-1:-1:-1;3713:55:1;;3764:1;3761;3754:12;3713:55;3787:74;3853:7;3848:2;3835:16;3830:2;3826;3822:11;3787:74;:::i;3872:347::-;3937:6;3945;3998:2;3986:9;3977:7;3973:23;3969:32;3966:52;;;4014:1;4011;4004:12;3966:52;4037:29;4056:9;4037:29;:::i;:::-;4027:39;;4116:2;4105:9;4101:18;4088:32;4163:5;4156:13;4149:21;4142:5;4139:32;4129:60;;4185:1;4182;4175:12;4129:60;4208:5;4198:15;;;3872:347;;;;;:::o;4224:221::-;4266:5;4319:3;4312:4;4304:6;4300:17;4296:27;4286:55;;4337:1;4334;4327:12;4286:55;4359:80;4435:3;4426:6;4413:20;4406:4;4398:6;4394:17;4359:80;:::i;4450:600::-;4554:6;4562;4570;4578;4586;4639:3;4627:9;4618:7;4614:23;4610:33;4607:53;;;4656:1;4653;4646:12;4607:53;4679:29;4698:9;4679:29;:::i;:::-;4669:39;;4755:2;4744:9;4740:18;4727:32;4717:42;;4806:2;4795:9;4791:18;4778:32;4768:42;;4857:2;4846:9;4842:18;4829:32;4819:42;;4912:3;4901:9;4897:19;4884:33;4940:18;4932:6;4929:30;4926:50;;;4972:1;4969;4962:12;4926:50;4995:49;5036:7;5027:6;5016:9;5012:22;4995:49;:::i;:::-;4985:59;;;4450:600;;;;;;;;:::o;5055:537::-;5150:6;5158;5166;5174;5227:3;5215:9;5206:7;5202:23;5198:33;5195:53;;;5244:1;5241;5234:12;5195:53;5267:29;5286:9;5267:29;:::i;:::-;5257:39;;5315:38;5349:2;5338:9;5334:18;5315:38;:::i;:::-;5305:48;;5400:2;5389:9;5385:18;5372:32;5362:42;;5455:2;5444:9;5440:18;5427:32;5482:18;5474:6;5471:30;5468:50;;;5514:1;5511;5504:12;5468:50;5537:49;5578:7;5569:6;5558:9;5554:22;5537:49;:::i;:::-;5527:59;;;5055:537;;;;;;;:::o;5597:260::-;5665:6;5673;5726:2;5714:9;5705:7;5701:23;5697:32;5694:52;;;5742:1;5739;5732:12;5694:52;5765:29;5784:9;5765:29;:::i;:::-;5755:39;;5813:38;5847:2;5836:9;5832:18;5813:38;:::i;:::-;5803:48;;5597:260;;;;;:::o;5862:380::-;5941:1;5937:12;;;;5984;;;6005:61;;6059:4;6051:6;6047:17;6037:27;;6005:61;6112:2;6104:6;6101:14;6081:18;6078:38;6075:161;;6158:10;6153:3;6149:20;6146:1;6139:31;6193:4;6190:1;6183:15;6221:4;6218:1;6211:15;6075:161;;5862:380;;;:::o;6906:127::-;6967:10;6962:3;6958:20;6955:1;6948:31;6998:4;6995:1;6988:15;7022:4;7019:1;7012:15;7164:518;7266:2;7261:3;7258:11;7255:421;;;7302:5;7299:1;7292:16;7346:4;7343:1;7333:18;7416:2;7404:10;7400:19;7397:1;7393:27;7387:4;7383:38;7452:4;7440:10;7437:20;7434:47;;;-1:-1:-1;7475:4:1;7434:47;7530:2;7525:3;7521:12;7518:1;7514:20;7508:4;7504:31;7494:41;;7585:81;7603:2;7596:5;7593:13;7585:81;;;7662:1;7648:16;;7629:1;7618:13;7585:81;;7858:1345;7984:3;7978:10;8011:18;8003:6;8000:30;7997:56;;;8033:18;;:::i;:::-;8062:97;8152:6;8112:38;8144:4;8138:11;8112:38;:::i;:::-;8106:4;8062:97;:::i;:::-;8214:4;;8271:2;8260:14;;8288:1;8283:663;;;;8990:1;9007:6;9004:89;;;-1:-1:-1;9059:19:1;;;9053:26;9004:89;-1:-1:-1;;7815:1:1;7811:11;;;7807:24;7803:29;7793:40;7839:1;7835:11;;;7790:57;9106:81;;8253:944;;8283:663;7111:1;7104:14;;;7148:4;7135:18;;-1:-1:-1;;8319:20:1;;;8437:236;8451:7;8448:1;8445:14;8437:236;;;8540:19;;;8534:26;8519:42;;8632:27;;;;8600:1;8588:14;;;;8467:19;;8437:236;;;8441:3;8701:6;8692:7;8689:19;8686:201;;;8762:19;;;8756:26;-1:-1:-1;;8845:1:1;8841:14;;;8857:3;8837:24;8833:37;8829:42;8814:58;8799:74;;8686:201;;;8933:1;8924:6;8921:1;8917:14;8913:22;8907:4;8900:36;8253:944;;;;;7858:1345;;:::o;9208:127::-;9269:10;9264:3;9260:20;9257:1;9250:31;9300:4;9297:1;9290:15;9324:4;9321:1;9314:15;9340:128;9407:9;;;9428:11;;;9425:37;;;9442:18;;:::i;9473:125::-;9538:9;;;9559:10;;;9556:36;;;9572:18;;:::i;9721:1304::-;10099:3;10128:1;10161:6;10155:13;10191:36;10217:9;10191:36;:::i;:::-;10246:1;10263:17;;;10289:133;;;;10436:1;10431:358;;;;10256:533;;10289:133;-1:-1:-1;;10322:24:1;;10310:37;;10395:14;;10388:22;10376:35;;10367:45;;;-1:-1:-1;10289:133:1;;10431:358;10462:6;10459:1;10452:17;10492:4;10537;10534:1;10524:18;10564:1;10578:165;10592:6;10589:1;10586:13;10578:165;;;10670:14;;10657:11;;;10650:35;10713:16;;;;10607:10;;10578:165;;;10582:3;;;10772:6;10767:3;10763:16;10756:23;;10256:533;;;;;-1:-1:-1;;;10805:3:1;10798:16;10845:6;10839:13;10899:8;10892:4;10884:6;10880:17;10876:1;10871:3;10867:11;10861:47;-1:-1:-1;;;10931:18:1;;10951:1;10927:26;;9663:20;;;9699:11;;10984:35;9721:1304;-1:-1:-1;;;;;9721:1304:1:o;12160:489::-;-1:-1:-1;;;;;12429:15:1;;;12411:34;;12481:15;;12476:2;12461:18;;12454:43;12528:2;12513:18;;12506:34;;;12576:3;12571:2;12556:18;;12549:31;;;12354:4;;12597:46;;12623:19;;12615:6;12597:46;:::i;:::-;12589:54;12160:489;-1:-1:-1;;;;;;12160:489:1:o;12654:249::-;12723:6;12776:2;12764:9;12755:7;12751:23;12747:32;12744:52;;;12792:1;12789;12782:12;12744:52;12824:9;12818:16;12843:30;12867:5;12843:30;:::i;13040:127::-;13101:10;13096:3;13092:20;13089:1;13082:31;13132:4;13129:1;13122:15;13156:4;13153:1;13146:15;13172:127;13233:10;13228:3;13224:20;13221:1;13214:31;13264:4;13261:1;13254:15;13288:4;13285:1;13278:15
Swarm Source
ipfs://e932a2916064214be22aa725ba4d4b36c0f61d51acb0555a41ca0b3fda292cfd
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.