ERC-721
Overview
Max Total Supply
10,000 BartCoin
Holders
5,010
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Balance
1 BartCoinLoading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
ApetimismLaunchpadNFT
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 160 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at zkevm.polygonscan.com on 2023-10-23 */ // Sources flattened with hardhat v2.9.9 https://hardhat.org // File @openzeppelin/contracts/utils/[email protected] // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File @openzeppelin/contracts/access/[email protected] // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File @openzeppelin/contracts/security/[email protected] // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File @openzeppelin/contracts/utils/math/[email protected] // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } } // File @openzeppelin/contracts/utils/[email protected] // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } } // File @openzeppelin/contracts/token/ERC20/[email protected] // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File erc721a/contracts/[email protected] // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @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`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @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 payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @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); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); } // File erc721a/contracts/extensions/[email protected] // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721AQueryable. */ interface IERC721AQueryable is IERC721A { /** * Invalid query range (`start` >= `stop`). */ error InvalidQueryRange(); /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory); /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory); /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view returns (uint256[] memory); /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner(address owner) external view returns (uint256[] memory); } // File erc721a/contracts/[email protected] // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => TokenApprovalRef) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than `_currentIndex - _startTokenId()` times. unchecked { return _currentIndex - _burnCounter - _startTokenId(); } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { return _currentIndex - _startTokenId(); } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return _burnCounter; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) revert BalanceQueryForZeroAddress(); return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); _packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @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, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { uint256 packed = _packedOwnerships[curr]; // If not burned. if (packed & _BITMASK_BURNED == 0) { // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `curr` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. while (packed == 0) { packed = _packedOwnerships[--curr]; } return packed; } } } revert OwnerQueryForNonexistentToken(); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @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) public payable virtual override { address owner = ownerOf(tokenId); if (_msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { revert ApprovalCallerNotOwnerNorApproved(); } _tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken(); return _tokenApprovals[tokenId].value; } /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) public virtual override { _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _startTokenId() <= tokenId && tokenId < _currentIndex && // If within bounds, _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned. } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * 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 ) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner(); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved(); if (to == address(0)) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, to, tokenId); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns ( bytes4 retval ) { return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert TransferToNonERC721ReceiverImplementer(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); uint256 toMasked; uint256 end = startTokenId + quantity; // Use assembly to loop and emit the `Transfer` event for gas savings. // The duplicated `log4` removes an extra check and reduces stack juggling. // The assembly, together with the surrounding Solidity code, have been // delicately arranged to nudge the compiler into producing optimized opcodes. assembly { // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. toMasked := and(to, _BITMASK_ADDRESS) // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. startTokenId // `tokenId`. ) // The `iszero(eq(,))` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. // The compiler will optimize the `iszero` away for performance. for { let tokenId := add(startTokenId, 1) } iszero(eq(tokenId, end)) { tokenId := add(tokenId, 1) } { // Emit the `Transfer` event. Similar to above. log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId) } } if (toMasked == 0) revert MintToZeroAddress(); _currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); _currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (index < end); // Reentrancy protection. if (_currentIndex != end) revert(); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { _burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = _packedOwnerships[index]; if (packed == 0) revert OwnershipNotInitializedForExtraData(); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); _packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } } // File erc721a/contracts/extensions/[email protected] // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @title ERC721AQueryable. * * @dev ERC721A subclass with convenience query functions. */ abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable { /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory) { TokenOwnership memory ownership; if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) { return ownership; } ownership = _ownershipAt(tokenId); if (ownership.burned) { return ownership; } return _ownershipOf(tokenId); } /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] calldata tokenIds) external view virtual override returns (TokenOwnership[] memory) { unchecked { uint256 tokenIdsLength = tokenIds.length; TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength); for (uint256 i; i != tokenIdsLength; ++i) { ownerships[i] = explicitOwnershipOf(tokenIds[i]); } return ownerships; } } /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view virtual override returns (uint256[] memory) { unchecked { if (start >= stop) revert InvalidQueryRange(); uint256 tokenIdsIdx; uint256 stopLimit = _nextTokenId(); // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) { start = _startTokenId(); } // Set `stop = min(stop, stopLimit)`. if (stop > stopLimit) { stop = stopLimit; } uint256 tokenIdsMaxLength = balanceOf(owner); // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`, // to cater for cases where `balanceOf(owner)` is too big. if (start < stop) { uint256 rangeLength = stop - start; if (rangeLength < tokenIdsMaxLength) { tokenIdsMaxLength = rangeLength; } } else { tokenIdsMaxLength = 0; } uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength); if (tokenIdsMaxLength == 0) { return tokenIds; } // We need to call `explicitOwnershipOf(start)`, // because the slot at `start` may not be initialized. TokenOwnership memory ownership = explicitOwnershipOf(start); address currOwnershipAddr; // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`. // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range. if (!ownership.burned) { currOwnershipAddr = ownership.addr; } for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) { ownership = _ownershipAt(i); if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } // Downsize the array to fit. assembly { mstore(tokenIds, tokenIdsIdx) } return tokenIds; } } /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) { unchecked { uint256 tokenIdsIdx; address currOwnershipAddr; uint256 tokenIdsLength = balanceOf(owner); uint256[] memory tokenIds = new uint256[](tokenIdsLength); TokenOwnership memory ownership; for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) { ownership = _ownershipAt(i); if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } return tokenIds; } } } // File contracts/ApetimismLaunchpadNFT.sol pragma solidity ^0.8.9; contract ApetimismLaunchpadNFT is ERC721AQueryable, Ownable, ReentrancyGuard { event RoundChanged(uint256 indexed); event TotalMintedChanged(uint256 indexed); /////////// // Errors /////////// error InvalidSignature(); error DuplicatedNonce(); error HitMaximum(); error InvalidAmount(); error RunOut(); error NotEligible(); error NotStarted(); error RoleNotExisted(); error MetadataFrozen(); error NonExistentToken(); error UnmatchedEther(); error EtherNotSent(); ////////////// // Constants ////////////// uint256 public constant MAX_SUPPLY = 10000; uint256 private constant START_TOKEN_ID = 1; string private constant TOKEN_NAME = "Bart"; string private constant TOKEN_SYMBOL = "BartCoin"; ////////////// // Internal ////////////// mapping(address => uint256) private _addressTokenMinted; mapping(address => mapping(uint256 => mapping(int256 => uint256))) private _addressTokenMintedInRoundByRole; mapping(address => mapping(int256 => uint256)) private _addressTokenMintedInRole; mapping(uint256 => uint256) private _nonces; mapping(uint256 => mapping(uint256 => mapping(int256 => Role))) private allowedRolesInRound; mapping(uint256 => mapping(uint256 => uint256)) private allowedRolesInRoundCount; mapping(uint256 => mapping(uint256 => int256[])) private allowedRolesInRoundArr; uint256[] private availableAllowedRounds; uint256[] private availableRounds; mapping(uint256 => mapping(uint256 => uint256)) private roundAllocations; mapping(uint256 => mapping(int256 => uint256)) private roleAllocations; int256[] private availableRoles; mapping(uint256 => uint256) private totalMintedInRound; uint256 private allowedRolesInRoundSetId; uint256 private roundAllocationsSetId; uint256 private roleAllocationsSetId; bool private metadataFrozen; uint256 private maxMintPerTx = 10000; uint256 private maxMintPerAddress = 10000; string private baseURIExtended; bool private metadataHasExtension = true; ///////////////////// // Public Variables ///////////////////// address public signerAddress = 0x0407FfD4EAD1B1AD36fa5f262eD7f13b50e1Fc89; uint256 public currentRound; struct Role { uint256 round_id; int256 role_id; uint256 max_mint; uint256 mint_price; bool exists; } address public currencyAddress; //////////////// // Parameters //////////////// struct RoleInRoundParams { uint256 round; int256 role; uint256 maxMint; uint256 mintPrice; } struct RoundAllocationParams { uint256 round; uint256 allocation; } struct RoleAllocationParams { int256 role; uint256 allocation; } //////////////// // Actual Code //////////////// constructor() ERC721A(TOKEN_NAME, TOKEN_SYMBOL) { } function _startTokenId() internal view virtual override returns (uint256) { return START_TOKEN_ID; } ////////////////////// // Setters for Owner ////////////////////// function setCurrentRound(uint256 round_) public onlyOwner { currentRound = round_; emit RoundChanged(round_); } function setMaxMintPerTx(uint256 count) external onlyOwner { maxMintPerTx = count; } function setMaxMintPerAddress(uint256 count) external onlyOwner { maxMintPerAddress = count; } function setBaseURI(string memory baseURI) external onlyOwner { if (metadataFrozen) revert MetadataFrozen(); baseURIExtended = baseURI; } function setMetadataHasExtension(bool hasExtension) external onlyOwner { metadataHasExtension = hasExtension; } function setCurrencyAddress(address addr) external onlyOwner { currencyAddress = addr; } function addAllowedRolesInRound(RoleInRoundParams[] memory params, bool replace) public onlyOwner { if (replace) { allowedRolesInRoundSetId++; delete availableAllowedRounds; } mapping(uint256 => mapping(int256 => Role)) storage _currentAllowedRolesInRound = allowedRolesInRound[allowedRolesInRoundSetId]; mapping(uint256 => uint256) storage _currentAllowedRolesInRoundCount = allowedRolesInRoundCount[allowedRolesInRoundSetId]; mapping(uint256 => int256[]) storage _currentAllowedRolesInRoundArr = allowedRolesInRoundArr[allowedRolesInRoundSetId]; unchecked { for (uint i; i < params.length; ++i) { RoleInRoundParams memory param = params[i]; uint256 round = param.round; Role storage allowedRole = _currentAllowedRolesInRound[round][param.role]; allowedRole.round_id = round; allowedRole.role_id = param.role; allowedRole.max_mint = param.maxMint; allowedRole.mint_price = param.mintPrice; if (allowedRole.exists) // Role already existed continue; allowedRole.exists = true; _currentAllowedRolesInRoundCount[round]++; _currentAllowedRolesInRoundArr[round].push(param.role); if (!_existedInUint256Array(availableAllowedRounds, round)) availableAllowedRounds.push(round); } } } function removeAllowedRoleInRound(uint256 round, int256 role) public onlyOwner { Role storage allowedRole = allowedRolesInRound[allowedRolesInRoundSetId][round][role]; mapping(uint256 => uint256) storage _allowedRolesInRoundCount = allowedRolesInRoundCount[allowedRolesInRoundSetId]; if (!allowedRole.exists) revert RoleNotExisted(); allowedRole.round_id = 0; allowedRole.role_id = 0; allowedRole.max_mint = 0; allowedRole.mint_price = 0; allowedRole.exists = false; _allowedRolesInRoundCount[round]--; // Remove available role int256[] storage _allowedRolesInRound = allowedRolesInRoundArr[allowedRolesInRoundSetId][round]; uint256 len = _allowedRolesInRound.length; for (uint i = 0; i < len; i++) { if (_allowedRolesInRound[i] == role) { removeArrayAtInt256Index(_allowedRolesInRound, i); break; } } if (_allowedRolesInRoundCount[round] == 0) { // Remove available round len = availableRounds.length; for (uint i = 0; i < len; i++) { if (availableRounds[i] == round) { removeArrayAtUint256Index(availableRounds, i); break; } } } } function addRoundsAllocation(RoundAllocationParams[] memory params, bool replace) public onlyOwner { if (replace) { roundAllocationsSetId++; delete availableRounds; } mapping(uint256 => uint256) storage _currentRoundAllocations = roundAllocations[roundAllocationsSetId]; unchecked { for (uint i = 0; i < params.length; i++) { RoundAllocationParams memory param = params[i]; uint256 round = param.round; _currentRoundAllocations[round] = param.allocation; if (!_existedInUint256Array(availableRounds, round)) availableRounds.push(round); } } } function addRolesAllocation(RoleAllocationParams[] memory params, bool replace) public onlyOwner { if (replace) { roleAllocationsSetId++; delete availableRoles; } mapping(int256 => uint256) storage _currentRoleAllocations = roleAllocations[roleAllocationsSetId]; unchecked { for (uint i = 0; i < params.length; i++) { RoleAllocationParams memory param = params[i]; _currentRoleAllocations[param.role] = param.allocation; bool existed = false; uint256 len = availableRoles.length; for (uint j = 0; j < len; j++) if (availableRoles[j] == param.role) existed = true; if (!existed) availableRoles.push(param.role); } } } function addRolesRounds( RoleInRoundParams[] memory _rolesInRound, bool _replaceRoleInRound, RoundAllocationParams[] memory _roundAllocations, bool _replaceRoundAllocations, RoleAllocationParams[] memory _roleAllocations, bool _replaceRoleAllocations ) external onlyOwner { addAllowedRolesInRound(_rolesInRound, _replaceRoleInRound); addRoundsAllocation(_roundAllocations, _replaceRoundAllocations); addRolesAllocation(_roleAllocations, _replaceRoleAllocations); } function freezeMetadata() external onlyOwner { metadataFrozen = true; } //////////// // Minting //////////// function mint(uint256 quantity, int256 role, uint256 apetimismFee, address apetimismAddress, uint256 nonce, uint8 v, bytes32 r, bytes32 s) external payable nonReentrant { if (currentRound == 0) revert NotStarted(); uint256 combined_nonce = nonce; if (role >= 0) combined_nonce = (nonce << 16) + uint256(role); _validateNonceAndSignature(combined_nonce, abi.encodePacked(combined_nonce, apetimismFee, apetimismAddress), v, r, s); mapping(int256 => Role) storage allowedRolesInCurrentRound = allowedRolesInRound[allowedRolesInRoundSetId][currentRound]; int256 selected_role = 0; if (role >= 0) selected_role = role; if (!allowedRolesInCurrentRound[selected_role].exists) { if (!allowedRolesInCurrentRound[0].exists) // Revert if Public Role is NOT allowed in this round revert NotEligible(); selected_role = 0; } _validateQuantity(quantity); // Check for Role Quota { int256 _roleToCheck = 0; if (role >= 0) _roleToCheck = role; if (maxMintableForTxForRole(msg.sender, _roleToCheck) < quantity) revert HitMaximum(); } uint256 cost = quantity * allowedRolesInCurrentRound[selected_role].mint_price; _nonces[combined_nonce] = 1; // Check the Ether value { uint256 _expectedValue = cost; // Pay by Token if (currencyAddress != address(0)) _expectedValue = 0; if (msg.value != _expectedValue) revert UnmatchedEther(); } _safeMint(msg.sender, quantity); totalMintedInRound[currentRound] += quantity; _addressTokenMinted[msg.sender] += quantity; _addressTokenMintedInRoundByRole[msg.sender][currentRound][selected_role] += quantity; _addressTokenMintedInRole[msg.sender][selected_role] += quantity; uint256 to_apetimism = cost * apetimismFee / 10000; if (currencyAddress != address(0)) { // Pay by Token IERC20 tokenContract = IERC20(currencyAddress); tokenContract.transferFrom(msg.sender, address(this), cost); tokenContract.transfer(apetimismAddress, to_apetimism); } else { // Pay by Native Coin _transferEth(payable(apetimismAddress), to_apetimism); } } function adminMintTo(address to, uint256 quantity) external onlyOwner { _validateQuantity(quantity); _safeMint(to, quantity); } ////////////// // Apetimism ////////////// function setCurrentRoundFromSignature(uint256 nonce, uint256 round, uint8 v, bytes32 r, bytes32 s) public { _validateNonceAndSignature(nonce, abi.encodePacked(nonce, round), v, r, s); _nonces[nonce] = 1; setCurrentRound(round); } function setSignerAddressFromSignature(uint256 nonce, address addr, uint8 v, bytes32 r, bytes32 s) public { _validateNonceAndSignature(nonce, abi.encodePacked(nonce, addr), v, r, s); _nonces[nonce] = 1; signerAddress = addr; } /////////////// // Validators /////////////// function _validateQuantity(uint256 quantity) private view { if (quantity <= 0) revert InvalidAmount(); if (mintableLeft() < quantity) revert RunOut(); } function _validateNonceAndSignature(uint256 nonce, bytes memory data, uint8 v, bytes32 r, bytes32 s) private view { if (_nonces[nonce] != 0) revert DuplicatedNonce(); if (_recoverAddress(data, v, r, s) != signerAddress) revert InvalidSignature(); } //////////////// // Transfering //////////////// function transfersFrom( address from, address to, uint256[] memory tokenIds ) public virtual { for (uint i = 0; i < tokenIds.length; i++) transferFrom(from, to, tokenIds[i]); } function safeTransfersFrom( address from, address to, uint256[] memory tokenIds, bytes memory _data ) public virtual { for (uint i = 0; i < tokenIds.length; i++) safeTransferFrom(from, to, tokenIds[i], _data); } ///////////////// // Public Views ///////////////// function getConfigs() public view returns (bool, uint256, uint256, string memory, bool) { return (metadataFrozen, maxMintPerTx, maxMintPerAddress, baseURIExtended, metadataHasExtension); } function getAllowedRolesInRoundArr(uint256 round) public view returns (int256[] memory) { int256[] storage _allowedRolesInRound = allowedRolesInRoundArr[allowedRolesInRoundSetId][round]; uint256 len = _allowedRolesInRound.length; int256[] memory ret = new int256[](len); for (uint i = 0; i < len; i++) ret[i] = _allowedRolesInRound[i]; return ret; } function getAllAllowedRolesInRounds() public view returns (RoleInRoundParams[] memory) { mapping(uint256 => uint256) storage _currentAllowedRolesInRoundCount = allowedRolesInRoundCount[allowedRolesInRoundSetId]; uint256 len = 0; for (uint i = 0; i < availableAllowedRounds.length; i++) len += _currentAllowedRolesInRoundCount[ availableAllowedRounds[i] ]; RoleInRoundParams[] memory ret = new RoleInRoundParams[](len); uint256 index = 0; for (uint i = 0; i < availableAllowedRounds.length; i++) { uint256 round = availableAllowedRounds[i]; uint256 count = _currentAllowedRolesInRoundCount[round]; for (uint j = 0; j < count; j++) { int256 role = allowedRolesInRoundArr[allowedRolesInRoundSetId][round][j]; Role storage allowedRole = allowedRolesInRound[allowedRolesInRoundSetId][round][role]; RoleInRoundParams memory retAtCurrentIndex = ret[index]; retAtCurrentIndex.round = round; retAtCurrentIndex.role = role; retAtCurrentIndex.maxMint = allowedRole.max_mint; retAtCurrentIndex.mintPrice = allowedRole.mint_price; index++; } } return ret; } function getAllRoundAllocations() public view returns (RoundAllocationParams[] memory) { uint256 len = availableRounds.length; RoundAllocationParams[] memory ret = new RoundAllocationParams[](len); mapping(uint256 => uint256) storage _currentRoundAllocations = roundAllocations[roundAllocationsSetId]; for (uint i = 0; i < len; i++) { RoundAllocationParams memory retAtCurrentIndex = ret[i]; retAtCurrentIndex.round = availableRounds[i]; retAtCurrentIndex.allocation = _currentRoundAllocations[retAtCurrentIndex.round]; } return ret; } function getAllRoleAllocations() public view returns (RoleAllocationParams[] memory) { uint256 len = availableRoles.length; RoleAllocationParams[] memory ret = new RoleAllocationParams[](len); mapping(int256 => uint256) storage _currentRoleAllocations = roleAllocations[roleAllocationsSetId]; for (uint i = 0; i < len; i++) { RoleAllocationParams memory retAtCurrentIndex = ret[i]; retAtCurrentIndex.role = availableRoles[i]; retAtCurrentIndex.allocation = _currentRoleAllocations[retAtCurrentIndex.role]; } return ret; } function mintPriceForCurrentRoundForRole(int256 role) public view returns (uint256) { return allowedRolesInRound[allowedRolesInRoundSetId][currentRound][role].mint_price; } function maxMintableForRole(address addr, int256 role) public view virtual returns (uint256) { uint256 minted = _addressTokenMinted[addr]; uint256 max_mint = 0; uint256 _currentRoundAllocation = roundAllocations[roundAllocationsSetId][currentRound]; uint256 _currentRoleAllocation = roleAllocations[roleAllocationsSetId][role]; uint256 _addressMintedInRoundByRole = _addressTokenMintedInRoundByRole[addr][currentRound][role]; uint256 _addressMintedInRole = _addressTokenMintedInRole[addr][role]; uint256 _currentTotalMintedInRound = totalMintedInRound[currentRound]; if ( // Not yet started currentRound == 0 // Total minted in this round reach the maximum allocated || _currentTotalMintedInRound >= _currentRoundAllocation // Cannot mint more than allocated for role || _addressMintedInRole >= _currentRoleAllocation // Hit the maximum per wallet || minted >= maxMintPerAddress // Prevent underflow || _currentTotalMintedInRound >= _currentRoundAllocation ) return 0; Role storage _allowedRoleInRound = allowedRolesInRound[allowedRolesInRoundSetId][currentRound][role]; if (_allowedRoleInRound.exists) max_mint = _allowedRoleInRound.max_mint; // Cannot mint more for this round if (_addressMintedInRoundByRole >= max_mint) return 0; uint256 wallet_quota_left = maxMintPerAddress - minted; uint256 round_quota_left = max_mint - _addressMintedInRoundByRole; uint256 round_allocation_quota_left = _currentRoundAllocation - _currentTotalMintedInRound; uint256 role_quota_left = _currentRoleAllocation - _addressMintedInRole; return Math.min( Math.min( Math.min( Math.min( wallet_quota_left, round_quota_left ), round_allocation_quota_left ), role_quota_left ), mintableLeft()); } function maxMintableForTxForRole(address addr, int256 role) public view virtual returns (uint256) { return Math.min(maxMintableForRole(addr, role), maxMintPerTx); } function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) revert NonExistentToken(); if (bytes(baseURIExtended).length == 0) return ''; string memory extension = ""; if (metadataHasExtension) extension = ".json"; return string(abi.encodePacked(baseURIExtended, Strings.toString(tokenId), extension)); } function totalMinted() public view returns (uint256) { return _totalMinted(); } function mintableLeft() public view returns (uint256) { return MAX_SUPPLY - totalMinted(); } //////////// // Helpers //////////// function removeArrayAtUint256Index(uint256[] storage array, uint256 index) private { array[index] = array[array.length - 1]; array.pop(); } function removeArrayAtInt256Index(int256[] storage array, uint256 index) private { array[index] = array[array.length - 1]; array.pop(); } function _existedInUint256Array(uint256[] storage array, uint256 value) private view returns (bool) { uint256 len = array.length; for (uint i = 0; i < len; i++) if (array[i] == value) return true; return false; } function _recoverAddress(bytes memory data, uint8 v, bytes32 r, bytes32 s) private pure returns (address) { return ecrecover(keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", keccak256(data) ) ), v, r, s); } function _transferEth(address payable to, uint256 amount) private { if (amount == 0) return; (bool sent,) = to.call{ value: amount }(""); if (!sent) revert EtherNotSent(); } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721A) returns (bool) { return super.supportsInterface(interfaceId) || ERC721A.supportsInterface(interfaceId); } /////////////// // Withdrawal /////////////// function withdraw() public onlyOwner { _transferEth(payable(msg.sender), address(this).balance); } function withdrawToken(address tokenAddress) public onlyOwner { IERC20 tokenContract = IERC20(tokenAddress); tokenContract.transfer(msg.sender, tokenContract.balanceOf(address(this))); } ///////////// // Fallback ///////////// receive() external payable { } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"DuplicatedNonce","type":"error"},{"inputs":[],"name":"EtherNotSent","type":"error"},{"inputs":[],"name":"HitMaximum","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MetadataFrozen","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NonExistentToken","type":"error"},{"inputs":[],"name":"NotEligible","type":"error"},{"inputs":[],"name":"NotStarted","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"RoleNotExisted","type":"error"},{"inputs":[],"name":"RunOut","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"UnmatchedEther","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":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"","type":"uint256"}],"name":"RoundChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"","type":"uint256"}],"name":"TotalMintedChanged","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"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"maxMint","type":"uint256"},{"internalType":"uint256","name":"mintPrice","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoleInRoundParams[]","name":"params","type":"tuple[]"},{"internalType":"bool","name":"replace","type":"bool"}],"name":"addAllowedRolesInRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoleAllocationParams[]","name":"params","type":"tuple[]"},{"internalType":"bool","name":"replace","type":"bool"}],"name":"addRolesAllocation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"maxMint","type":"uint256"},{"internalType":"uint256","name":"mintPrice","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoleInRoundParams[]","name":"_rolesInRound","type":"tuple[]"},{"internalType":"bool","name":"_replaceRoleInRound","type":"bool"},{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoundAllocationParams[]","name":"_roundAllocations","type":"tuple[]"},{"internalType":"bool","name":"_replaceRoundAllocations","type":"bool"},{"components":[{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoleAllocationParams[]","name":"_roleAllocations","type":"tuple[]"},{"internalType":"bool","name":"_replaceRoleAllocations","type":"bool"}],"name":"addRolesRounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoundAllocationParams[]","name":"params","type":"tuple[]"},{"internalType":"bool","name":"replace","type":"bool"}],"name":"addRoundsAllocation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMintTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currencyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllAllowedRolesInRounds","outputs":[{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"maxMint","type":"uint256"},{"internalType":"uint256","name":"mintPrice","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoleInRoundParams[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRoleAllocations","outputs":[{"components":[{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoleAllocationParams[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRoundAllocations","outputs":[{"components":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"internalType":"struct ApetimismLaunchpadNFT.RoundAllocationParams[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"round","type":"uint256"}],"name":"getAllowedRolesInRoundArr","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfigs","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"},{"internalType":"bool","name":"","type":"bool"}],"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":"address","name":"addr","type":"address"},{"internalType":"int256","name":"role","type":"int256"}],"name":"maxMintableForRole","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"int256","name":"role","type":"int256"}],"name":"maxMintableForTxForRole","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"int256","name":"role","type":"int256"},{"internalType":"uint256","name":"apetimismFee","type":"uint256"},{"internalType":"address","name":"apetimismAddress","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"role","type":"int256"}],"name":"mintPriceForCurrentRoundForRole","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintableLeft","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"int256","name":"role","type":"int256"}],"name":"removeAllowedRoleInRound","outputs":[],"stateMutability":"nonpayable","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":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransfersFrom","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":"address","name":"addr","type":"address"}],"name":"setCurrencyAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"round_","type":"uint256"}],"name":"setCurrentRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"setCurrentRoundFromSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"setMaxMintPerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"setMaxMintPerTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"hasExtension","type":"bool"}],"name":"setMetadataHasExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"setSignerAddressFromSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"transfersFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052612710601b819055601c55601e80546001600160a81b031916740407ffd4ead1b1ad36fa5f262ed7f13b50e1fc89011790553480156200004357600080fd5b50604080518082018252600481526310985c9d60e21b6020808301918252835180850190945260088452672130b93a21b7b4b760c11b908401528151919291620000909160029162000116565b508051620000a690600390602084019062000116565b5050600160005550620000b933620000c4565b6001600955620001f9565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200012490620001bc565b90600052602060002090601f01602090048101928262000148576000855562000193565b82601f106200016357805160ff191683800117855562000193565b8280016001018555821562000193579182015b828111156200019357825182559160200191906001019062000176565b50620001a1929150620001a5565b5090565b5b80821115620001a15760008155600101620001a6565b600181811c90821680620001d157607f821691505b60208210811415620001f357634e487b7160e01b600052602260045260246000fd5b50919050565b613e0580620002096000396000f3fe6080604052600436106102e35760003560e01c806370a0823111610186578063abdc3033116100d7578063d111515d11610085578063d111515d146108d0578063dd065559146108e5578063ddddefc714610905578063e985e9c514610925578063f2fde38b1461096e578063f4d40a9c1461098e578063fb0c402b146109d557600080fd5b8063abdc3033146107f5578063ac7dc68d1461081b578063b88d4fde14610830578063be4f182c14610843578063c23dc68f14610863578063c87b56dd14610890578063c9d48579146108b057600080fd5b80638a19c8bc116101345780638a19c8bc146107335780638da5cb5b1461074957806395d89b411461076757806399a2557a1461077c578063a22cb4651461079c578063a2309ff8146107bc578063a4fb233c146107d557600080fd5b806370a082311461065c578063715018a61461067c578063748a500a14610691578063796b89ec146106a65780638462151c146106c657806389476069146106f357806389b5a8c21461071357600080fd5b80633aeb75011161024057806355f804b3116101ee57806355f804b3146105775780635b7633d0146105975780635bbb2177146105bc578063616cdb1e146105e95780636352211e146106095780636c22e06e146106295780636e453d621461063c57600080fd5b80633aeb7501146104ad5780633bc91e28146104cd5780633ccfd60b146104ed5780633d6a5745146105025780633e9dbed01461052257806342842e0e14610544578063511e1d511461055757600080fd5b806318160ddd1161029d57806318160ddd146103e75780631c1cb323146104045780631e14d44b1461042457806323b872dd146104445780632fdea6541461045757806332ab9bbe1461047757806332cb6b0c1461049757600080fd5b80620319df146102ef57806301ffc9a71461031a57806306fdde031461034a578063081812fc1461036c578063095ea7b3146103a45780630ebbb09c146103b957600080fd5b366102ea57005b600080fd5b3480156102fb57600080fd5b506103046109f5565b60405161031191906130a1565b60405180910390f35b34801561032657600080fd5b5061033a610335366004613106565b610ae3565b6040519015158152602001610311565b34801561035657600080fd5b5061035f610b03565b604051610311919061317b565b34801561037857600080fd5b5061038c61038736600461318e565b610b95565b6040516001600160a01b039091168152602001610311565b6103b76103b23660046131c3565b610bd9565b005b3480156103c557600080fd5b506103d96103d43660046131c3565b610c79565b604051908152602001610311565b3480156103f357600080fd5b5060015460005403600019016103d9565b34801561041057600080fd5b5060205461038c906001600160a01b031681565b34801561043057600080fd5b506103b761043f36600461318e565b610c97565b6103b76104523660046131ed565b610ca4565b34801561046357600080fd5b506103b7610472366004613379565b610e36565b34801561048357600080fd5b506103b761049236600461349c565b610f11565b3480156104a357600080fd5b506103d961271081565b3480156104b957600080fd5b506103b76104c83660046135b3565b610f5b565b3480156104d957600080fd5b506103b76104e836600461318e565b610f81565b3480156104f957600080fd5b506103b7610fbc565b34801561050e57600080fd5b506103b761051d3660046131c3565b610fd0565b34801561052e57600080fd5b50610537610fef565b6040516103119190613677565b6103b76105523660046131ed565b611204565b34801561056357600080fd5b506103b76105723660046136ce565b611224565b34801561058357600080fd5b506103b7610592366004613703565b611386565b3480156105a357600080fd5b50601e5461038c9061010090046001600160a01b031681565b3480156105c857600080fd5b506105dc6105d736600461374b565b6113c5565b60405161031191906137fb565b3480156105f557600080fd5b506103b761060436600461318e565b611477565b34801561061557600080fd5b5061038c61062436600461318e565b611484565b6103b761063736600461384e565b61148f565b34801561064857600080fd5b506103b76106573660046138bb565b611864565b34801561066857600080fd5b506103d96106773660046138d8565b61187f565b34801561068857600080fd5b506103b76118cd565b34801561069d57600080fd5b506103046118df565b3480156106b257600080fd5b506103b76106c13660046138d8565b6119c4565b3480156106d257600080fd5b506106e66106e13660046138d8565b6119ee565b60405161031191906138f3565b3480156106ff57600080fd5b506103b761070e3660046138d8565b611adb565b34801561071f57600080fd5b506103b761072e36600461392b565b611be4565b34801561073f57600080fd5b506103d9601f5481565b34801561075557600080fd5b506008546001600160a01b031661038c565b34801561077357600080fd5b5061035f611c26565b34801561078857600080fd5b506106e6610797366004613988565b611c35565b3480156107a857600080fd5b506103b76107b73660046139bb565b611dbe565b3480156107c857600080fd5b50600054600019016103d9565b3480156107e157600080fd5b506103b76107f03660046139e7565b611e2f565b34801561080157600080fd5b5061080a611e81565b604051610311959493929190613a2e565b34801561082757600080fd5b506103d9611f4f565b6103b761083e366004613a69565b611f63565b34801561084f57600080fd5b506103b761085e366004613ac4565b611fa7565b34801561086f57600080fd5b5061088361087e36600461318e565b612126565b6040516103119190613ae6565b34801561089c57600080fd5b5061035f6108ab36600461318e565b612176565b3480156108bc57600080fd5b506103b76108cb366004613af4565b612234565b3480156108dc57600080fd5b506103b761229f565b3480156108f157600080fd5b506103b7610900366004613379565b6122b6565b34801561091157600080fd5b506103d96109203660046131c3565b6123c1565b34801561093157600080fd5b5061033a610940366004613b2a565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b34801561097a57600080fd5b506103b76109893660046138d8565b612561565b34801561099a57600080fd5b506103d96109a936600461318e565b6017546000908152600e60209081526040808320601f5484528252808320938352929052206003015490565b3480156109e157600080fd5b506106e66109f036600461318e565b6125df565b6012546060906000816001600160401b03811115610a1557610a15613229565b604051908082528060200260200182016040528015610a5a57816020015b6040805180820190915260008082526020820152815260200190600190039081610a335790505b5060185460009081526013602052604081209192505b83811015610ada576000838281518110610a8c57610a8c613b5d565b6020026020010151905060128281548110610aa957610aa9613b5d565b6000918252602080832090910154808452825284815260409091205491015280610ad281613b89565b915050610a70565b50909392505050565b6000610aee8261269b565b80610afd5750610afd8261269b565b92915050565b606060028054610b1290613ba4565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3e90613ba4565b8015610b8b5780601f10610b6057610100808354040283529160200191610b8b565b820191906000526020600020905b815481529060010190602001808311610b6e57829003601f168201915b5050505050905090565b6000610ba0826126e9565b610bbd576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b6000610be482611484565b9050336001600160a01b03821614610c1d57610c008133610940565b610c1d576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000610c90610c8884846123c1565b601b5461271e565b9392505050565b610c9f612734565b601c55565b6000610caf8261278e565b9050836001600160a01b0316816001600160a01b031614610ce25760405162a1148160e81b815260040160405180910390fd5b60008281526006602052604090208054338082146001600160a01b03881690911417610d2f57610d128633610940565b610d2f57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b038516610d5657604051633a954ecd60e21b815260040160405180910390fd5b8015610d6157600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040902055600160e11b8316610dec5760018401600081815260046020526040902054610dea576000548114610dea5760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b505050505050565b610e3e612734565b8015610e665760188054906000610e5483613b89565b90915550610e66905060126000612fc3565b6018546000908152601360205260408120905b8351811015610f0b576000848281518110610e9657610e96613b5d565b6020908102919091018101518051818301516000828152938790526040909320929092559150610ec76012826127f7565b610f0157601280546001810182556000919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444018190555b5050600101610e79565b50505050565b60005b8251811015610f5457610f428585858481518110610f3457610f34613b5d565b602002602001015185611f63565b80610f4c81613b89565b915050610f14565b5050505050565b610f63612734565b610f6d8686611224565b610f778484610e36565b610e2e82826122b6565b610f89612734565b601f81905560405181907fe13ec1fa9c3ede43997fc070c234a83909ba45575dd0ad079ea7138418cc846590600090a250565b610fc4612734565b610fce3347612852565b565b610fd8612734565b610fe1816128cf565b610feb8282612918565b5050565b6017546000908152600f60205260408120606091805b60115481101561105e578260006011838154811061102557611025613b5d565b90600052602060002001548152602001908152602001600020548261104a9190613bdf565b91508061105681613b89565b915050611005565b506000816001600160401b0381111561107957611079613229565b6040519080825280602002602001820160405280156110d557816020015b6110c26040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816110975790505b5090506000805b6011548110156111fa576000601182815481106110fb576110fb613b5d565b6000918252602080832090910154808352908890526040822054909250905b818110156111e4576017546000908152601060209081526040808320868452909152812080548390811061115057611150613b5d565b60009182526020808320909101546017548352600e8252604080842088855283528084208285529092529082208951919350919089908990811061119657611196613b5d565b60209081029190910181015187815290810184905260028301546040820152600383015460608201529050876111cb81613b89565b98505050505080806111dc90613b89565b91505061111a565b50505080806111f290613b89565b9150506110dc565b5090949350505050565b61121f83838360405180602001604052806000815250611f63565b505050565b61122c612734565b8015611254576017805490600061124283613b89565b90915550611254905060116000612fc3565b6017546000908152600e60209081526040808320600f8352818420601090935290832090925b8551811015610e2e57600086828151811061129757611297613b5d565b60209081029190910181015180516000818152888452604080822084860180518452955290819020828155935160018501558201516002840155606082015160038401556004830154919350919060ff16156112f55750505061137e565b60048101805460ff19166001908117909155600083815260208881526040808320805485019055888252822086820151815494850182559083529120909101556113406011836127f7565b61137a57601180546001810182556000919091527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c68018290555b5050505b60010161127a565b61138e612734565b601a5460ff16156113b25760405163777821ff60e11b815260040160405180910390fd5b8051610feb90601d906020840190612fe1565b6060816000816001600160401b038111156113e2576113e2613229565b60405190808252806020026020018201604052801561141b57816020015b611408613065565b8152602001906001900390816114005790505b50905060005b82811461146e5761144986868381811061143d5761143d613b5d565b90506020020135612126565b82828151811061145b5761145b613b5d565b6020908102919091010152600101611421565b50949350505050565b61147f612734565b601b55565b6000610afd8261278e565b611497612932565b601f546114b757604051636f312cbd60e01b815260040160405180910390fd5b83600088126114d1576114ce88601087901b613bdf565b90505b61151f8182898960405160200161150893929190928352602083019190915260601b6001600160601b031916604082015260540190565b60405160208183030381529060405286868661298c565b6017546000908152600e60209081526040808320601f548452909152812090808a126115485750885b60008181526020839052604090206004015460ff166115975760008080526020839052604090206004015460ff1661159357604051637c75aa6f60e11b815260040160405180910390fd5b5060005b6115a08b6128cf565b6000808b126115ac5750895b8b6115b73383610c79565b10156115d657604051633ce4251960e01b815260040160405180910390fd5b506000818152602083905260408120600301546115f3908d613bf7565b6000858152600d60209081526040909120600190555490915081906001600160a01b031615611620575060005b80341461164057604051630551cf2960e01b815260040160405180910390fd5b5061164b338d612918565b601f54600090815260166020526040812080548e929061166c908490613bdf565b9091555050336000908152600a6020526040812080548e9290611690908490613bdf565b9091555050336000908152600b60209081526040808320601f5484528252808320858452909152812080548e92906116c9908490613bdf565b9091555050336000908152600c60209081526040808320858452909152812080548e92906116f8908490613bdf565b909155506000905061271061170d8c84613bf7565b6117179190613c16565b6020549091506001600160a01b031615611841576020546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b039091169081906323b872dd90606401602060405180830381600087803b15801561177f57600080fd5b505af1158015611793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b79190613c38565b5060405163a9059cbb60e01b81526001600160a01b038c811660048301526024820184905282169063a9059cbb90604401602060405180830381600087803b15801561180257600080fd5b505af1158015611816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183a9190613c38565b505061184b565b61184b8a82612852565b505050505061185a6001600955565b5050505050505050565b61186c612734565b601e805460ff1916911515919091179055565b60006001600160a01b0382166118a8576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152600560205260409020546001600160401b031690565b6118d5612734565b610fce60006129fd565b6015546060906000816001600160401b038111156118ff576118ff613229565b60405190808252806020026020018201604052801561194457816020015b604080518082019091526000808252602082015281526020019060019003908161191d5790505b5060195460009081526014602052604081209192505b83811015610ada57600083828151811061197657611976613b5d565b602002602001015190506015828154811061199357611993613b5d565b60009182526020808320909101548084528252848152604090912054910152806119bc81613b89565b91505061195a565b6119cc612734565b602080546001600160a01b0319166001600160a01b0392909216919091179055565b606060008060006119fe8561187f565b90506000816001600160401b03811115611a1a57611a1a613229565b604051908082528060200260200182016040528015611a43578160200160208202803683370190505b509050611a4e613065565b60015b838614611acf57611a6181612a4f565b9150816040015115611a7257611ac7565b81516001600160a01b031615611a8757815194505b876001600160a01b0316856001600160a01b03161415611ac75780838780600101985081518110611aba57611aba613b5d565b6020026020010181815250505b600101611a51565b50909695505050505050565b611ae3612734565b6040516370a0823160e01b815230600482015281906001600160a01b0382169063a9059cbb90339083906370a082319060240160206040518083038186803b158015611b2e57600080fd5b505afa158015611b42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b669190613c55565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015611bac57600080fd5b505af1158015611bc0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121f9190613c38565b60005b8151811015610f0b57611c148484848481518110611c0757611c07613b5d565b6020026020010151610ca4565b80611c1e81613b89565b915050611be7565b606060038054610b1290613ba4565b6060818310611c5757604051631960ccad60e11b815260040160405180910390fd5b600080611c6360005490565b90506001851015611c7357600194505b80841115611c7f578093505b6000611c8a8761187f565b905084861015611ca95785850381811015611ca3578091505b50611cad565b5060005b6000816001600160401b03811115611cc757611cc7613229565b604051908082528060200260200182016040528015611cf0578160200160208202803683370190505b50905081611d03579350610c9092505050565b6000611d0e88612126565b905060008160400151611d1f575080515b885b888114158015611d315750848714155b15611dad57611d3f81612a4f565b9250826040015115611d5057611da5565b82516001600160a01b031615611d6557825191505b8a6001600160a01b0316826001600160a01b03161415611da55780848880600101995081518110611d9857611d98613b5d565b6020026020010181815250505b600101611d21565b505050928352509095945050505050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b905090565b611e66858686604051602001611e4f929190918252602082015260400190565b60405160208183030381529060405285858561298c565b6000858152600d6020526040902060019055610f5484610f81565b600080600060606000601a60009054906101000a900460ff16601b54601c54601d601e60009054906101000a900460ff16818054611ebe90613ba4565b80601f0160208091040260200160405190810160405280929190818152602001828054611eea90613ba4565b8015611f375780601f10611f0c57610100808354040283529160200191611f37565b820191906000526020600020905b815481529060010190602001808311611f1a57829003601f168201915b50505050509150945094509450945094509091929394565b6000805460001901611e2a90612710613c6e565b611f6e848484610ca4565b6001600160a01b0383163b15610f0b57611f8a84848484612a6f565b610f0b576040516368d2bf6b60e11b815260040160405180910390fd5b611faf612734565b6017546000818152600e6020908152604080832086845282528083208584528252808320938352600f9091529020600482015460ff166120025760405163d73251d760e01b815260040160405180910390fd5b600080835560018301819055600283018190556003830181905560048301805460ff1916905584815260208290526040812080549161204083613c85565b909155505060175460009081526010602090815260408083208784529091528120805490915b818110156120b3578583828154811061208157612081613b5d565b906000526020600020015414156120a15761209c8382612b67565b6120b3565b806120ab81613b89565b915050612066565b50600086815260208490526040902054610e2e575060125460005b8181101561211d5786601282815481106120ea576120ea613b5d565b9060005260206000200154141561210b57612106601282612b67565b61211d565b8061211581613b89565b9150506120ce565b50505050505050565b61212e613065565b612136613065565b600183108061214757506000548310155b156121525792915050565b61215b83612a4f565b905080604001511561216d5792915050565b610c9083612bdc565b6060612181826126e9565b61219e57604051634a1850bf60e11b815260040160405180910390fd5b601d80546121ab90613ba4565b151590506121c757505060408051602081019091526000815290565b604080516020810190915260008152601e5460ff16156121ff5750604080518082019091526005815264173539b7b760d91b60208201525b601d61220a84612bf5565b8260405160200161221d93929190613cb8565b604051602081830303815290604052915050919050565b612261858686604051602001611e4f92919091825260601b6001600160601b031916602082015260340190565b5050506000918252600d602052604090912060019055601e80546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6122a7612734565b601a805460ff19166001179055565b6122be612734565b80156122e657601980549060006122d483613b89565b909155506122e6905060156000612fc3565b6019546000908152601460205260408120905b8351811015610f0b57600084828151811061231657612316613b5d565b6020908102919091018101518082015181516000908152928690526040832055601554909250815b8181101561237a578351601580548390811061235c5761235c613b5d565b9060005260206000200154141561237257600192505b60010161233e565b50816123b6578251601580546001810182556000919091527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47501555b5050506001016122f9565b6001600160a01b0382166000818152600a6020908152604080832054601854845260138352818420601f5480865290845282852054601954865260148552838620888752855283862054878752600b86528487208388528652848720898852865284872054978752600c865284872089885286528487205483885260169096529386205495969295879591949392158061245b5750848110155b806124665750838210155b806124735750601c548710155b8061247e5750848110155b15612493576000975050505050505050610afd565b6017546000908152600e60209081526040808320601f54845282528083208c84529091529020600481015460ff16156124ce57806002015496505b8684106124e657600098505050505050505050610afd565b600088601c546124f69190613c6e565b90506000612504868a613c6e565b90506000612512858a613c6e565b90506000612520878a613c6e565b905061254e61254161253b612535878761271e565b8561271e565b8361271e565b612549611f4f565b61271e565b9f9e505050505050505050505050505050565b612569612734565b6001600160a01b0381166125d35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6125dc816129fd565b50565b601754600090815260106020908152604080832084845290915281208054606092816001600160401b0381111561261857612618613229565b604051908082528060200260200182016040528015612641578160200160208202803683370190505b50905060005b8281101561146e5783818154811061266157612661613b5d565b906000526020600020015482828151811061267e5761267e613b5d565b60209081029190910101528061269381613b89565b915050612647565b60006301ffc9a760e01b6001600160e01b0319831614806126cc57506380ac58cd60e01b6001600160e01b03198316145b80610afd5750506001600160e01b031916635b5e139f60e01b1490565b6000816001111580156126fd575060005482105b8015610afd575050600090815260046020526040902054600160e01b161590565b600081831061272d5781610c90565b5090919050565b6008546001600160a01b03163314610fce5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016125ca565b600081806001116127de576000548110156127de57600081815260046020526040902054600160e01b81166127dc575b80610c905750600019016000818152600460205260409020546127be565b505b604051636f96cda160e11b815260040160405180910390fd5b8154600090815b81811015612847578385828154811061281957612819613b5d565b9060005260206000200154141561283557600192505050610afd565b8061283f81613b89565b9150506127fe565b506000949350505050565b8061285b575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146128a8576040519150601f19603f3d011682016040523d82523d6000602084013e6128ad565b606091505b505090508061121f576040516328316c4d60e11b815260040160405180910390fd5b600081116128f05760405163162908e360e11b815260040160405180910390fd5b806128f9611f4f565b10156125dc5760405163671317e960e11b815260040160405180910390fd5b610feb828260405180602001604052806000815250612c91565b600260095414156129855760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016125ca565b6002600955565b6000858152600d6020526040902054156129b95760405163256f5cdd60e11b815260040160405180910390fd5b601e5461010090046001600160a01b03166129d685858585612cf7565b6001600160a01b031614610f5457604051638baa579f60e01b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612a57613065565b600082815260046020526040902054610afd90612db1565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290612aa4903390899088908890600401613d69565b602060405180830381600087803b158015612abe57600080fd5b505af1925050508015612aee575060408051601f3d908101601f19168201909252612aeb91810190613d9c565b60015b612b49573d808015612b1c576040519150601f19603f3d011682016040523d82523d6000602084013e612b21565b606091505b508051612b41576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b81548290612b7790600190613c6e565b81548110612b8757612b87613b5d565b9060005260206000200154828281548110612ba457612ba4613b5d565b906000526020600020018190555081805480612bc257612bc2613db9565b600190038181906000526020600020016000905590555050565b612be4613065565b610afd612bf08361278e565b612db1565b60606000612c0283612df4565b60010190506000816001600160401b03811115612c2157612c21613229565b6040519080825280601f01601f191660200182016040528015612c4b576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612c8457612c89565b612c55565b509392505050565b612c9b8383612ecc565b6001600160a01b0383163b1561121f576000548281035b612cc56000868380600101945086612a6f565b612ce2576040516368d2bf6b60e11b815260040160405180910390fd5b818110612cb2578160005414610f5457600080fd5b600060018580519060200120604051602001612d3f91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b60408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015612d9d573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b612db9613065565b6001600160a01b03821681526001600160401b0360a083901c166020820152600160e01b82161515604082015260e89190911c606082015290565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612e335772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612e5f576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612e7d57662386f26fc10000830492506010015b6305f5e1008310612e95576305f5e100830492506008015b6127108310612ea957612710830492506004015b60648310612ebb576064830492506002015b600a8310610afd5760010192915050565b60005481612eed5760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b818114612f9c57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600101612f64565b5081612fba57604051622e076360e81b815260040160405180910390fd5b60005550505050565b50805460008255906000526020600020908101906125dc919061308c565b828054612fed90613ba4565b90600052602060002090601f01602090048101928261300f5760008555613055565b82601f1061302857805160ff1916838001178555613055565b82800160010185558215613055579182015b8281111561305557825182559160200191906001019061303a565b5061306192915061308c565b5090565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b80821115613061576000815560010161308d565b602080825282518282018190526000919060409081850190868401855b828110156130e3578151805185528601518685015292840192908501906001016130be565b5091979650505050505050565b6001600160e01b0319811681146125dc57600080fd5b60006020828403121561311857600080fd5b8135610c90816130f0565b60005b8381101561313e578181015183820152602001613126565b83811115610f0b5750506000910152565b60008151808452613167816020860160208601613123565b601f01601f19169290920160200192915050565b602081526000610c90602083018461314f565b6000602082840312156131a057600080fd5b5035919050565b80356001600160a01b03811681146131be57600080fd5b919050565b600080604083850312156131d657600080fd5b6131df836131a7565b946020939093013593505050565b60008060006060848603121561320257600080fd5b61320b846131a7565b9250613219602085016131a7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561326157613261613229565b60405290565b604051608081016001600160401b038111828210171561326157613261613229565b604051601f8201601f191681016001600160401b03811182821017156132b1576132b1613229565b604052919050565b60006001600160401b038211156132d2576132d2613229565b5060051b60200190565b600082601f8301126132ed57600080fd5b813560206133026132fd836132b9565b613289565b82815260069290921b8401810191818101908684111561332157600080fd5b8286015b84811015613360576040818903121561333e5760008081fd5b61334661323f565b813581528482013585820152835291830191604001613325565b509695505050505050565b80151581146125dc57600080fd5b6000806040838503121561338c57600080fd5b82356001600160401b038111156133a257600080fd5b6133ae858286016132dc565b92505060208301356133bf8161336b565b809150509250929050565b600082601f8301126133db57600080fd5b813560206133eb6132fd836132b9565b82815260059290921b8401810191818101908684111561340a57600080fd5b8286015b84811015613360578035835291830191830161340e565b60006001600160401b0383111561343e5761343e613229565b613451601f8401601f1916602001613289565b905082815283838301111561346557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261348d57600080fd5b610c9083833560208501613425565b600080600080608085870312156134b257600080fd5b6134bb856131a7565b93506134c9602086016131a7565b925060408501356001600160401b03808211156134e557600080fd5b6134f1888389016133ca565b9350606087013591508082111561350757600080fd5b506135148782880161347c565b91505092959194509250565b600082601f83011261353157600080fd5b813560206135416132fd836132b9565b82815260079290921b8401810191818101908684111561356057600080fd5b8286015b84811015613360576080818903121561357d5760008081fd5b613585613267565b8135815284820135858201526040808301359082015260608083013590820152835291830191608001613564565b60008060008060008060c087890312156135cc57600080fd5b86356001600160401b03808211156135e357600080fd5b6135ef8a838b01613520565b9750602089013591506136018261336b565b9095506040880135908082111561361757600080fd5b6136238a838b016132dc565b9550606089013591506136358261336b565b9093506080880135908082111561364b57600080fd5b5061365889828a016132dc565b92505060a08701356136698161336b565b809150509295509295509295565b602080825282518282018190526000919060409081850190868401855b828110156130e357815180518552868101518786015285810151868601526060908101519085015260809093019290850190600101613694565b600080604083850312156136e157600080fd5b82356001600160401b038111156136f757600080fd5b6133ae85828601613520565b60006020828403121561371557600080fd5b81356001600160401b0381111561372b57600080fd5b8201601f8101841361373c57600080fd5b612b5f84823560208401613425565b6000806020838503121561375e57600080fd5b82356001600160401b038082111561377557600080fd5b818501915085601f83011261378957600080fd5b81358181111561379857600080fd5b8660208260051b85010111156137ad57600080fd5b60209290920196919550909350505050565b80516001600160a01b031682526020808201516001600160401b03169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b81811015611acf5761382a8385516137bf565b9284019260809290920191600101613817565b803560ff811681146131be57600080fd5b600080600080600080600080610100898b03121561386b57600080fd5b88359750602089013596506040890135955061388960608a016131a7565b94506080890135935061389e60a08a0161383d565b925060c0890135915060e089013590509295985092959890939650565b6000602082840312156138cd57600080fd5b8135610c908161336b565b6000602082840312156138ea57600080fd5b610c90826131a7565b6020808252825182820181905260009190848201906040850190845b81811015611acf5783518352928401929184019160010161390f565b60008060006060848603121561394057600080fd5b613949846131a7565b9250613957602085016131a7565b915060408401356001600160401b0381111561397257600080fd5b61397e868287016133ca565b9150509250925092565b60008060006060848603121561399d57600080fd5b6139a6846131a7565b95602085013595506040909401359392505050565b600080604083850312156139ce57600080fd5b6139d7836131a7565b915060208301356133bf8161336b565b600080600080600060a086880312156139ff57600080fd5b8535945060208601359350613a166040870161383d565b94979396509394606081013594506080013592915050565b851515815284602082015283604082015260a060608201526000613a5560a083018561314f565b905082151560808301529695505050505050565b60008060008060808587031215613a7f57600080fd5b613a88856131a7565b9350613a96602086016131a7565b92506040850135915060608501356001600160401b03811115613ab857600080fd5b6135148782880161347c565b60008060408385031215613ad757600080fd5b50508035926020909101359150565b60808101610afd82846137bf565b600080600080600060a08688031215613b0c57600080fd5b85359450613b1c602087016131a7565b9350613a166040870161383d565b60008060408385031215613b3d57600080fd5b613b46836131a7565b9150613b54602084016131a7565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415613b9d57613b9d613b73565b5060010190565b600181811c90821680613bb857607f821691505b60208210811415613bd957634e487b7160e01b600052602260045260246000fd5b50919050565b60008219821115613bf257613bf2613b73565b500190565b6000816000190483118215151615613c1157613c11613b73565b500290565b600082613c3357634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215613c4a57600080fd5b8151610c908161336b565b600060208284031215613c6757600080fd5b5051919050565b600082821015613c8057613c80613b73565b500390565b600081613c9457613c94613b73565b506000190190565b60008151613cae818560208601613123565b9290920192915050565b600080855481600182811c915080831680613cd457607f831692505b6020808410821415613cf457634e487b7160e01b86526022600452602486fd5b818015613d085760018114613d1957613d46565b60ff19861689528489019650613d46565b60008c81526020902060005b86811015613d3e5781548b820152908501908301613d25565b505084890196505b505050505050613d5f613d598287613c9c565b85613c9c565b9695505050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613d5f9083018461314f565b600060208284031215613dae57600080fd5b8151610c90816130f0565b634e487b7160e01b600052603160045260246000fdfea264697066735822122009c37dea9132af101e7da31ec87c2beba64ee47dfd1299d32be1c7fe14760f2364736f6c63430008090033
Deployed Bytecode
0x6080604052600436106102e35760003560e01c806370a0823111610186578063abdc3033116100d7578063d111515d11610085578063d111515d146108d0578063dd065559146108e5578063ddddefc714610905578063e985e9c514610925578063f2fde38b1461096e578063f4d40a9c1461098e578063fb0c402b146109d557600080fd5b8063abdc3033146107f5578063ac7dc68d1461081b578063b88d4fde14610830578063be4f182c14610843578063c23dc68f14610863578063c87b56dd14610890578063c9d48579146108b057600080fd5b80638a19c8bc116101345780638a19c8bc146107335780638da5cb5b1461074957806395d89b411461076757806399a2557a1461077c578063a22cb4651461079c578063a2309ff8146107bc578063a4fb233c146107d557600080fd5b806370a082311461065c578063715018a61461067c578063748a500a14610691578063796b89ec146106a65780638462151c146106c657806389476069146106f357806389b5a8c21461071357600080fd5b80633aeb75011161024057806355f804b3116101ee57806355f804b3146105775780635b7633d0146105975780635bbb2177146105bc578063616cdb1e146105e95780636352211e146106095780636c22e06e146106295780636e453d621461063c57600080fd5b80633aeb7501146104ad5780633bc91e28146104cd5780633ccfd60b146104ed5780633d6a5745146105025780633e9dbed01461052257806342842e0e14610544578063511e1d511461055757600080fd5b806318160ddd1161029d57806318160ddd146103e75780631c1cb323146104045780631e14d44b1461042457806323b872dd146104445780632fdea6541461045757806332ab9bbe1461047757806332cb6b0c1461049757600080fd5b80620319df146102ef57806301ffc9a71461031a57806306fdde031461034a578063081812fc1461036c578063095ea7b3146103a45780630ebbb09c146103b957600080fd5b366102ea57005b600080fd5b3480156102fb57600080fd5b506103046109f5565b60405161031191906130a1565b60405180910390f35b34801561032657600080fd5b5061033a610335366004613106565b610ae3565b6040519015158152602001610311565b34801561035657600080fd5b5061035f610b03565b604051610311919061317b565b34801561037857600080fd5b5061038c61038736600461318e565b610b95565b6040516001600160a01b039091168152602001610311565b6103b76103b23660046131c3565b610bd9565b005b3480156103c557600080fd5b506103d96103d43660046131c3565b610c79565b604051908152602001610311565b3480156103f357600080fd5b5060015460005403600019016103d9565b34801561041057600080fd5b5060205461038c906001600160a01b031681565b34801561043057600080fd5b506103b761043f36600461318e565b610c97565b6103b76104523660046131ed565b610ca4565b34801561046357600080fd5b506103b7610472366004613379565b610e36565b34801561048357600080fd5b506103b761049236600461349c565b610f11565b3480156104a357600080fd5b506103d961271081565b3480156104b957600080fd5b506103b76104c83660046135b3565b610f5b565b3480156104d957600080fd5b506103b76104e836600461318e565b610f81565b3480156104f957600080fd5b506103b7610fbc565b34801561050e57600080fd5b506103b761051d3660046131c3565b610fd0565b34801561052e57600080fd5b50610537610fef565b6040516103119190613677565b6103b76105523660046131ed565b611204565b34801561056357600080fd5b506103b76105723660046136ce565b611224565b34801561058357600080fd5b506103b7610592366004613703565b611386565b3480156105a357600080fd5b50601e5461038c9061010090046001600160a01b031681565b3480156105c857600080fd5b506105dc6105d736600461374b565b6113c5565b60405161031191906137fb565b3480156105f557600080fd5b506103b761060436600461318e565b611477565b34801561061557600080fd5b5061038c61062436600461318e565b611484565b6103b761063736600461384e565b61148f565b34801561064857600080fd5b506103b76106573660046138bb565b611864565b34801561066857600080fd5b506103d96106773660046138d8565b61187f565b34801561068857600080fd5b506103b76118cd565b34801561069d57600080fd5b506103046118df565b3480156106b257600080fd5b506103b76106c13660046138d8565b6119c4565b3480156106d257600080fd5b506106e66106e13660046138d8565b6119ee565b60405161031191906138f3565b3480156106ff57600080fd5b506103b761070e3660046138d8565b611adb565b34801561071f57600080fd5b506103b761072e36600461392b565b611be4565b34801561073f57600080fd5b506103d9601f5481565b34801561075557600080fd5b506008546001600160a01b031661038c565b34801561077357600080fd5b5061035f611c26565b34801561078857600080fd5b506106e6610797366004613988565b611c35565b3480156107a857600080fd5b506103b76107b73660046139bb565b611dbe565b3480156107c857600080fd5b50600054600019016103d9565b3480156107e157600080fd5b506103b76107f03660046139e7565b611e2f565b34801561080157600080fd5b5061080a611e81565b604051610311959493929190613a2e565b34801561082757600080fd5b506103d9611f4f565b6103b761083e366004613a69565b611f63565b34801561084f57600080fd5b506103b761085e366004613ac4565b611fa7565b34801561086f57600080fd5b5061088361087e36600461318e565b612126565b6040516103119190613ae6565b34801561089c57600080fd5b5061035f6108ab36600461318e565b612176565b3480156108bc57600080fd5b506103b76108cb366004613af4565b612234565b3480156108dc57600080fd5b506103b761229f565b3480156108f157600080fd5b506103b7610900366004613379565b6122b6565b34801561091157600080fd5b506103d96109203660046131c3565b6123c1565b34801561093157600080fd5b5061033a610940366004613b2a565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b34801561097a57600080fd5b506103b76109893660046138d8565b612561565b34801561099a57600080fd5b506103d96109a936600461318e565b6017546000908152600e60209081526040808320601f5484528252808320938352929052206003015490565b3480156109e157600080fd5b506106e66109f036600461318e565b6125df565b6012546060906000816001600160401b03811115610a1557610a15613229565b604051908082528060200260200182016040528015610a5a57816020015b6040805180820190915260008082526020820152815260200190600190039081610a335790505b5060185460009081526013602052604081209192505b83811015610ada576000838281518110610a8c57610a8c613b5d565b6020026020010151905060128281548110610aa957610aa9613b5d565b6000918252602080832090910154808452825284815260409091205491015280610ad281613b89565b915050610a70565b50909392505050565b6000610aee8261269b565b80610afd5750610afd8261269b565b92915050565b606060028054610b1290613ba4565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3e90613ba4565b8015610b8b5780601f10610b6057610100808354040283529160200191610b8b565b820191906000526020600020905b815481529060010190602001808311610b6e57829003601f168201915b5050505050905090565b6000610ba0826126e9565b610bbd576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b6000610be482611484565b9050336001600160a01b03821614610c1d57610c008133610940565b610c1d576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000610c90610c8884846123c1565b601b5461271e565b9392505050565b610c9f612734565b601c55565b6000610caf8261278e565b9050836001600160a01b0316816001600160a01b031614610ce25760405162a1148160e81b815260040160405180910390fd5b60008281526006602052604090208054338082146001600160a01b03881690911417610d2f57610d128633610940565b610d2f57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b038516610d5657604051633a954ecd60e21b815260040160405180910390fd5b8015610d6157600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040902055600160e11b8316610dec5760018401600081815260046020526040902054610dea576000548114610dea5760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b505050505050565b610e3e612734565b8015610e665760188054906000610e5483613b89565b90915550610e66905060126000612fc3565b6018546000908152601360205260408120905b8351811015610f0b576000848281518110610e9657610e96613b5d565b6020908102919091018101518051818301516000828152938790526040909320929092559150610ec76012826127f7565b610f0157601280546001810182556000919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444018190555b5050600101610e79565b50505050565b60005b8251811015610f5457610f428585858481518110610f3457610f34613b5d565b602002602001015185611f63565b80610f4c81613b89565b915050610f14565b5050505050565b610f63612734565b610f6d8686611224565b610f778484610e36565b610e2e82826122b6565b610f89612734565b601f81905560405181907fe13ec1fa9c3ede43997fc070c234a83909ba45575dd0ad079ea7138418cc846590600090a250565b610fc4612734565b610fce3347612852565b565b610fd8612734565b610fe1816128cf565b610feb8282612918565b5050565b6017546000908152600f60205260408120606091805b60115481101561105e578260006011838154811061102557611025613b5d565b90600052602060002001548152602001908152602001600020548261104a9190613bdf565b91508061105681613b89565b915050611005565b506000816001600160401b0381111561107957611079613229565b6040519080825280602002602001820160405280156110d557816020015b6110c26040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001906001900390816110975790505b5090506000805b6011548110156111fa576000601182815481106110fb576110fb613b5d565b6000918252602080832090910154808352908890526040822054909250905b818110156111e4576017546000908152601060209081526040808320868452909152812080548390811061115057611150613b5d565b60009182526020808320909101546017548352600e8252604080842088855283528084208285529092529082208951919350919089908990811061119657611196613b5d565b60209081029190910181015187815290810184905260028301546040820152600383015460608201529050876111cb81613b89565b98505050505080806111dc90613b89565b91505061111a565b50505080806111f290613b89565b9150506110dc565b5090949350505050565b61121f83838360405180602001604052806000815250611f63565b505050565b61122c612734565b8015611254576017805490600061124283613b89565b90915550611254905060116000612fc3565b6017546000908152600e60209081526040808320600f8352818420601090935290832090925b8551811015610e2e57600086828151811061129757611297613b5d565b60209081029190910181015180516000818152888452604080822084860180518452955290819020828155935160018501558201516002840155606082015160038401556004830154919350919060ff16156112f55750505061137e565b60048101805460ff19166001908117909155600083815260208881526040808320805485019055888252822086820151815494850182559083529120909101556113406011836127f7565b61137a57601180546001810182556000919091527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c68018290555b5050505b60010161127a565b61138e612734565b601a5460ff16156113b25760405163777821ff60e11b815260040160405180910390fd5b8051610feb90601d906020840190612fe1565b6060816000816001600160401b038111156113e2576113e2613229565b60405190808252806020026020018201604052801561141b57816020015b611408613065565b8152602001906001900390816114005790505b50905060005b82811461146e5761144986868381811061143d5761143d613b5d565b90506020020135612126565b82828151811061145b5761145b613b5d565b6020908102919091010152600101611421565b50949350505050565b61147f612734565b601b55565b6000610afd8261278e565b611497612932565b601f546114b757604051636f312cbd60e01b815260040160405180910390fd5b83600088126114d1576114ce88601087901b613bdf565b90505b61151f8182898960405160200161150893929190928352602083019190915260601b6001600160601b031916604082015260540190565b60405160208183030381529060405286868661298c565b6017546000908152600e60209081526040808320601f548452909152812090808a126115485750885b60008181526020839052604090206004015460ff166115975760008080526020839052604090206004015460ff1661159357604051637c75aa6f60e11b815260040160405180910390fd5b5060005b6115a08b6128cf565b6000808b126115ac5750895b8b6115b73383610c79565b10156115d657604051633ce4251960e01b815260040160405180910390fd5b506000818152602083905260408120600301546115f3908d613bf7565b6000858152600d60209081526040909120600190555490915081906001600160a01b031615611620575060005b80341461164057604051630551cf2960e01b815260040160405180910390fd5b5061164b338d612918565b601f54600090815260166020526040812080548e929061166c908490613bdf565b9091555050336000908152600a6020526040812080548e9290611690908490613bdf565b9091555050336000908152600b60209081526040808320601f5484528252808320858452909152812080548e92906116c9908490613bdf565b9091555050336000908152600c60209081526040808320858452909152812080548e92906116f8908490613bdf565b909155506000905061271061170d8c84613bf7565b6117179190613c16565b6020549091506001600160a01b031615611841576020546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b039091169081906323b872dd90606401602060405180830381600087803b15801561177f57600080fd5b505af1158015611793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b79190613c38565b5060405163a9059cbb60e01b81526001600160a01b038c811660048301526024820184905282169063a9059cbb90604401602060405180830381600087803b15801561180257600080fd5b505af1158015611816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183a9190613c38565b505061184b565b61184b8a82612852565b505050505061185a6001600955565b5050505050505050565b61186c612734565b601e805460ff1916911515919091179055565b60006001600160a01b0382166118a8576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152600560205260409020546001600160401b031690565b6118d5612734565b610fce60006129fd565b6015546060906000816001600160401b038111156118ff576118ff613229565b60405190808252806020026020018201604052801561194457816020015b604080518082019091526000808252602082015281526020019060019003908161191d5790505b5060195460009081526014602052604081209192505b83811015610ada57600083828151811061197657611976613b5d565b602002602001015190506015828154811061199357611993613b5d565b60009182526020808320909101548084528252848152604090912054910152806119bc81613b89565b91505061195a565b6119cc612734565b602080546001600160a01b0319166001600160a01b0392909216919091179055565b606060008060006119fe8561187f565b90506000816001600160401b03811115611a1a57611a1a613229565b604051908082528060200260200182016040528015611a43578160200160208202803683370190505b509050611a4e613065565b60015b838614611acf57611a6181612a4f565b9150816040015115611a7257611ac7565b81516001600160a01b031615611a8757815194505b876001600160a01b0316856001600160a01b03161415611ac75780838780600101985081518110611aba57611aba613b5d565b6020026020010181815250505b600101611a51565b50909695505050505050565b611ae3612734565b6040516370a0823160e01b815230600482015281906001600160a01b0382169063a9059cbb90339083906370a082319060240160206040518083038186803b158015611b2e57600080fd5b505afa158015611b42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b669190613c55565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015611bac57600080fd5b505af1158015611bc0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121f9190613c38565b60005b8151811015610f0b57611c148484848481518110611c0757611c07613b5d565b6020026020010151610ca4565b80611c1e81613b89565b915050611be7565b606060038054610b1290613ba4565b6060818310611c5757604051631960ccad60e11b815260040160405180910390fd5b600080611c6360005490565b90506001851015611c7357600194505b80841115611c7f578093505b6000611c8a8761187f565b905084861015611ca95785850381811015611ca3578091505b50611cad565b5060005b6000816001600160401b03811115611cc757611cc7613229565b604051908082528060200260200182016040528015611cf0578160200160208202803683370190505b50905081611d03579350610c9092505050565b6000611d0e88612126565b905060008160400151611d1f575080515b885b888114158015611d315750848714155b15611dad57611d3f81612a4f565b9250826040015115611d5057611da5565b82516001600160a01b031615611d6557825191505b8a6001600160a01b0316826001600160a01b03161415611da55780848880600101995081518110611d9857611d98613b5d565b6020026020010181815250505b600101611d21565b505050928352509095945050505050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b905090565b611e66858686604051602001611e4f929190918252602082015260400190565b60405160208183030381529060405285858561298c565b6000858152600d6020526040902060019055610f5484610f81565b600080600060606000601a60009054906101000a900460ff16601b54601c54601d601e60009054906101000a900460ff16818054611ebe90613ba4565b80601f0160208091040260200160405190810160405280929190818152602001828054611eea90613ba4565b8015611f375780601f10611f0c57610100808354040283529160200191611f37565b820191906000526020600020905b815481529060010190602001808311611f1a57829003601f168201915b50505050509150945094509450945094509091929394565b6000805460001901611e2a90612710613c6e565b611f6e848484610ca4565b6001600160a01b0383163b15610f0b57611f8a84848484612a6f565b610f0b576040516368d2bf6b60e11b815260040160405180910390fd5b611faf612734565b6017546000818152600e6020908152604080832086845282528083208584528252808320938352600f9091529020600482015460ff166120025760405163d73251d760e01b815260040160405180910390fd5b600080835560018301819055600283018190556003830181905560048301805460ff1916905584815260208290526040812080549161204083613c85565b909155505060175460009081526010602090815260408083208784529091528120805490915b818110156120b3578583828154811061208157612081613b5d565b906000526020600020015414156120a15761209c8382612b67565b6120b3565b806120ab81613b89565b915050612066565b50600086815260208490526040902054610e2e575060125460005b8181101561211d5786601282815481106120ea576120ea613b5d565b9060005260206000200154141561210b57612106601282612b67565b61211d565b8061211581613b89565b9150506120ce565b50505050505050565b61212e613065565b612136613065565b600183108061214757506000548310155b156121525792915050565b61215b83612a4f565b905080604001511561216d5792915050565b610c9083612bdc565b6060612181826126e9565b61219e57604051634a1850bf60e11b815260040160405180910390fd5b601d80546121ab90613ba4565b151590506121c757505060408051602081019091526000815290565b604080516020810190915260008152601e5460ff16156121ff5750604080518082019091526005815264173539b7b760d91b60208201525b601d61220a84612bf5565b8260405160200161221d93929190613cb8565b604051602081830303815290604052915050919050565b612261858686604051602001611e4f92919091825260601b6001600160601b031916602082015260340190565b5050506000918252600d602052604090912060019055601e80546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6122a7612734565b601a805460ff19166001179055565b6122be612734565b80156122e657601980549060006122d483613b89565b909155506122e6905060156000612fc3565b6019546000908152601460205260408120905b8351811015610f0b57600084828151811061231657612316613b5d565b6020908102919091018101518082015181516000908152928690526040832055601554909250815b8181101561237a578351601580548390811061235c5761235c613b5d565b9060005260206000200154141561237257600192505b60010161233e565b50816123b6578251601580546001810182556000919091527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47501555b5050506001016122f9565b6001600160a01b0382166000818152600a6020908152604080832054601854845260138352818420601f5480865290845282852054601954865260148552838620888752855283862054878752600b86528487208388528652848720898852865284872054978752600c865284872089885286528487205483885260169096529386205495969295879591949392158061245b5750848110155b806124665750838210155b806124735750601c548710155b8061247e5750848110155b15612493576000975050505050505050610afd565b6017546000908152600e60209081526040808320601f54845282528083208c84529091529020600481015460ff16156124ce57806002015496505b8684106124e657600098505050505050505050610afd565b600088601c546124f69190613c6e565b90506000612504868a613c6e565b90506000612512858a613c6e565b90506000612520878a613c6e565b905061254e61254161253b612535878761271e565b8561271e565b8361271e565b612549611f4f565b61271e565b9f9e505050505050505050505050505050565b612569612734565b6001600160a01b0381166125d35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6125dc816129fd565b50565b601754600090815260106020908152604080832084845290915281208054606092816001600160401b0381111561261857612618613229565b604051908082528060200260200182016040528015612641578160200160208202803683370190505b50905060005b8281101561146e5783818154811061266157612661613b5d565b906000526020600020015482828151811061267e5761267e613b5d565b60209081029190910101528061269381613b89565b915050612647565b60006301ffc9a760e01b6001600160e01b0319831614806126cc57506380ac58cd60e01b6001600160e01b03198316145b80610afd5750506001600160e01b031916635b5e139f60e01b1490565b6000816001111580156126fd575060005482105b8015610afd575050600090815260046020526040902054600160e01b161590565b600081831061272d5781610c90565b5090919050565b6008546001600160a01b03163314610fce5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016125ca565b600081806001116127de576000548110156127de57600081815260046020526040902054600160e01b81166127dc575b80610c905750600019016000818152600460205260409020546127be565b505b604051636f96cda160e11b815260040160405180910390fd5b8154600090815b81811015612847578385828154811061281957612819613b5d565b9060005260206000200154141561283557600192505050610afd565b8061283f81613b89565b9150506127fe565b506000949350505050565b8061285b575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146128a8576040519150601f19603f3d011682016040523d82523d6000602084013e6128ad565b606091505b505090508061121f576040516328316c4d60e11b815260040160405180910390fd5b600081116128f05760405163162908e360e11b815260040160405180910390fd5b806128f9611f4f565b10156125dc5760405163671317e960e11b815260040160405180910390fd5b610feb828260405180602001604052806000815250612c91565b600260095414156129855760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016125ca565b6002600955565b6000858152600d6020526040902054156129b95760405163256f5cdd60e11b815260040160405180910390fd5b601e5461010090046001600160a01b03166129d685858585612cf7565b6001600160a01b031614610f5457604051638baa579f60e01b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612a57613065565b600082815260046020526040902054610afd90612db1565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290612aa4903390899088908890600401613d69565b602060405180830381600087803b158015612abe57600080fd5b505af1925050508015612aee575060408051601f3d908101601f19168201909252612aeb91810190613d9c565b60015b612b49573d808015612b1c576040519150601f19603f3d011682016040523d82523d6000602084013e612b21565b606091505b508051612b41576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b81548290612b7790600190613c6e565b81548110612b8757612b87613b5d565b9060005260206000200154828281548110612ba457612ba4613b5d565b906000526020600020018190555081805480612bc257612bc2613db9565b600190038181906000526020600020016000905590555050565b612be4613065565b610afd612bf08361278e565b612db1565b60606000612c0283612df4565b60010190506000816001600160401b03811115612c2157612c21613229565b6040519080825280601f01601f191660200182016040528015612c4b576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612c8457612c89565b612c55565b509392505050565b612c9b8383612ecc565b6001600160a01b0383163b1561121f576000548281035b612cc56000868380600101945086612a6f565b612ce2576040516368d2bf6b60e11b815260040160405180910390fd5b818110612cb2578160005414610f5457600080fd5b600060018580519060200120604051602001612d3f91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b60408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015612d9d573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b612db9613065565b6001600160a01b03821681526001600160401b0360a083901c166020820152600160e01b82161515604082015260e89190911c606082015290565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612e335772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612e5f576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612e7d57662386f26fc10000830492506010015b6305f5e1008310612e95576305f5e100830492506008015b6127108310612ea957612710830492506004015b60648310612ebb576064830492506002015b600a8310610afd5760010192915050565b60005481612eed5760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b818114612f9c57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600101612f64565b5081612fba57604051622e076360e81b815260040160405180910390fd5b60005550505050565b50805460008255906000526020600020908101906125dc919061308c565b828054612fed90613ba4565b90600052602060002090601f01602090048101928261300f5760008555613055565b82601f1061302857805160ff1916838001178555613055565b82800160010185558215613055579182015b8281111561305557825182559160200191906001019061303a565b5061306192915061308c565b5090565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b80821115613061576000815560010161308d565b602080825282518282018190526000919060409081850190868401855b828110156130e3578151805185528601518685015292840192908501906001016130be565b5091979650505050505050565b6001600160e01b0319811681146125dc57600080fd5b60006020828403121561311857600080fd5b8135610c90816130f0565b60005b8381101561313e578181015183820152602001613126565b83811115610f0b5750506000910152565b60008151808452613167816020860160208601613123565b601f01601f19169290920160200192915050565b602081526000610c90602083018461314f565b6000602082840312156131a057600080fd5b5035919050565b80356001600160a01b03811681146131be57600080fd5b919050565b600080604083850312156131d657600080fd5b6131df836131a7565b946020939093013593505050565b60008060006060848603121561320257600080fd5b61320b846131a7565b9250613219602085016131a7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561326157613261613229565b60405290565b604051608081016001600160401b038111828210171561326157613261613229565b604051601f8201601f191681016001600160401b03811182821017156132b1576132b1613229565b604052919050565b60006001600160401b038211156132d2576132d2613229565b5060051b60200190565b600082601f8301126132ed57600080fd5b813560206133026132fd836132b9565b613289565b82815260069290921b8401810191818101908684111561332157600080fd5b8286015b84811015613360576040818903121561333e5760008081fd5b61334661323f565b813581528482013585820152835291830191604001613325565b509695505050505050565b80151581146125dc57600080fd5b6000806040838503121561338c57600080fd5b82356001600160401b038111156133a257600080fd5b6133ae858286016132dc565b92505060208301356133bf8161336b565b809150509250929050565b600082601f8301126133db57600080fd5b813560206133eb6132fd836132b9565b82815260059290921b8401810191818101908684111561340a57600080fd5b8286015b84811015613360578035835291830191830161340e565b60006001600160401b0383111561343e5761343e613229565b613451601f8401601f1916602001613289565b905082815283838301111561346557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261348d57600080fd5b610c9083833560208501613425565b600080600080608085870312156134b257600080fd5b6134bb856131a7565b93506134c9602086016131a7565b925060408501356001600160401b03808211156134e557600080fd5b6134f1888389016133ca565b9350606087013591508082111561350757600080fd5b506135148782880161347c565b91505092959194509250565b600082601f83011261353157600080fd5b813560206135416132fd836132b9565b82815260079290921b8401810191818101908684111561356057600080fd5b8286015b84811015613360576080818903121561357d5760008081fd5b613585613267565b8135815284820135858201526040808301359082015260608083013590820152835291830191608001613564565b60008060008060008060c087890312156135cc57600080fd5b86356001600160401b03808211156135e357600080fd5b6135ef8a838b01613520565b9750602089013591506136018261336b565b9095506040880135908082111561361757600080fd5b6136238a838b016132dc565b9550606089013591506136358261336b565b9093506080880135908082111561364b57600080fd5b5061365889828a016132dc565b92505060a08701356136698161336b565b809150509295509295509295565b602080825282518282018190526000919060409081850190868401855b828110156130e357815180518552868101518786015285810151868601526060908101519085015260809093019290850190600101613694565b600080604083850312156136e157600080fd5b82356001600160401b038111156136f757600080fd5b6133ae85828601613520565b60006020828403121561371557600080fd5b81356001600160401b0381111561372b57600080fd5b8201601f8101841361373c57600080fd5b612b5f84823560208401613425565b6000806020838503121561375e57600080fd5b82356001600160401b038082111561377557600080fd5b818501915085601f83011261378957600080fd5b81358181111561379857600080fd5b8660208260051b85010111156137ad57600080fd5b60209290920196919550909350505050565b80516001600160a01b031682526020808201516001600160401b03169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b81811015611acf5761382a8385516137bf565b9284019260809290920191600101613817565b803560ff811681146131be57600080fd5b600080600080600080600080610100898b03121561386b57600080fd5b88359750602089013596506040890135955061388960608a016131a7565b94506080890135935061389e60a08a0161383d565b925060c0890135915060e089013590509295985092959890939650565b6000602082840312156138cd57600080fd5b8135610c908161336b565b6000602082840312156138ea57600080fd5b610c90826131a7565b6020808252825182820181905260009190848201906040850190845b81811015611acf5783518352928401929184019160010161390f565b60008060006060848603121561394057600080fd5b613949846131a7565b9250613957602085016131a7565b915060408401356001600160401b0381111561397257600080fd5b61397e868287016133ca565b9150509250925092565b60008060006060848603121561399d57600080fd5b6139a6846131a7565b95602085013595506040909401359392505050565b600080604083850312156139ce57600080fd5b6139d7836131a7565b915060208301356133bf8161336b565b600080600080600060a086880312156139ff57600080fd5b8535945060208601359350613a166040870161383d565b94979396509394606081013594506080013592915050565b851515815284602082015283604082015260a060608201526000613a5560a083018561314f565b905082151560808301529695505050505050565b60008060008060808587031215613a7f57600080fd5b613a88856131a7565b9350613a96602086016131a7565b92506040850135915060608501356001600160401b03811115613ab857600080fd5b6135148782880161347c565b60008060408385031215613ad757600080fd5b50508035926020909101359150565b60808101610afd82846137bf565b600080600080600060a08688031215613b0c57600080fd5b85359450613b1c602087016131a7565b9350613a166040870161383d565b60008060408385031215613b3d57600080fd5b613b46836131a7565b9150613b54602084016131a7565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415613b9d57613b9d613b73565b5060010190565b600181811c90821680613bb857607f821691505b60208210811415613bd957634e487b7160e01b600052602260045260246000fd5b50919050565b60008219821115613bf257613bf2613b73565b500190565b6000816000190483118215151615613c1157613c11613b73565b500290565b600082613c3357634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215613c4a57600080fd5b8151610c908161336b565b600060208284031215613c6757600080fd5b5051919050565b600082821015613c8057613c80613b73565b500390565b600081613c9457613c94613b73565b506000190190565b60008151613cae818560208601613123565b9290920192915050565b600080855481600182811c915080831680613cd457607f831692505b6020808410821415613cf457634e487b7160e01b86526022600452602486fd5b818015613d085760018114613d1957613d46565b60ff19861689528489019650613d46565b60008c81526020902060005b86811015613d3e5781548b820152908501908301613d25565b505084890196505b505050505050613d5f613d598287613c9c565b85613c9c565b9695505050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613d5f9083018461314f565b600060208284031215613dae57600080fd5b8151610c90816130f0565b634e487b7160e01b600052603160045260246000fdfea264697066735822122009c37dea9132af101e7da31ec87c2beba64ee47dfd1299d32be1c7fe14760f2364736f6c63430008090033
[ Download: CSV Export ]
[ 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.