ERC-721
Overview
Max Total Supply
500 EONFT
Holders
208
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 EONFTLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
EthernalOnes
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /** * @team : Asteria Labs * @author : Lambdalf the White */ pragma solidity 0.8.17; import 'EthereumContracts/contracts/interfaces/IArrayErrors.sol'; import 'EthereumContracts/contracts/interfaces/IEtherErrors.sol'; import 'EthereumContracts/contracts/interfaces/IERC721Errors.sol'; import 'EthereumContracts/contracts/interfaces/INFTSupplyErrors.sol'; import 'EthereumContracts/contracts/interfaces/IERC165.sol'; import 'EthereumContracts/contracts/interfaces/IERC721.sol'; import 'EthereumContracts/contracts/interfaces/IERC721Metadata.sol'; import 'EthereumContracts/contracts/interfaces/IERC721Enumerable.sol'; import 'EthereumContracts/contracts/interfaces/IERC721Receiver.sol'; import 'EthereumContracts/contracts/utils/ERC173.sol'; import 'EthereumContracts/contracts/utils/ContractState.sol'; import 'EthereumContracts/contracts/utils/Whitelist_ECDSA.sol'; import 'EthereumContracts/contracts/utils/ERC2981.sol'; import 'operator-filter-registry/src/UpdatableOperatorFilterer.sol'; contract EthernalOnes is IArrayErrors, IEtherErrors, IERC721Errors, INFTSupplyErrors, IERC165, IERC721, IERC721Metadata, IERC721Enumerable, ERC173, ContractState, Whitelist_ECDSA, ERC2981, UpdatableOperatorFilterer { // Errors error EO_PHASE_DEPLETED( uint8 currentPhase ); // Constants uint8 public constant PHASE1_SALE = 1; uint8 public constant PHASE2_SALE = 2; uint8 public constant PUBLIC_SALE = 3; address public constant DEFAULT_SUBSCRIPTION = address( 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6 ); address public constant DEFAULT_OPERATOR_FILTER_REGISTRY = address( 0x000000000000AAeB6D7670E522A718067333cd4E ); string public constant name = "Ethernal Ones - The Awakening"; string public constant symbol = "EONFT"; uint256 public constant MAX_BATCH = 2; // Private variables uint256 public maxSupply = 6666; uint256 private _nextId = 1; uint256 private _reserve = 50; address private _treasury; string private _baseURI = "ipfs://QmPcyrBaY65ZVWReFwkPXUQHGUjq4skCVhk5HfSx1FJoi7"; // Mapping from token ID to approved address mapping( uint256 => address ) private _approvals; // Mapping from owner to operator approvals mapping( address => mapping( address => bool ) ) private _operatorApprovals; // List of owner addresses mapping( uint256 => address ) private _owners; // Mapping from phase to sale price mapping( uint8 => uint256 ) private _salePrice; // Mapping from phase to max supply mapping( uint8 => uint256 ) private _maxPhase; constructor() UpdatableOperatorFilterer( DEFAULT_OPERATOR_FILTER_REGISTRY, DEFAULT_SUBSCRIPTION, true ) { _salePrice[ PHASE1_SALE ] = 59000000000000000; // 0.059 ether _salePrice[ PHASE2_SALE ] = 79000000000000000; // 0.079 ether _salePrice[ PUBLIC_SALE ] = 89000000000000000; // 0.089 ether _maxPhase[ PHASE1_SALE ] = 2999; _maxPhase[ PHASE2_SALE ] = 5665; _treasury = 0x2b1076BF95DA326441e5bf81A1d0357b10bDb933; _setOwner( msg.sender ); _setRoyaltyInfo( 0x4F440081A1c6a94cA5Fa5fEcc31bceC5bba62691, 500 ); _setWhitelist( 0x7df36A44FcA36F05A6fbF74B7cBdd9B43349e37F ); } // ************************************** // ***** MODIFIER ***** // ************************************** /** * @dev Ensures the token exist. * A token exists if it has been minted and is not owned by the null address. * * @param tokenId_ : identifier of the NFT being referenced */ modifier exists( uint256 tokenId_ ) { if ( ! _exists( tokenId_ ) ) { revert IERC721_NONEXISTANT_TOKEN( tokenId_ ); } _; } /** * @dev Ensures that `qty_` is higher than 0 * * @param qty_ : the amount to validate */ modifier validateAmount( uint256 qty_ ) { if ( qty_ == 0 ) { revert NFT_INVALID_QTY(); } _; } /** * @dev Ensures that contract state is {PHASE1_SALE} or {PHASE2_SALE} */ modifier isWhitelist() { uint8 _currentState_ = getContractState(); if ( _currentState_ != PHASE1_SALE && _currentState_ != PHASE2_SALE ) { revert ContractState_INCORRECT_STATE( _currentState_ ); } _; } // ************************************** // ************************************** // ***** INTERNAL ***** // ************************************** // *********** // * IERC721 * // *********** /** * @dev Internal function returning the number of tokens in `userAddress_`'s account. * * @param userAddress_ : address that may own tokens * * @return uint256 : the number of tokens owned by `userAddress_` */ function _balanceOf( address userAddress_ ) internal view virtual returns ( uint256 ) { if ( userAddress_ == address( 0 ) ) { return 0; } uint256 _count_; address _currentTokenOwner_; uint256 _index_ = 1; while ( _index_ < _nextId ) { if ( _exists( _index_ ) ) { if ( _owners[ _index_ ] != address( 0 ) ) { _currentTokenOwner_ = _owners[ _index_ ]; } if ( userAddress_ == _currentTokenOwner_ ) { unchecked { ++_count_; } } } unchecked { ++_index_; } } return _count_; } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param fromAddress_ : previous owner of the NFT * @param toAddress_ : new owner of the NFT * @param tokenId_ : identifier of the NFT being transferred * @param data_ : optional data to send along with the call * @return bool : whether the call correctly returned the expected value (IERC721Receiver.onERC721Received.selector) */ function _checkOnERC721Received( address fromAddress_, address toAddress_, uint256 tokenId_, bytes memory data_ ) internal virtual returns ( bool ) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. // // IMPORTANT // It is unsafe to assume that an address not flagged by this method // is an externally-owned account (EOA) and not a contract. // // Among others, the following types of addresses will not be flagged: // // - an externally-owned account // - a contract in construction // - an address where a contract will be created // - an address where a contract lived, but was destroyed uint256 _size_; assembly { _size_ := extcodesize( toAddress_ ) } // If address is a contract, check that it is aware of how to handle ERC721 tokens if ( _size_ > 0 ) { try IERC721Receiver( toAddress_ ).onERC721Received( msg.sender, fromAddress_, tokenId_, data_ ) returns ( bytes4 retval ) { return retval == IERC721Receiver.onERC721Received.selector; } catch ( bytes memory reason ) { if ( reason.length == 0 ) { revert IERC721_NON_ERC721_RECEIVER( toAddress_ ); } else { assembly { revert( add( 32, reason ), mload( reason ) ) } } } } else { return true; } } /** * @dev Internal function returning whether a token exists. * A token exists if it has been minted and is not owned by the null address. * * @param tokenId_ : identifier of the NFT to verify * * @return bool : whether the NFT exists */ function _exists( uint256 tokenId_ ) internal view virtual returns ( bool ) { if ( tokenId_ == 0 ) { return false; } return tokenId_ < _nextId; } /** * @dev Internal function returning whether `operator_` is allowed * to manage tokens on behalf of `tokenOwner_`. * * @param tokenOwner_ : address that owns tokens * @param operator_ : address that tries to manage tokens * * @return bool : whether `operator_` is allowed to handle the token */ function _isApprovedForAll( address tokenOwner_, address operator_ ) internal view virtual returns ( bool ) { return _operatorApprovals[ tokenOwner_ ][ operator_ ]; } /** * @dev Internal function returning whether `operator_` is allowed to handle `tokenId_` * * Note: To avoid multiple checks for the same data, it is assumed that existence of `tokenId_` * has been verified prior via {_exists} * If it hasn't been verified, this function might panic * * @param tokenOwner_ : address that owns tokens * @param operator_ : address that tries to handle the token * @param tokenId_ : identifier of the NFT * * @return bool whether `operator_` is allowed to handle the token */ function _isApprovedOrOwner( address tokenOwner_, address operator_, uint256 tokenId_ ) internal view virtual returns ( bool ) { bool _isApproved_ = operator_ == tokenOwner_ || operator_ == _approvals[ tokenId_ ] || _isApprovedForAll( tokenOwner_, operator_ ); return _isApproved_; } /** * @dev Mints `qty_` tokens and transfers them to `toAddress_`. * * This internal function can be used to perform token minting. * * Emits one or more {Transfer} event. * * @param toAddress_ : address receiving the NFTs * @param qty_ : number of NFTs being minted */ function _mint( address toAddress_, uint256 qty_ ) internal virtual { uint256 _firstToken_ = _nextId; uint256 _nextStart_ = _firstToken_ + qty_; uint256 _lastToken_ = _nextStart_ - 1; _owners[ _firstToken_ ] = toAddress_; if ( _lastToken_ > _firstToken_ ) { _owners[ _lastToken_ ] = toAddress_; } _nextId = _nextStart_; if ( ! _checkOnERC721Received( address( 0 ), toAddress_, _firstToken_, "" ) ) { revert IERC721_NON_ERC721_RECEIVER( toAddress_ ); } while ( _firstToken_ < _nextStart_ ) { emit Transfer( address( 0 ), toAddress_, _firstToken_ ); unchecked { _firstToken_ ++; } } } /** * @dev Internal function returning the owner of the `tokenId_` token. * * @param tokenId_ : identifier of the NFT * * @return : address that owns the NFT */ function _ownerOf( uint256 tokenId_ ) internal view virtual returns ( address ) { uint256 _tokenId_ = tokenId_; address _tokenOwner_ = _owners[ _tokenId_ ]; while ( _tokenOwner_ == address( 0 ) ) { _tokenId_ --; _tokenOwner_ = _owners[ _tokenId_ ]; } return _tokenOwner_; } /** * @dev Transfers `tokenId_` from `fromAddress_` to `toAddress_`. * * This internal function can be used to implement alternative mechanisms to perform * token transfer, such as signature-based, or token burning. * * @param fromAddress_ : previous owner of the NFT * @param toAddress_ : new owner of the NFT * @param tokenId_ : identifier of the NFT being transferred * * Emits a {Transfer} event. */ function _transfer( address fromAddress_, address toAddress_, uint256 tokenId_ ) internal virtual { _approvals[ tokenId_ ] = address( 0 ); uint256 _previousId_ = tokenId_ > 1 ? tokenId_ - 1 : 1; uint256 _nextId_ = tokenId_ + 1; bool _previousShouldUpdate_ = _previousId_ < tokenId_ && _exists( _previousId_ ) && _owners[ _previousId_ ] == address( 0 ); bool _nextShouldUpdate_ = _exists( _nextId_ ) && _owners[ _nextId_ ] == address( 0 ); if ( _previousShouldUpdate_ ) { _owners[ _previousId_ ] = fromAddress_; } if ( _nextShouldUpdate_ ) { _owners[ _nextId_ ] = fromAddress_; } _owners[ tokenId_ ] = toAddress_; emit Transfer( fromAddress_, toAddress_, tokenId_ ); } // *********** // ********************* // * IERC721Enumerable * // ********************* /** * @dev See {IERC721Enumerable-totalSupply}. */ function _totalSupply() internal view virtual returns ( uint256 ) { uint256 _supplyMinted_ = supplyMinted(); uint256 _count_ = _supplyMinted_; uint256 _index_ = _supplyMinted_; while ( _index_ > 0 ) { if ( ! _exists( _index_ ) ) { unchecked { _count_ --; } } unchecked { _index_ --; } } return _count_; } // ********************* // ******************* // * IERC721Metadata * // ******************* /** * @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 ) } } // ******************* // ************************************** // ************************************** // ***** PUBLIC ***** // ************************************** /** * @notice Mints `qty_` tokens and transfers them to the caller. * * @param qty_ : the amount of tokens to be minted * @param alloted_ : the maximum alloted for that user * @param proof_ : the signature to verify whitelist allocation * * Requirements: * * - Sale state must be {PHASE1_SALE or PHASE2_SALE}. * - Caller must send enough ether to pay for `qty_` tokens at private sale price. */ function mintPrivate( uint256 qty_, uint256 alloted_, Proof memory proof_ ) public payable validateAmount( qty_ ) isWhitelist isWhitelisted( msg.sender, PHASE1_SALE, alloted_, proof_, qty_ ) { uint8 _currentState_ = getContractState(); if ( qty_ + supplyMinted() > _maxPhase[ _currentState_ ] ) { revert EO_PHASE_DEPLETED( _currentState_ ); } uint256 _expected_ = qty_ * _salePrice[ _currentState_ ]; if ( _expected_ != msg.value ) { revert ETHER_INCORRECT_PRICE( msg.value, _expected_ ); } _mint( msg.sender, qty_ ); _consumeWhitelist( msg.sender, PHASE1_SALE, qty_ ); } /** * @notice Mints `qty_` tokens and transfers them to the caller. * * @param qty_ : the amount of tokens to be minted * * Requirements: * * - Sale state must be {PUBLIC_SALE}. * - There must be enough tokens left to mint outside of the reserve. * - Caller must send enough ether to pay for `qty_` tokens at public sale price. */ function mintPublic( uint256 qty_ ) public payable validateAmount( qty_ ) isState( PUBLIC_SALE ) { if ( qty_ > MAX_BATCH ) { revert NFT_MAX_BATCH( qty_, MAX_BATCH ); } uint256 _remainingSupply_ = maxSupply - _reserve - supplyMinted(); if ( qty_ > _remainingSupply_ ) { revert NFT_MAX_SUPPLY( qty_, _remainingSupply_ ); } uint256 _expected_ = qty_ * _salePrice[ PUBLIC_SALE ]; if ( _expected_ != msg.value ) { revert ETHER_INCORRECT_PRICE( msg.value, _expected_ ); } _mint( msg.sender, qty_ ); } // *********** // * IERC721 * // *********** /** * @dev See {IERC721-approve}. */ function approve( address to_, uint256 tokenId_ ) public virtual exists( tokenId_ ) onlyAllowedOperatorApproval( msg.sender ) { address _operator_ = msg.sender; address _tokenOwner_ = _ownerOf( tokenId_ ); if ( to_ == _tokenOwner_ ) { revert IERC721_INVALID_APPROVAL( to_ ); } bool _isApproved_ = _isApprovedOrOwner( _tokenOwner_, _operator_, tokenId_ ); if ( ! _isApproved_ ) { revert IERC721_CALLER_NOT_APPROVED( _tokenOwner_, _operator_, tokenId_ ); } _approvals[ tokenId_ ] = to_; emit Approval( _tokenOwner_, to_, tokenId_ ); } /** * @dev See {IERC721-safeTransferFrom}. * * Note: We can ignore `from_` as we can compare everything to the actual token owner, * but we cannot remove this parameter to stay in conformity with IERC721 */ function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) public virtual override { safeTransferFrom( from_, to_, tokenId_, "" ); } /** * @dev See {IERC721-safeTransferFrom}. * * Note: We can ignore `from_` as we can compare everything to the actual token owner, * but we cannot remove this parameter to stay in conformity with IERC721 */ function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes memory data_ ) public virtual override { transferFrom( from_, to_, tokenId_ ); if ( ! _checkOnERC721Received( from_, to_, tokenId_, data_ ) ) { revert IERC721_NON_ERC721_RECEIVER( to_ ); } } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll( address operator_, bool approved_ ) public virtual override onlyAllowedOperatorApproval( msg.sender ) { address _account_ = msg.sender; if ( operator_ == _account_ ) { revert IERC721_INVALID_APPROVAL( operator_ ); } _operatorApprovals[ _account_ ][ operator_ ] = approved_; emit ApprovalForAll( _account_, operator_, approved_ ); } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from_, address to_, uint256 tokenId_ ) public virtual exists( tokenId_ ) onlyAllowedOperator( msg.sender ) { if ( to_ == address( 0 ) ) { revert IERC721_INVALID_TRANSFER(); } address _operator_ = msg.sender; address _tokenOwner_ = _ownerOf( tokenId_ ); if ( from_ != _tokenOwner_ ) { revert IERC721_INVALID_TRANSFER_FROM( _tokenOwner_, from_, tokenId_ ); } bool _isApproved_ = _isApprovedOrOwner( _tokenOwner_, _operator_, tokenId_ ); if ( ! _isApproved_ ) { revert IERC721_CALLER_NOT_APPROVED( _tokenOwner_, _operator_, tokenId_ ); } _transfer( _tokenOwner_, to_, tokenId_ ); } // *********** // ************************************** // ************************************** // ***** CONTRACT_OWNER ***** // ************************************** /** * @notice Mints `amounts_` tokens and transfers them to `accounts_`. * * @param accounts_ : the list of accounts that will receive airdropped tokens * @param amounts_ : the amount of tokens each account will receive * * Requirements: * * - Caller must be the contract owner. * - `accounts_` and `amounts_` must have the same length. * - There must be enough tokens left in the reserve. */ function airdrop( address[] memory accounts_, uint256[] memory amounts_ ) public onlyOwner { uint256 _count_ = accounts_.length; if ( _count_ != amounts_.length ) { revert ARRAY_LENGTH_MISMATCH(); } uint256 _totalQty_; while ( _count_ > 0 ) { unchecked { --_count_; } _totalQty_ += amounts_[ _count_ ]; _mint( accounts_[ _count_ ], amounts_[ _count_ ] ); } if ( _totalQty_ > _reserve ) { revert NFT_MAX_RESERVE( _totalQty_, _reserve ); } unchecked { _reserve -= _totalQty_; } } /** * @notice Reduces the max supply. * * @param newMaxSupply_ : the new max supply * * Requirements: * * - Caller must be the contract owner. * - `newMaxSupply_` must be lower than `maxSupply`. * - `newMaxSupply_` must be higher than `_nextId`. */ function reduceSupply( uint256 newMaxSupply_ ) public onlyOwner { if ( newMaxSupply_ > maxSupply || newMaxSupply_ < _nextId + _reserve ) { revert NFT_INVALID_SUPPLY(); } maxSupply = newMaxSupply_; } /** * @notice Updates the baseURI for the tokens. * * @param newBaseURI_ : the new baseURI for the tokens * * Requirements: * * - Caller must be the contract owner. */ function setBaseURI( string memory newBaseURI_ ) public onlyOwner { _baseURI = newBaseURI_; } /** * @notice Updates the contract state. * * @param newState_ : the new sale state * * Requirements: * * - Caller must be the contract owner. * - `newState_` must be a valid state. */ function setContractState( uint8 newState_ ) external onlyOwner { if ( newState_ > PUBLIC_SALE ) { revert ContractState_INVALID_STATE( newState_ ); } _setContractState( newState_ ); } /** * @notice Updates the royalty recipient and rate. * * @param newRoyaltyRecipient_ : the new recipient of the royalties * @param newRoyaltyRate_ : the new royalty rate * * Requirements: * * - Caller must be the contract owner. * - `newRoyaltyRate_` cannot be higher than 10,000. */ function setRoyaltyInfo( address newRoyaltyRecipient_, uint256 newRoyaltyRate_ ) external onlyOwner { _setRoyaltyInfo( newRoyaltyRecipient_, newRoyaltyRate_ ); } /** * @notice Updates the royalty recipient and rate. * * @param newPhase1Price_ : the new phase 1 price * @param newPhase2Price_ : the new phase 2 price * @param newPublicPrice_ : the new public price * * Requirements: * * - Caller must be the contract owner. */ function setPrices( uint256 newPhase1Price_, uint256 newPhase2Price_, uint256 newPublicPrice_ ) external onlyOwner { _salePrice[ PHASE1_SALE ] = newPhase1Price_; _salePrice[ PHASE2_SALE ] = newPhase2Price_; _salePrice[ PUBLIC_SALE ] = newPublicPrice_; } /** * @notice Updates the contract treasury. * * @param newTreasury_ : the new trasury * * Requirements: * * - Caller must be the contract owner. */ function setTreasury( address newTreasury_ ) external onlyOwner { _treasury = newTreasury_; } /** * @notice Updates the whitelist signer. * * @param newAdminSigner_ : the new whitelist signer * * Requirements: * * - Caller must be the contract owner. */ function setWhitelist( address newAdminSigner_ ) external onlyOwner { _setWhitelist( newAdminSigner_ ); } /** * @notice Withdraws all the money stored in the contract and sends it to the treasury. * * Requirements: * * - Caller must be the contract owner. * - `_treasury` must be able to receive the funds. * - Contract must have a positive balance. */ function withdraw() public onlyOwner { uint256 _balance_ = address( this ).balance; if ( _balance_ == 0 ) { revert ETHER_NO_BALANCE(); } address _recipient_ = payable( _treasury ); ( bool _success_, ) = _recipient_.call{ value: _balance_ }( "" ); if ( ! _success_ ) { revert ETHER_TRANSFER_FAIL( _recipient_, _balance_ ); } } // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /** * @notice Returns the current sale price * * @return uint256 the current sale price */ function salePrice() public view returns ( uint256 ) { return _salePrice[ getContractState() ]; } /** * @notice Returns the total number of tokens minted * * @return uint256 the number of tokens that have been minted so far */ function supplyMinted() public view returns ( uint256 ) { return _nextId - 1; } // *********** // * IERC721 * // *********** /** * @dev See {IERC721-balanceOf}. */ function balanceOf( address tokenOwner_ ) public view virtual returns ( uint256 ) { return _balanceOf( tokenOwner_ ); } /** * @dev See {IERC721-getApproved}. */ function getApproved( uint256 tokenId_ ) public view virtual exists( tokenId_ ) returns ( address ) { return _approvals[ tokenId_ ]; } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll( address tokenOwner_, address operator_ ) public view virtual returns ( bool ) { return _isApprovedForAll( tokenOwner_, operator_ ); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf( uint256 tokenId_ ) public view virtual exists( tokenId_ ) returns ( address ) { return _ownerOf( tokenId_ ); } // *********** // ********************* // * IERC721Enumerable * // ********************* /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex( uint256 index_ ) public view virtual override returns ( uint256 ) { if ( index_ >= supplyMinted() ) { revert IERC721Enumerable_INDEX_OUT_OF_BOUNDS( index_ ); } return index_ + 1; } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex( address tokenOwner_, uint256 index_ ) public view virtual override returns ( uint256 tokenId ) { if ( index_ >= _balanceOf( tokenOwner_ ) ) { revert IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS( tokenOwner_, index_ ); } uint256 _count_ = 0; uint256 _nextId_ = supplyMinted(); for ( uint256 i = 1; i < _nextId_; i++ ) { if ( _exists( i ) && tokenOwner_ == _ownerOf( i ) ) { if ( index_ == _count_ ) { return i; } _count_++; } } } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns ( uint256 ) { return _totalSupply(); } // ********************* // ******************* // * IERC721Metadata * // ******************* /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI( uint256 tokenId_ ) public view virtual override exists( tokenId_ ) returns ( string memory ) { if ( bytes( _baseURI ).length > 0 ) { if ( supplyMinted() == maxSupply ) { return string( abi.encodePacked( _baseURI, _toString( tokenId_ ) ) ); } else { return _baseURI; } } return _toString( tokenId_ ); } // ******************* // *********** // * IERC165 * // *********** /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface( bytes4 interfaceId_ ) public view override returns ( bool ) { return interfaceId_ == type( IERC721 ).interfaceId || interfaceId_ == type( IERC721Enumerable ).interfaceId || interfaceId_ == type( IERC721Metadata ).interfaceId || interfaceId_ == type( IERC173 ).interfaceId || interfaceId_ == type( IERC165 ).interfaceId || interfaceId_ == type( IERC2981 ).interfaceId; } // *********** // *********** // * IERC173 * // *********** function owner() public view override(ERC173, UpdatableOperatorFilterer) returns ( address ) { return ERC173.owner(); } // *********** }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; interface IArrayErrors { /** * @dev Thrown when two related arrays have different lengths */ error ARRAY_LENGTH_MISMATCH(); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IERC165 { /// @notice Query if a contract implements an interface /// @param interfaceID The interface identifier, as specified in ERC-165 /// @dev Interface identification is specified in ERC-165. This function /// uses less than 30,000 gas. /// @return `true` if the contract implements `interfaceID` and /// `interfaceID` is not 0xffffffff, `false` otherwise function supportsInterface(bytes4 interfaceID) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /** * @dev Required interface of an ERC173 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-173[EIP]. */ interface IERC173 /* is IERC165 */ { /// @dev This emits when ownership of a contract changes. event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /// @notice Get the address of the owner /// @return The address of the owner. function owner() view external returns(address); /// @notice Set the address of the new owner of the contract /// @dev Set _newOwner to address(0) to renounce any ownership. /// @param _newOwner The address of the new owner of the contract function transferOwnership(address _newOwner) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// /// @dev Interface for the NFT Royalty Standard /// interface IERC2981 /* is IERC165 */ { /// ERC165 bytes to add to interface array - set in parent contract /// implementing this standard /// /// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a /// bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a; /// _registerInterface(_INTERFACE_ID_ERC2981); /// @notice Called with the sale price to determine how much royalty // is owed and to whom. /// @param tokenId_ - the NFT asset queried for royalty information /// @param salePrice_ - the sale price of the NFT asset specified by tokenId_ /// @return receiver - address of who should be sent the royalty payment /// @return royaltyAmount - the royalty payment amount for salePrice_ function royaltyInfo( uint256 tokenId_, uint256 salePrice_ ) external view returns ( address receiver, uint256 royaltyAmount ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity 0.8.17; /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x80ac58cd. interface IERC721 /* is IERC165 */ { /// @dev This emits when ownership of any NFT changes by any mechanism. /// This event emits when NFTs are created (`from` == 0) and destroyed /// (`to` == 0). Exception: during contract creation, any number of NFTs /// may be created and assigned without emitting Transfer. At the time of /// any transfer, the approved address for that NFT (if any) is reset to none. event Transfer( address indexed from_, address indexed to_, uint256 indexed tokenId_ ); /// @dev This emits when the approved address for an NFT is changed or /// reaffirmed. The zero address indicates there is no approved address. /// When a Transfer event emits, this also indicates that the approved /// address for that NFT (if any) is reset to none. event Approval( address indexed owner_, address indexed approved_, uint256 indexed tokenId_ ); /// @dev This emits when an operator is enabled or disabled for an owner. /// The operator can manage all NFTs of the owner. event ApprovalForAll( address indexed owner_, address indexed operator_, bool approved_ ); /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this /// function throws for queries about the zero address. /// @param owner_ An address for whom to query the balance /// @return The number of NFTs owned by `owner_`, possibly zero function balanceOf( address owner_ ) external view returns ( uint256 ); /// @notice Find the owner of an NFT /// @dev NFTs assigned to zero address are considered invalid, and queries /// about them do throw. /// @param tokenId_ The identifier for an NFT /// @return The address of the owner of the NFT function ownerOf( uint256 tokenId_ ) external view returns ( address ); /// @notice Transfers the ownership of an NFT from one address to another address /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `from_` is /// not the current owner. Throws if `to_` is the zero address. Throws if /// `tokenId_` is not a valid NFT. When transfer is complete, this function /// checks if `to_` is a smart contract (code size > 0). If so, it calls /// `onERC721Received` on `to_` and throws if the return value is not /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. /// @param from_ The current owner of the NFT /// @param to_ The new owner /// @param tokenId_ The NFT to transfer /// @param data_ Additional data with no specified format, sent in call to `to_` function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes calldata data_ ) external; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, /// except this function just sets data to "". /// @param from_ The current owner of the NFT /// @param to_ The new owner /// @param tokenId_ The NFT to transfer function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) external; /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE /// TO CONFIRM THAT `to_` IS CAPABLE OF RECEIVING NFTS OR ELSE /// THEY MAY BE PERMANENTLY LOST /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `from_` is /// not the current owner. Throws if `to_` is the zero address. Throws if /// `tokenId_` is not a valid NFT. /// @param from_ The current owner of the NFT /// @param to_ The new owner /// @param tokenId_ The NFT to transfer function transferFrom( address from_, address to_, uint256 tokenId_ ) external; /// @notice Change or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. /// Throws unless `msg.sender` is the current NFT owner, or an authorized /// operator of the current owner. /// @param approved_ The new approved NFT controller /// @param tokenId_ The NFT to approve function approve( address approved_, uint256 tokenId_ ) external; /// @notice Enable or disable approval for a third party ("operator") to manage /// all of `msg.sender`'s assets /// @dev Emits the ApprovalForAll event. The contract MUST allow /// multiple operators per owner. /// @param operator_ Address to add to the set of authorized operators /// @param approved_ True if the operator is approved, false to revoke approval function setApprovalForAll( address operator_, bool approved_ ) external; /// @notice Get the approved address for a single NFT /// @dev Throws if `tokenId_` is not a valid NFT. /// @param tokenId_ The NFT to find the approved address for /// @return The approved address for this NFT, or the zero address if there is none function getApproved( uint256 tokenId_ ) external view returns ( address ); /// @notice Query if an address is an authorized operator for another address /// @param owner_ The address that owns the NFTs /// @param operator_ The address that acts on behalf of the owner /// @return True if `operator_` is an approved operator for `owner_`, false otherwise function isApprovedForAll( address owner_, address operator_ ) external view returns ( bool ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x780e9d63. interface IERC721Enumerable /* is IERC721 */ { /// @notice Count NFTs tracked by this contract /// @return A count of valid NFTs tracked by this contract, where each one of /// them has an assigned and queryable owner not equal to the zero address function totalSupply() external view returns ( uint256 ); /// @notice Enumerate valid NFTs /// @dev Throws if `index_` >= `totalSupply()`. /// @param index_ A counter less than `totalSupply()` /// @return The token identifier for the `index_`th NFT, /// (sort order not specified) function tokenByIndex( uint256 index_ ) external view returns ( uint256 ); /// @notice Enumerate NFTs assigned to an owner /// @dev Throws if `index_` >= `balanceOf(owner_)` or if /// `owner_` is the zero address, representing invalid NFTs. /// @param owner_ An address where we are interested in NFTs owned by them /// @param index_ A counter less than `balanceOf(owner_)` /// @return The token identifier for the `index_`th NFT assigned to `owner_`, /// (sort order not specified) function tokenOfOwnerByIndex( address owner_, uint256 index_ ) external view returns ( uint256 ); }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; interface IERC721Errors { /** * @dev Thrown when `operator` has not been approved to manage `tokenId` on behalf of `tokenOwner`. * * @param tokenOwner : address owning the token * @param operator : address trying to manage the token * @param tokenId : identifier of the NFT being referenced */ error IERC721_CALLER_NOT_APPROVED( address tokenOwner, address operator, uint256 tokenId ); /** * @dev Thrown when `operator` tries to approve themselves for managing a token they own. * * @param operator : address that is trying to approve themselves */ error IERC721_INVALID_APPROVAL( address operator ); /** * @dev Thrown when a token is being transferred to the zero address. */ error IERC721_INVALID_TRANSFER(); /** * @dev Thrown when a token is being transferred from an address that doesn't own it. * * @param tokenOwner : address owning the token * @param from : address that the NFT is being transferred from * @param tokenId : identifier of the NFT being referenced */ error IERC721_INVALID_TRANSFER_FROM( address tokenOwner, address from, uint256 tokenId ); /** * @dev Thrown when the requested token doesn't exist. * * @param tokenId : identifier of the NFT being referenced */ error IERC721_NONEXISTANT_TOKEN( uint256 tokenId ); /** * @dev Thrown when a token is being safely transferred to a contract unable to handle it. * * @param receiver : address unable to receive the token */ error IERC721_NON_ERC721_RECEIVER( address receiver ); /** * @dev Thrown when trying to get the token at an index that doesn't exist. * * @param index : the inexistant index */ error IERC721Enumerable_INDEX_OUT_OF_BOUNDS( uint256 index ); /** * @dev Thrown when trying to get the token owned by `tokenOwner` at an index that doesn't exist. * * @param tokenOwner : address owning the token * @param index : the inexistant index */ error IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS( address tokenOwner, uint256 index ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x5b5e139f. interface IERC721Metadata /* is IERC721 */ { /// @notice A descriptive name for a collection of NFTs in this contract function name() external view returns ( string memory _name ); /// @notice An abbreviated name for NFTs in this contract function symbol() external view returns ( string memory _symbol ); /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC /// 3986. The URI may point to a JSON file that conforms to the "ERC721 /// Metadata JSON Schema". function tokenURI( uint256 _tokenId ) external view returns ( string memory ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. interface IERC721Receiver { /// @notice Handle the receipt of an NFT /// @dev The ERC721 smart contract calls this function on the recipient /// after a `transfer`. This function MAY throw to revert and reject the /// transfer. Return of other than the magic value MUST result in the /// transaction being reverted. /// Note: the contract address is always the message sender. /// @param operator_ The address which called `safeTransferFrom` function /// @param from_ The address which previously owned the token /// @param tokenId_ The NFT identifier which is being transferred /// @param data_ Additional data with no specified format /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` /// unless throwing function onERC721Received( address operator_, address from_, uint256 tokenId_, bytes calldata data_ ) external returns( bytes4 ); }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; interface IEtherErrors { /** * @dev Thrown when an incorrect amount of eth is being sent for a payable operation. * * @param amountReceived : the amount the contract received * @param amountExpected : the actual amount the contract expected to receive */ error ETHER_INCORRECT_PRICE( uint256 amountReceived, uint256 amountExpected ); /** * @dev Thrown when trying to withdraw from the contract with no balance. */ error ETHER_NO_BALANCE(); /** * @dev Thrown when contract fails to send ether to recipient. * * @param to : the recipient of the ether * @param amount : the amount of ether being sent */ error ETHER_TRANSFER_FAIL( address to, uint256 amount ); }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; interface INFTSupplyErrors { /** * @dev Thrown when trying to mint 0 token. */ error NFT_INVALID_QTY(); /** * @dev Thrown when trying to set max supply to an invalid amount. */ error NFT_INVALID_SUPPLY(); /** * @dev Thrown when trying to mint more tokens than the max allowed per transaction. * * @param qtyRequested : the amount of tokens requested * @param maxBatch : the maximum amount that can be minted per transaction */ error NFT_MAX_BATCH( uint256 qtyRequested, uint256 maxBatch ); /** * @dev Thrown when trying to mint more tokens from the reserve than the amount left. * * @param qtyRequested : the amount of tokens requested * @param reserveLeft : the amount of tokens left in the reserve */ error NFT_MAX_RESERVE( uint256 qtyRequested, uint256 reserveLeft ); /** * @dev Thrown when trying to mint more tokens than the amount left to be minted (except reserve). * * @param qtyRequested : the amount of tokens requested * @param remainingSupply : the amount of tokens left in the reserve */ error NFT_MAX_SUPPLY( uint256 qtyRequested, uint256 remainingSupply ); }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; abstract contract ContractState { // Enum to represent the sale state, defaults to ``PAUSED``. uint8 public constant PAUSED = 0; // Errors /** * @dev Thrown when a function is called with the wrong contract state. * * @param currentState : the current state of the contract */ error ContractState_INCORRECT_STATE( uint8 currentState ); /** * @dev Thrown when trying to set the contract state to an invalid value. * * @param invalidState : the invalid contract state */ error ContractState_INVALID_STATE( uint8 invalidState ); // The current state of the contract uint8 private _contractState; /** * @dev Emitted when the sale state changes */ event ContractStateChanged( uint8 indexed previousState, uint8 indexed newState ); /** * @dev Ensures that contract state is `expectedState_`. * * @param expectedState_ : the desirable contract state */ modifier isState( uint8 expectedState_ ) { if ( _contractState != expectedState_ ) { revert ContractState_INCORRECT_STATE( _contractState ); } _; } /** * @dev Ensures that contract state is not `unexpectedState_`. * * @param unexpectedState_ : the undesirable contract state */ modifier isNotState( uint8 unexpectedState_ ) { if ( _contractState == unexpectedState_ ) { revert ContractState_INCORRECT_STATE( _contractState ); } _; } /** * @dev Internal function setting the contract state to `newState_`. * * Note: Contract state defaults to ``PAUSED``. * To maintain extendability, this value kept as uint8 instead of enum. * As a result, it is possible to set the state to an incorrect value. * To avoid issues, `newState_` should be validated before calling this function */ function _setContractState( uint8 newState_ ) internal virtual { uint8 _previousState_ = _contractState; _contractState = newState_; emit ContractStateChanged( _previousState_, newState_ ); } /** * @dev Returns the current contract state. * * @return uint8 : the current contract state */ function getContractState() public virtual view returns ( uint8 ) { return _contractState; } }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; import "../interfaces/IERC173.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract ERC173 is IERC173 { // Errors /** * @dev Thrown when `operator` is not the contract owner. * * @param operator : address trying to use a function reserved to contract owner without authorization */ error IERC173_NOT_OWNER( address operator ); // The owner of the contract address private _owner; /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { address _sender_ = msg.sender; if ( owner() != _sender_ ) { revert IERC173_NOT_OWNER( _sender_ ); } _; } /** * @dev Sets the contract owner. * * Note: This function needs to be called in the contract constructor to initialize the contract owner, * if it is not, then parts of the contract might be non functional * * @param owner_ : address that owns the contract */ function _setOwner( address owner_ ) internal { _owner = owner_; } /** * @dev Returns the address of the current contract owner. * * @return address : the current contract owner */ function owner() public view virtual returns ( address ) { return _owner; } /** * @dev Transfers ownership of the contract to `newOwner_`. * * @param newOwner_ : address of the new contract owner * * Requirements: * * - Caller must be the contract owner. */ function transferOwnership( address newOwner_ ) public virtual onlyOwner { address _oldOwner_ = _owner; _owner = newOwner_; emit OwnershipTransferred( _oldOwner_, newOwner_ ); } }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; import "../interfaces/IERC2981.sol"; abstract contract ERC2981 is IERC2981 { // Errors /** * @dev Thrown when the desired royalty rate is higher than 10,000 * * @param royaltyRate : the desired royalty rate * @param royaltyBase : the maximum royalty rate */ error IERC2981_INVALID_ROYALTIES( uint256 royaltyRate, uint256 royaltyBase ); // Royalty rate is stored out of 10,000 instead of a percentage to allow for // up to two digits below the unit such as 2.5% or 1.25%. uint private constant ROYALTY_BASE = 10000; // Represents the percentage of royalties on each sale on secondary markets. // Set to 0 to have no royalties. uint256 private _royaltyRate; // Address of the recipient of the royalties. address private _royaltyRecipient; /** * @notice Called with the sale price to determine how much royalty is owed and to whom. * * Note: This function should be overriden to revert on a query for non existent token. * * @param tokenId_ : identifier of the NFT being referenced * @param salePrice_ : the sale price of the token sold * * @return address : the address receiving the royalties * @return uint256 : the royalty payment amount */ function royaltyInfo( uint256 tokenId_, uint256 salePrice_ ) public view virtual override returns ( address, uint256 ) { if ( salePrice_ == 0 || _royaltyRate == 0 ) { return ( _royaltyRecipient, 0 ); } uint256 _royaltyAmount_ = _royaltyRate * salePrice_ / ROYALTY_BASE; return ( _royaltyRecipient, _royaltyAmount_ ); } /** * @dev Sets the royalty rate to `royaltyRate_` and the royalty recipient to `royaltyRecipient_`. * * @param royaltyRecipient_ : the address that will receive royalty payments * @param royaltyRate_ : the percentage of the sale price that will be taken off as royalties, expressed in Basis Points (100 BP = 1%) * * Requirements: * * - `royaltyRate_` cannot be higher than `10,000`; */ function _setRoyaltyInfo( address royaltyRecipient_, uint256 royaltyRate_ ) internal virtual { if ( royaltyRate_ > ROYALTY_BASE ) { revert IERC2981_INVALID_ROYALTIES( royaltyRate_, ROYALTY_BASE ); } _royaltyRate = royaltyRate_; _royaltyRecipient = royaltyRecipient_; } }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White * Edit : Squeebo */ pragma solidity 0.8.17; abstract contract Whitelist_ECDSA { // Errors /** * @dev Thrown when trying to query the whitelist while it's not set */ error Whitelist_NOT_SET(); /** * @dev Thrown when `account` has consumed their alloted access and tries to query more * * @param account : address trying to access the whitelist */ error Whitelist_CONSUMED( address account ); /** * @dev Thrown when `account` does not have enough alloted access to fulfil their query * * @param account : address trying to access the whitelist */ error Whitelist_FORBIDDEN( address account ); /** * @dev A structure representing a signature proof to be decoded by the contract */ struct Proof { bytes32 r; bytes32 s; uint8 v; } address private _adminSigner; mapping( uint8 => mapping ( address => uint256 ) ) private _consumed; /** * @dev Ensures that `account_` has `qty_` alloted access on the `whitelistId_` whitelist. * * @param account_ : the address to validate access * @param whitelistId_ : the identifier of the whitelist being queried * @param alloted_ : the max amount of whitelist spots allocated * @param proof_ : the signature proof to validate whitelist allocation * @param qty_ : the amount of whitelist access requested */ modifier isWhitelisted( address account_, uint8 whitelistId_, uint256 alloted_, Proof memory proof_, uint256 qty_ ) { uint256 _allowed_ = checkWhitelistAllowance( account_, whitelistId_, alloted_, proof_ ); if ( _allowed_ < qty_ ) { revert Whitelist_FORBIDDEN( account_ ); } _; } /** * @dev Sets the pass to protect the whitelist. * * @param adminSigner_ : the address validating the whitelist signatures */ function _setWhitelist( address adminSigner_ ) internal virtual { _adminSigner = adminSigner_; } /** * @dev Returns the amount that `account_` is allowed to access from the whitelist. * * @param account_ : the address to validate access * @param whitelistId_ : the identifier of the whitelist being queried * @param alloted_ : the max amount of whitelist spots allocated * @param proof_ : the signature proof to validate whitelist allocation * * @return uint256 : the total amount of whitelist allocation remaining for `account_` * * Requirements: * * - `_adminSigner` must be set. */ function checkWhitelistAllowance( address account_, uint8 whitelistId_, uint256 alloted_, Proof memory proof_ ) public view returns ( uint256 ) { if ( _adminSigner == address( 0 ) ) { revert Whitelist_NOT_SET(); } if ( _consumed[ whitelistId_ ][ account_ ] >= alloted_ ) { revert Whitelist_CONSUMED( account_ ); } if ( ! _validateProof( account_, whitelistId_, alloted_, proof_ ) ) { revert Whitelist_FORBIDDEN( account_ ); } return alloted_ - _consumed[ whitelistId_ ][ account_ ]; } /** * @dev Internal function to decode a signature and compare it with the `_adminSigner`. * * @param account_ : the address to validate access * @param whitelistId_ : the identifier of the whitelist being queried * @param alloted_ : the max amount of whitelist spots allocated * @param proof_ : the signature proof to validate whitelist allocation * * @return bool : whether the signature is valid or not */ function _validateProof( address account_, uint8 whitelistId_, uint256 alloted_, Proof memory proof_ ) private view returns ( bool ) { bytes32 _digest_ = keccak256( abi.encode( whitelistId_, alloted_, account_ ) ); address _signer_ = ecrecover( _digest_, proof_.v, proof_.r, proof_.s ); return _signer_ == _adminSigner; } /** * @dev Consumes `amount_` whitelist access passes from `account_`. * * @param account_ : the address to consume access from * @param whitelistId_ : the identifier of the whitelist being queried * @param qty_ : the amount of whitelist access consumed * * Note: Before calling this function, eligibility should be checked through {Whitelistable-checkWhitelistAllowance}. */ function _consumeWhitelist( address account_, uint8 whitelistId_, uint256 qty_ ) internal { unchecked { _consumed[ whitelistId_ ][ account_ ] += qty_; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; /** * @title UpdatableOperatorFilterer * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another * registrant's entries in the OperatorFilterRegistry. This contract allows the Owner to update the * OperatorFilterRegistry address via updateOperatorFilterRegistryAddress, including to the zero address, * which will bypass registry checks. * Note that OpenSea will still disable creator fee enforcement if filtered operators begin fulfilling orders * on-chain, eg, if the registry is revoked or bypassed. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. */ abstract contract UpdatableOperatorFilterer { error OperatorNotAllowed(address operator); error OnlyOwner(); IOperatorFilterRegistry public operatorFilterRegistry; constructor(address _registry, address subscriptionOrRegistrantToCopy, bool subscribe) { IOperatorFilterRegistry registry = IOperatorFilterRegistry(_registry); operatorFilterRegistry = registry; // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(registry).code.length > 0) { if (subscribe) { registry.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { registry.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { registry.register(address(this)); } } } } modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } /** * @notice Update the address that the contract will make OperatorFilter checks against. When set to the zero * address, checks will be bypassed. OnlyOwner. */ function updateOperatorFilterRegistryAddress(address newRegistry) public virtual { if (msg.sender != owner()) { revert OnlyOwner(); } operatorFilterRegistry = IOperatorFilterRegistry(newRegistry); } /** * @dev assume the contract has an owner, but leave specific Ownable implementation up to inheriting contract */ function owner() public view virtual returns (address); function _checkFilterOperator(address operator) internal view virtual { IOperatorFilterRegistry registry = operatorFilterRegistry; // Check registry code length to facilitate testing in environments without a deployed registry. if (address(registry) != address(0) && address(registry).code.length > 0) { if (!registry.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ARRAY_LENGTH_MISMATCH","type":"error"},{"inputs":[{"internalType":"uint8","name":"currentState","type":"uint8"}],"name":"ContractState_INCORRECT_STATE","type":"error"},{"inputs":[{"internalType":"uint8","name":"invalidState","type":"uint8"}],"name":"ContractState_INVALID_STATE","type":"error"},{"inputs":[{"internalType":"uint8","name":"currentPhase","type":"uint8"}],"name":"EO_PHASE_DEPLETED","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountReceived","type":"uint256"},{"internalType":"uint256","name":"amountExpected","type":"uint256"}],"name":"ETHER_INCORRECT_PRICE","type":"error"},{"inputs":[],"name":"ETHER_NO_BALANCE","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHER_TRANSFER_FAIL","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"IERC173_NOT_OWNER","type":"error"},{"inputs":[{"internalType":"uint256","name":"royaltyRate","type":"uint256"},{"internalType":"uint256","name":"royaltyBase","type":"uint256"}],"name":"IERC2981_INVALID_ROYALTIES","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"IERC721Enumerable_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_CALLER_NOT_APPROVED","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"IERC721_INVALID_APPROVAL","type":"error"},{"inputs":[],"name":"IERC721_INVALID_TRANSFER","type":"error"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_INVALID_TRANSFER_FROM","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_NONEXISTANT_TOKEN","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"IERC721_NON_ERC721_RECEIVER","type":"error"},{"inputs":[],"name":"NFT_INVALID_QTY","type":"error"},{"inputs":[],"name":"NFT_INVALID_SUPPLY","type":"error"},{"inputs":[{"internalType":"uint256","name":"qtyRequested","type":"uint256"},{"internalType":"uint256","name":"maxBatch","type":"uint256"}],"name":"NFT_MAX_BATCH","type":"error"},{"inputs":[{"internalType":"uint256","name":"qtyRequested","type":"uint256"},{"internalType":"uint256","name":"reserveLeft","type":"uint256"}],"name":"NFT_MAX_RESERVE","type":"error"},{"inputs":[{"internalType":"uint256","name":"qtyRequested","type":"uint256"},{"internalType":"uint256","name":"remainingSupply","type":"uint256"}],"name":"NFT_MAX_SUPPLY","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"Whitelist_CONSUMED","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"Whitelist_FORBIDDEN","type":"error"},{"inputs":[],"name":"Whitelist_NOT_SET","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":"uint8","name":"previousState","type":"uint8"},{"indexed":true,"internalType":"uint8","name":"newState","type":"uint8"}],"name":"ContractStateChanged","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":"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":"DEFAULT_OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_SUBSCRIPTION","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BATCH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSED","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PHASE1_SALE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PHASE2_SALE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_SALE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts_","type":"address[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint8","name":"whitelistId_","type":"uint8"},{"internalType":"uint256","name":"alloted_","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct Whitelist_ECDSA.Proof","name":"proof_","type":"tuple"}],"name":"checkWhitelistAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"getContractState","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"qty_","type":"uint256"},{"internalType":"uint256","name":"alloted_","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct Whitelist_ECDSA.Proof","name":"proof_","type":"tuple"}],"name":"mintPrivate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"qty_","type":"uint256"}],"name":"mintPublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFilterRegistry","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"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":"newMaxSupply_","type":"uint256"}],"name":"reduceSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"salePrice_","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"salePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"newBaseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"newState_","type":"uint8"}],"name":"setContractState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPhase1Price_","type":"uint256"},{"internalType":"uint256","name":"newPhase2Price_","type":"uint256"},{"internalType":"uint256","name":"newPublicPrice_","type":"uint256"}],"name":"setPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRoyaltyRecipient_","type":"address"},{"internalType":"uint256","name":"newRoyaltyRate_","type":"uint256"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasury_","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdminSigner_","type":"address"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"index_","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRegistry","type":"address"}],"name":"updateOperatorFilterRegistryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060409080825234620002ab57600580546daaeb6d7670e522a718067333cd4e6001600160a01b0319918216811790925591600091803b62000222575b505090611a0a600655600191826007556032600855600a548381811c9116801562000217575b602082101462000203579081601f86931162000195575b50737df36a44fca36f05a6fbf74b7cbdd9b43349e37f929161162191606b600a55600a81527f556a7134736b4356686b354866537831464a6f6937000000000000000000000086602083207f697066733a2f2f516d5063797242615936355a5657526546776b50585551484781550155858152600e60205266d19c2ff9bf80008282205560028152670118aa14d9418000828220556003815267013c31074902800082822055858152600f602052610bb782822055600281522055732b1076bf95da326441e5bf81a1d0357b10bdb933816009541617600955338160005416176000556101f4600355734f440081a1c6a94ca5fa5fecc31bcec5bba6269181600454161760045582541617905551612e759081620002b18239f35b600a8252601f0160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a801847fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2aa5b828110620001f45750506200007a565b838155879450869101620001e4565b634e487b7160e01b82526022600452602482fd5b90607f169062000063565b803b15620002a75781604481858094633e9f1edf60e11b8352306004840152733cc6cdda760b79bafa08df41ecfa224f810dceb660248401525af180156200029d5762000271575b806200003d565b6001600160401b03811162000289578352386200026a565b634e487b7160e01b82526041600452602482fd5b84513d84823e3d90fd5b8280fd5b600080fdfe60806040526004361015610013575b600080fd5b60003560e01c806301ffc9a71461037a57806306fdde0314610371578063081812fc14610368578063095ea7b31461035f57806318160ddd146103565780631a3f839d1461034d57806323b872dd146103445780632a55205a1461033b5780632f745c59146103325780633ccfd60b1461032957806342842e0e146103205780634f6ccce71461031757806355f804b31461030e5780635f89584e146103055780636352211e146102fc57806367243482146102f357806370a08231146102ea5780637e9845f5146102e15780637f4e4849146102d857806380623444146102cf578063854cff2f146102c65780638da5cb5b146102bd578063950bff9f146102a257806395d89b41146102b45780639b2851cf146102ab5780639f6eb762146102a2578063a22cb46514610299578063a49225f814610290578063a88fe42d14610287578063a9aad58c1461027e578063b0ccc31e14610275578063b88d4fde1461026c578063b8d1e53214610263578063c87b56dd1461025a578063d5abeb0114610251578063e2e784d514610248578063e985e9c51461023f578063efd0cbf914610236578063f0f442601461022d578063f2fde38b14610224578063f51f96dd1461021b578063f7b4c18714610212578063f9c0611c146102095763ff21456b1461020157600080fd5b61000e611adb565b5061000e611aab565b5061000e6119d1565b5061000e6119a1565b5061000e61191d565b5061000e6118c0565b5061000e61170c565b5061000e6116a9565b5061000e611603565b5061000e6115e4565b5061000e6115a1565b5061000e61151a565b5061000e6114b9565b5061000e611491565b5061000e611474565b5061000e611423565b5061000e6113f9565b5061000e6112f2565b5061000e61124f565b5061000e6112cb565b5061000e61126c565b5061000e611227565b5061000e6111ca565b5061000e61113f565b5061000e61111a565b5061000e6110fe565b5061000e6110da565b5061000e61102f565b5061000e610f6b565b5061000e610f4e565b5061000e610e07565b5061000e610d58565b5061000e610d10565b5061000e610c1b565b5061000e610bf3565b5061000e610bb9565b5061000e610a9a565b5061000e6109cf565b5061000e610916565b5061000e61078d565b5061000e6106d8565b5061000e610679565b5061000e6103ad565b7fffffffff0000000000000000000000000000000000000000000000000000000081160361000e57565b503461000e57602060031936011261000e5761044a7fffffffff000000000000000000000000000000000000000000000000000000006004356103ef81610383565b167f80ac58cd0000000000000000000000000000000000000000000000000000000081149081156104f6575b81156104cc575b81156104a2575b8115610478575b811561044e575b5060405190151581529081906020820190565b0390f35b7f2a55205a0000000000000000000000000000000000000000000000000000000091501438610437565b7f01ffc9a70000000000000000000000000000000000000000000000000000000081149150610430565b7f7f5828d00000000000000000000000000000000000000000000000000000000081149150610429565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150610422565b7f780e9d63000000000000000000000000000000000000000000000000000000008114915061041b565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761056c57604052565b610574610520565b604052565b6040810190811067ffffffffffffffff82111761056c57604052565b6080810190811067ffffffffffffffff82111761056c57604052565b90601f601f19910116810190811067ffffffffffffffff82111761056c57604052565b601f19601f60209267ffffffffffffffff81116105f2575b01160190565b6105fa610520565b6105ec565b604051906020820182811067ffffffffffffffff821117610624575b60405260008252565b61062c610520565b61061b565b60005b8381106106445750506000910152565b8181015183820152602001610634565b90601f19601f60209361067281518092818752878088019101610631565b0116010190565b503461000e57600060031936011261000e5761044a60405161069a81610579565b601d81527f45746865726e616c204f6e6573202d20546865204177616b656e696e670000006020820152604051918291602083526020830190610654565b503461000e57602060031936011261000e576004356106f681612387565b1561071c57600052600b60205260206001600160a01b0360406000205416604051908152f35b602490604051907f1cf4d9a40000000000000000000000000000000000000000000000000000000082526004820152fd5b600435906001600160a01b038216820361000e57565b602435906001600160a01b038216820361000e57565b35906001600160a01b038216820361000e57565b503461000e57604060031936011261000e576107a761074d565b602435906107b482612387565b156108e5576107c233612d2e565b6107cb82612411565b6001600160a01b0380831692908216918383146108b4576107f46107f086338461239a565b1590565b61086b57506108449061081185600052600b602052604060002090565b906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4005b6040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b0391909116600482015233602482015260448101859052606490fd5b602484604051907ff2b21e1c0000000000000000000000000000000000000000000000000000000082526004820152fd5b602482604051907f1cf4d9a40000000000000000000000000000000000000000000000000000000082526004820152fd5b503461000e57600060031936011261000e5761093061292d565b80805b61094257602082604051908152f35b61094b81612387565b1561095b575b6000190180610933565b60001990910190610951565b6004359060ff8216820361000e57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc606091011261000e57604051906109ae82610550565b604435825260643560208301526084358260ff8216820361000e5760400152565b503461000e5760c060031936011261000e576109e961074d565b6024359060ff8216820361000e5760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c36011261000e57604051610a2d81610550565b6064358152608435602082015260a4359160ff8316830361000e57602093610a5d93604084015260443591611e87565b604051908152f35b600319606091011261000e576001600160a01b0390600435828116810361000e5791602435908116810361000e579060443590565b503461000e57610aa936610a65565b90610ab382612387565b156108e5576001600160a01b039283821615610b8f57610ad283612411565b9380851690821603610b445750610aed6107f083338661239a565b610afc57610afa926125b5565b005b506040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b039290921660048301523360248301526044820152606490fd5b6040517fe02b28e70000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291909116602482015260448101839052606490fd5b60046040517f14242cb6000000000000000000000000000000000000000000000000000000008152fd5b503461000e57604060031936011261000e57610bd6602435611cd7565b604080516001600160a01b03939093168352602083019190915290f35b503461000e57604060031936011261000e576020610a5d610c1261074d565b602435906129ff565b503461000e57600080600319360112610d0d576001600160a01b03338183541603610cdd5747908115610cb357600954166001600160a01b03168280808085855af1610c656121ef565b5015610c6f578280f35b6040517f84020a7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039190911660048201526024810191909152604490fd5b60046040517f6cc4466b000000000000000000000000000000000000000000000000000000008152fd5b60246040517f55932a1b000000000000000000000000000000000000000000000000000000008152336004820152fd5b80fd5b503461000e57610afa610d2236610a65565b90604051926020840184811067ffffffffffffffff821117610d4b575b6040526000845261247b565b610d53610520565b610d3f565b503461000e57602060031936011261000e57600435610d7561292d565b811015610d9f5780600160209201809111610d9257604051908152f35b610d9a611c8a565b610a5d565b602490604051907f125c19b00000000000000000000000000000000000000000000000000000000082526004820152fd5b929192610ddc826105d4565b91610dea60405193846105b1565b82948184528183011161000e578281602093846000960137010152565b503461000e5760208060031936011261000e5767ffffffffffffffff9060043582811161000e573660238201121561000e57610e4d903690602481600401359101610dd0565b91600091336001600160a01b0384541603610cdd578351918211610f41575b610e8082610e7b600a54612869565b6128bc565b80601f8311600114610eb957508293829392610eae575b50506000198260011b9260031b1c191617600a5580f35b015190503880610e97565b90601f19831694610eec600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890565b9285905b878210610f29575050836001959610610f10575b505050811b01600a5580f35b015160001960f88460031b161c19169055388080610f04565b80600185968294968601518155019501930190610ef0565b610f49610520565b610e6c565b503461000e57600060031936011261000e57602060405160038152f35b503461000e57602060031936011261000e57600435610f8981612387565b1561071c57610f99602091612411565b6001600160a01b0360405191168152f35b60209067ffffffffffffffff8111610fc4575b60051b0190565b610fcc610520565b610fbd565b81601f8201121561000e57803591610fe883610faa565b92610ff660405194856105b1565b808452602092838086019260051b82010192831161000e578301905b828210611020575050505090565b81358152908301908301611012565b503461000e57604060031936011261000e5767ffffffffffffffff60043581811161000e573660238201121561000e57806004013561106d81610faa565b9161107b60405193846105b1565b81835260209160248385019160051b8301019136831161000e57602401905b8282106110c3576024358587821161000e576110bd610afa923690600401610fd1565b9061273b565b8380916110cf84610779565b81520191019061109a565b503461000e57602060031936011261000e576020610a5d6110f961074d565b612947565b503461000e57600060031936011261000e576020610a5d61292d565b503461000e57600060031936011261000e57602060ff60005460a01c16604051908152f35b503461000e57602060031936011261000e57600435336001600160a01b036000541603610cdd57600654811180156111a5575b61117b57600655005b60046040517fbcc7b4fb000000000000000000000000000000000000000000000000000000008152fd5b5060075460085481018091116111bd575b8110611172565b6111c5611c8a565b6111b6565b503461000e57602060031936011261000e576111e461074d565b6001600160a01b039033826000541603610cdd57167fffffffffffffffffffffffff00000000000000000000000000000000000000006001541617600155600080f35b503461000e57600060031936011261000e5760206001600160a01b0360005416604051908152f35b503461000e57600060031936011261000e57602060405160028152f35b503461000e57600060031936011261000e5761044a60405161128d81610579565b600581527f454f4e46540000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610654565b503461000e57600060031936011261000e57602060405160018152f35b8015150361000e57565b503461000e57604060031936011261000e5761130c61074d565b602435611318816112e8565b61132133612d2e565b6001600160a01b038216913383146113c85761135d9033600052600c6020526040600020906001600160a01b0316600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff831515161790557f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31604051806113c3339482919091602081019215159052565b0390a3005b602483604051907ff2b21e1c0000000000000000000000000000000000000000000000000000000082526004820152fd5b503461000e57600060031936011261000e5760206040516daaeb6d7670e522a718067333cd4e8152f35b503461000e57606060031936011261000e576000336001600160a01b0382541603610cdd5760018152600e602052600435604082205560028152602435604082205560038152604435604082205580f35b503461000e57600060031936011261000e57602060405160008152f35b503461000e57600060031936011261000e5760206001600160a01b0360055416604051908152f35b503461000e57608060031936011261000e576114d361074d565b6114db610763565b6064359167ffffffffffffffff831161000e573660238401121561000e57611510610afa933690602481600401359101610dd0565b916044359161247b565b503461000e57602060031936011261000e5761153461074d565b6001600160a01b03908160005416330361157757167fffffffffffffffffffffffff00000000000000000000000000000000000000006005541617600555600080f35b60046040517f5fc483c5000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e576004356115bf81612387565b1561071c576115d061044a91612b99565b604051918291602083526020830190610654565b503461000e57600060031936011261000e576020600654604051908152f35b503461000e57604060031936011261000e5761161d61074d565b602435906001600160a01b039133836000541603610cdd576127108082116116725750600355167fffffffffffffffffffffffff00000000000000000000000000000000000000006004541617600455600080f35b60449250604051917f4ec3fd3a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b503461000e57604060031936011261000e57602060ff6117006116ca61074d565b6001600160a01b036116da610763565b9116600052600c84526040600020906001600160a01b0316600052602052604060002090565b54166040519015158152f35b50602060031936011261000e57600480359081156118985760ff60005460a01c166003810361186857506002821161182b5761175e61175060065460085490611d31565b61175861292d565b90611d31565b8083116117ed57506003600052600e6020529061179d7fe0283e559c29e31ee7f56467acc9dd307779c843a883aeeb3bf5c6128c9081445b5482611cba565b913483036117af57610afa8233612076565b604080517f9310692e000000000000000000000000000000000000000000000000000000008152349281019283526020830194909452839250010390fd5b604080517f9abbab07000000000000000000000000000000000000000000000000000000008152928301938452602084019190915290918291010390fd5b604080517f5aaca4e40000000000000000000000000000000000000000000000000000000081529182019283526002602084015290918291010390fd5b60249250604051917f5d80b9ec000000000000000000000000000000000000000000000000000000008352820152fd5b6040517f7fcfed3c000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e576118da61074d565b6001600160a01b039033826000541603610cdd57167fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955600080f35b503461000e57602060031936011261000e5761193761074d565b60009081546001600160a01b039081811691338303610cdd577fffffffffffffffffffffffff00000000000000000000000000000000000000009316928391161783557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b503461000e57600080600319360112610d0d5760408160ff6020935460a01c168152600e83522054604051908152f35b503461000e57602060031936011261000e576119eb610967565b6000908154336001600160a01b03821603610cdd5760ff82169160038311611a7a577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff821660a091821b74ff0000000000000000000000000000000000000000161784551c60ff167f7285522ec93a20dcefa1a1d057094a227073a5463b91c0c19a23c6ef5c9c1fe48380a380f35b602483604051907fb81f89930000000000000000000000000000000000000000000000000000000082526004820152fd5b503461000e57600060031936011261000e576020604051733cc6cdda760b79bafa08df41ecfa224f810dceb68152f35b5060a060031936011261000e5760048035611af536610977565b8115611c615760ff60005460a01c1690600182141580611c56575b611c2657611b22839160243533611d3e565b10611bf657611b38611b3261292d565b83612069565b611b4f8260ff16600052600f602052604060002090565b5410611bbc57611796611b6f9160ff16600052600e602052604060002090565b913483036117af57610afa82611b858133612076565b3360009081527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e06020526040902080549091019055565b6040517f5301a3b800000000000000000000000000000000000000000000000000000000815260ff90911681840190815281906020010390fd5b6040517f186a628d0000000000000000000000000000000000000000000000000000000081523381850152602490fd5b60248483604051917f5d80b9ec000000000000000000000000000000000000000000000000000000008352820152fd5b506002821415611b10565b826040517f7fcfed3c000000000000000000000000000000000000000000000000000000008152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810292918115918404141715611ccd57565b611cd5611c8a565b565b80158015611d18575b611d0557611cf361271091600354611cba565b04906001600160a01b03600454169190565b506001600160a01b036004541690600090565b5060035415611ce0565b906000198201918211611ccd57565b91908203918211611ccd57565b92916001600160a01b03611d5a6001546001600160a01b031690565b1615611e5d576001600052600260205281611da9857fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e05b906001600160a01b0316600052602052604060002090565b541015611e23576107f0611dbe918386611f7f565b611de957611ddf611de69293611d9160016000526002602052604060002090565b5490611d31565b90565b6040517f186a628d0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602490fd5b6040517f6acdb0950000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602490fd5b60046040517f93dff142000000000000000000000000000000000000000000000000000000008152fd5b93926001600160a01b03611ea36001546001600160a01b031690565b1615611e5d5782611ec586611d918560ff166000526002602052604060002090565b541015611f38576107f0611edb91848488612022565b611efe57611de69293611d91611ddf9260ff166000526002602052604060002090565b6040517f186a628d0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602490fd5b6040517f6acdb0950000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602490fd5b506040513d6000823e3d90fd5b916080600091602093604051858101916001835260408201526001600160a01b03809716606082015260608152611fb581610595565b5190209060ff6040820151169085815191015191604051938452868401526040830152606082015282805260015afa15612015575b6000519061200f6120036001546001600160a01b031690565b6001600160a01b031690565b91161490565b61201d611f72565b611fea565b926080906000926020946040519060ff8783019316835260408201526001600160a01b03809716606082015260608152611fb581610595565b9060018201809211611ccd57565b91908201809211611ccd57565b600754918201808311612172575b61208d81611d22565b6120a58361081186600052600d602052604060002090565b82848211612154575b50506120b981600755565b6120ce6107f06120c76105ff565b858561221f565b61211a57915b8281106120e057505050565b600190806001600160a01b03841660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4016120d4565b6040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602490fd5b61081161216b92600052600d602052604060002090565b38826120ae565b61217a611c8a565b612084565b9081602091031261000e5751611de681610383565b611de693926001600160a01b036080931682526000602083015260408201528160608201520190610654565b9092611de694936080936001600160a01b03809216845216602083015260408201528160608201520190610654565b3d1561221a573d90612200826105d4565b9161220e60405193846105b1565b82523d6000602084013e565b606090565b9291833b1561232c57602061226491604051809381927f150b7a0200000000000000000000000000000000000000000000000000000000968784523360048501612194565b038160006001600160a01b0389165af1600091816122fc575b506122d5578361228b6121ef565b80519190826122ce576040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602490fd5b9050602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000016149150565b61231e91925060203d8111612325575b61231681836105b1565b81019061217f565b903861227d565b503d61230c565b506001925050565b9093929091843b1561237e576122649160209160405193849283927f150b7a02000000000000000000000000000000000000000000000000000000009788855233600486016121c0565b50600193505050565b8015612394576007541190565b50600090565b6001600160a01b0380911690808316908282149485156123f6575b50505082156123c357505090565b60ff9250906123f191600052600c6020526040600020906001600160a01b0316600052602052604060002090565b541690565b6000908152600b6020526040902054161492503880806123b5565b806000908152600d906020918083526001600160a01b0391604091838383205416955b848716156124455750505050505090565b60001991929394959650801561246e575b01808352818652838320548516959493929190612434565b612476611c8a565b612456565b9291909261248882612387565b156108e5576001600160a01b0380851615610b8f576124a683612411565b908082169083160361256c576124c06107f084338461239a565b6125215791846124de94926124d983836107f0976125b5565b612334565b6124e55750565b6040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152602490fd5b6040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152336024820152604481019290925250606490fd5b6040517fe02b28e70000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529116602482015260448101829052606490fd5b906125ca83600052600b602052604060002090565b80547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560018311156127345761260283611d22565b8261260c8561205b565b918581109081612723575b816126fa575b8261262785612387565b92836126c4575b6126a6575b5050612688575b50506126548161081185600052600d602052604060002090565b6001600160a01b0380911691167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4565b61081161269f92600052600d602052604060002090565b388261263a565b6108116126bd92600052600d602052604060002090565b3882612633565b92506001600160a01b036126f26126e587600052600d602052604060002090565b546001600160a01b031690565b16159261262e565b90506001600160a01b0361271b6126e583600052600d602052604060002090565b16159061261d565b905061272e81612387565b90612617565b6001612602565b90336001600160a01b036000541603610cdd57815191815183036127fc57826000935b6127ad575050506008548082116127755703600855565b6040517f016c69db00000000000000000000000000000000000000000000000000000000815260048101929092526024820152604490fd5b6000196127c79101936127c08585612826565b5190612069565b92806127f76127e66127d98386612826565b516001600160a01b031690565b6127f08387612826565b5190612076565b61275e565b60046040517f88adebd2000000000000000000000000000000000000000000000000000000008152fd5b805182101561283a5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600182811c921680156128b2575b602083101461288357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612878565b601f81116128c8575050565b600090600a82527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8906020601f850160051c83019410612923575b601f0160051c01915b82811061291857505050565b81815560010161290c565b9092508290612903565b600754600019810190811161293f5790565b611de6611c8a565b6001600160a01b038091169081156129dc5760075460009260019284845b8481106129755750505050505090565b806129808792612387565b61298b575b01612965565b809150600052600d60205282604060002054166129bd575b82821684146129b4575b8590612985565b958501956129ad565b9050816129d482600052600d602052604060002090565b5416906129a3565b5050600090565b60019060001981146129f3570190565b6129fb611c8a565b0190565b9190600092612a0d81612947565b821015612a9557600091612a1f61292d565b9160015b838110612a31575050505050565b612a3a81612387565b80612a78575b612a53575b612a4e906129e3565b612a23565b93808314612a6f57612a67612a4e916129e3565b949050612a45565b50929450505050565b506001600160a01b0380612a8b83612411565b1690831614612a40565b6040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526001600160a01b039190911660048201526024810191909152604490fd5b600a5460009291612ae982612869565b91600190818116908115612b555750600114612b0457505050565b9091929350600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8906000915b848310612b42575050500190565b8181602092548587015201920191612b34565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001683525050811515909102019150565b906129fb60209282815194859201610631565b600a54612ba581612869565b612bb35750611de690612cd0565b612bbb61292d565b60065403612bf95750611de6612bd3612beb92612cd0565b604051928391612be560208401612ad9565b90612b86565b03601f1981018352826105b1565b6040519150816000612c0a83612869565b80835292600190818116908115612c905750600114612c31575b50611de6925003826105b1565b600a600090815291507fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a85b848310612c755750611de6935050810160200138612c24565b81935090816020925483858901015201910190918492612c5c565b60209350611de69592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612c24565b9060405160a08101604052600019608082019360008552935b0192600a90818106603001855304928315612d075760001990612ce9565b9250608083601f199203019201918252565b9081602091031261000e5751611de6816112e8565b612d436120036005546001600160a01b031690565b6001600160a01b038116151580612e35575b612d5d575050565b6040517fc61711340000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316602482015290602090829060449082905afa908115612e28575b600091612dfa575b5015612dbe5750565b6040517fede71dcc0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152602490fd5b612e1b915060203d8111612e21575b612e1381836105b1565b810190612d19565b38612db5565b503d612e09565b612e30611f72565b612dad565b50803b1515612d5556fea2646970667358221220195a19e2203dd7eec03600d2529ef0a60b329f231f5ecff027939d3f0e9e72e264736f6c63430008110033
Deployed Bytecode
0x60806040526004361015610013575b600080fd5b60003560e01c806301ffc9a71461037a57806306fdde0314610371578063081812fc14610368578063095ea7b31461035f57806318160ddd146103565780631a3f839d1461034d57806323b872dd146103445780632a55205a1461033b5780632f745c59146103325780633ccfd60b1461032957806342842e0e146103205780634f6ccce71461031757806355f804b31461030e5780635f89584e146103055780636352211e146102fc57806367243482146102f357806370a08231146102ea5780637e9845f5146102e15780637f4e4849146102d857806380623444146102cf578063854cff2f146102c65780638da5cb5b146102bd578063950bff9f146102a257806395d89b41146102b45780639b2851cf146102ab5780639f6eb762146102a2578063a22cb46514610299578063a49225f814610290578063a88fe42d14610287578063a9aad58c1461027e578063b0ccc31e14610275578063b88d4fde1461026c578063b8d1e53214610263578063c87b56dd1461025a578063d5abeb0114610251578063e2e784d514610248578063e985e9c51461023f578063efd0cbf914610236578063f0f442601461022d578063f2fde38b14610224578063f51f96dd1461021b578063f7b4c18714610212578063f9c0611c146102095763ff21456b1461020157600080fd5b61000e611adb565b5061000e611aab565b5061000e6119d1565b5061000e6119a1565b5061000e61191d565b5061000e6118c0565b5061000e61170c565b5061000e6116a9565b5061000e611603565b5061000e6115e4565b5061000e6115a1565b5061000e61151a565b5061000e6114b9565b5061000e611491565b5061000e611474565b5061000e611423565b5061000e6113f9565b5061000e6112f2565b5061000e61124f565b5061000e6112cb565b5061000e61126c565b5061000e611227565b5061000e6111ca565b5061000e61113f565b5061000e61111a565b5061000e6110fe565b5061000e6110da565b5061000e61102f565b5061000e610f6b565b5061000e610f4e565b5061000e610e07565b5061000e610d58565b5061000e610d10565b5061000e610c1b565b5061000e610bf3565b5061000e610bb9565b5061000e610a9a565b5061000e6109cf565b5061000e610916565b5061000e61078d565b5061000e6106d8565b5061000e610679565b5061000e6103ad565b7fffffffff0000000000000000000000000000000000000000000000000000000081160361000e57565b503461000e57602060031936011261000e5761044a7fffffffff000000000000000000000000000000000000000000000000000000006004356103ef81610383565b167f80ac58cd0000000000000000000000000000000000000000000000000000000081149081156104f6575b81156104cc575b81156104a2575b8115610478575b811561044e575b5060405190151581529081906020820190565b0390f35b7f2a55205a0000000000000000000000000000000000000000000000000000000091501438610437565b7f01ffc9a70000000000000000000000000000000000000000000000000000000081149150610430565b7f7f5828d00000000000000000000000000000000000000000000000000000000081149150610429565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150610422565b7f780e9d63000000000000000000000000000000000000000000000000000000008114915061041b565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761056c57604052565b610574610520565b604052565b6040810190811067ffffffffffffffff82111761056c57604052565b6080810190811067ffffffffffffffff82111761056c57604052565b90601f601f19910116810190811067ffffffffffffffff82111761056c57604052565b601f19601f60209267ffffffffffffffff81116105f2575b01160190565b6105fa610520565b6105ec565b604051906020820182811067ffffffffffffffff821117610624575b60405260008252565b61062c610520565b61061b565b60005b8381106106445750506000910152565b8181015183820152602001610634565b90601f19601f60209361067281518092818752878088019101610631565b0116010190565b503461000e57600060031936011261000e5761044a60405161069a81610579565b601d81527f45746865726e616c204f6e6573202d20546865204177616b656e696e670000006020820152604051918291602083526020830190610654565b503461000e57602060031936011261000e576004356106f681612387565b1561071c57600052600b60205260206001600160a01b0360406000205416604051908152f35b602490604051907f1cf4d9a40000000000000000000000000000000000000000000000000000000082526004820152fd5b600435906001600160a01b038216820361000e57565b602435906001600160a01b038216820361000e57565b35906001600160a01b038216820361000e57565b503461000e57604060031936011261000e576107a761074d565b602435906107b482612387565b156108e5576107c233612d2e565b6107cb82612411565b6001600160a01b0380831692908216918383146108b4576107f46107f086338461239a565b1590565b61086b57506108449061081185600052600b602052604060002090565b906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4005b6040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b0391909116600482015233602482015260448101859052606490fd5b602484604051907ff2b21e1c0000000000000000000000000000000000000000000000000000000082526004820152fd5b602482604051907f1cf4d9a40000000000000000000000000000000000000000000000000000000082526004820152fd5b503461000e57600060031936011261000e5761093061292d565b80805b61094257602082604051908152f35b61094b81612387565b1561095b575b6000190180610933565b60001990910190610951565b6004359060ff8216820361000e57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc606091011261000e57604051906109ae82610550565b604435825260643560208301526084358260ff8216820361000e5760400152565b503461000e5760c060031936011261000e576109e961074d565b6024359060ff8216820361000e5760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c36011261000e57604051610a2d81610550565b6064358152608435602082015260a4359160ff8316830361000e57602093610a5d93604084015260443591611e87565b604051908152f35b600319606091011261000e576001600160a01b0390600435828116810361000e5791602435908116810361000e579060443590565b503461000e57610aa936610a65565b90610ab382612387565b156108e5576001600160a01b039283821615610b8f57610ad283612411565b9380851690821603610b445750610aed6107f083338661239a565b610afc57610afa926125b5565b005b506040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b039290921660048301523360248301526044820152606490fd5b6040517fe02b28e70000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291909116602482015260448101839052606490fd5b60046040517f14242cb6000000000000000000000000000000000000000000000000000000008152fd5b503461000e57604060031936011261000e57610bd6602435611cd7565b604080516001600160a01b03939093168352602083019190915290f35b503461000e57604060031936011261000e576020610a5d610c1261074d565b602435906129ff565b503461000e57600080600319360112610d0d576001600160a01b03338183541603610cdd5747908115610cb357600954166001600160a01b03168280808085855af1610c656121ef565b5015610c6f578280f35b6040517f84020a7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039190911660048201526024810191909152604490fd5b60046040517f6cc4466b000000000000000000000000000000000000000000000000000000008152fd5b60246040517f55932a1b000000000000000000000000000000000000000000000000000000008152336004820152fd5b80fd5b503461000e57610afa610d2236610a65565b90604051926020840184811067ffffffffffffffff821117610d4b575b6040526000845261247b565b610d53610520565b610d3f565b503461000e57602060031936011261000e57600435610d7561292d565b811015610d9f5780600160209201809111610d9257604051908152f35b610d9a611c8a565b610a5d565b602490604051907f125c19b00000000000000000000000000000000000000000000000000000000082526004820152fd5b929192610ddc826105d4565b91610dea60405193846105b1565b82948184528183011161000e578281602093846000960137010152565b503461000e5760208060031936011261000e5767ffffffffffffffff9060043582811161000e573660238201121561000e57610e4d903690602481600401359101610dd0565b91600091336001600160a01b0384541603610cdd578351918211610f41575b610e8082610e7b600a54612869565b6128bc565b80601f8311600114610eb957508293829392610eae575b50506000198260011b9260031b1c191617600a5580f35b015190503880610e97565b90601f19831694610eec600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890565b9285905b878210610f29575050836001959610610f10575b505050811b01600a5580f35b015160001960f88460031b161c19169055388080610f04565b80600185968294968601518155019501930190610ef0565b610f49610520565b610e6c565b503461000e57600060031936011261000e57602060405160038152f35b503461000e57602060031936011261000e57600435610f8981612387565b1561071c57610f99602091612411565b6001600160a01b0360405191168152f35b60209067ffffffffffffffff8111610fc4575b60051b0190565b610fcc610520565b610fbd565b81601f8201121561000e57803591610fe883610faa565b92610ff660405194856105b1565b808452602092838086019260051b82010192831161000e578301905b828210611020575050505090565b81358152908301908301611012565b503461000e57604060031936011261000e5767ffffffffffffffff60043581811161000e573660238201121561000e57806004013561106d81610faa565b9161107b60405193846105b1565b81835260209160248385019160051b8301019136831161000e57602401905b8282106110c3576024358587821161000e576110bd610afa923690600401610fd1565b9061273b565b8380916110cf84610779565b81520191019061109a565b503461000e57602060031936011261000e576020610a5d6110f961074d565b612947565b503461000e57600060031936011261000e576020610a5d61292d565b503461000e57600060031936011261000e57602060ff60005460a01c16604051908152f35b503461000e57602060031936011261000e57600435336001600160a01b036000541603610cdd57600654811180156111a5575b61117b57600655005b60046040517fbcc7b4fb000000000000000000000000000000000000000000000000000000008152fd5b5060075460085481018091116111bd575b8110611172565b6111c5611c8a565b6111b6565b503461000e57602060031936011261000e576111e461074d565b6001600160a01b039033826000541603610cdd57167fffffffffffffffffffffffff00000000000000000000000000000000000000006001541617600155600080f35b503461000e57600060031936011261000e5760206001600160a01b0360005416604051908152f35b503461000e57600060031936011261000e57602060405160028152f35b503461000e57600060031936011261000e5761044a60405161128d81610579565b600581527f454f4e46540000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610654565b503461000e57600060031936011261000e57602060405160018152f35b8015150361000e57565b503461000e57604060031936011261000e5761130c61074d565b602435611318816112e8565b61132133612d2e565b6001600160a01b038216913383146113c85761135d9033600052600c6020526040600020906001600160a01b0316600052602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff831515161790557f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31604051806113c3339482919091602081019215159052565b0390a3005b602483604051907ff2b21e1c0000000000000000000000000000000000000000000000000000000082526004820152fd5b503461000e57600060031936011261000e5760206040516daaeb6d7670e522a718067333cd4e8152f35b503461000e57606060031936011261000e576000336001600160a01b0382541603610cdd5760018152600e602052600435604082205560028152602435604082205560038152604435604082205580f35b503461000e57600060031936011261000e57602060405160008152f35b503461000e57600060031936011261000e5760206001600160a01b0360055416604051908152f35b503461000e57608060031936011261000e576114d361074d565b6114db610763565b6064359167ffffffffffffffff831161000e573660238401121561000e57611510610afa933690602481600401359101610dd0565b916044359161247b565b503461000e57602060031936011261000e5761153461074d565b6001600160a01b03908160005416330361157757167fffffffffffffffffffffffff00000000000000000000000000000000000000006005541617600555600080f35b60046040517f5fc483c5000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e576004356115bf81612387565b1561071c576115d061044a91612b99565b604051918291602083526020830190610654565b503461000e57600060031936011261000e576020600654604051908152f35b503461000e57604060031936011261000e5761161d61074d565b602435906001600160a01b039133836000541603610cdd576127108082116116725750600355167fffffffffffffffffffffffff00000000000000000000000000000000000000006004541617600455600080f35b60449250604051917f4ec3fd3a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b503461000e57604060031936011261000e57602060ff6117006116ca61074d565b6001600160a01b036116da610763565b9116600052600c84526040600020906001600160a01b0316600052602052604060002090565b54166040519015158152f35b50602060031936011261000e57600480359081156118985760ff60005460a01c166003810361186857506002821161182b5761175e61175060065460085490611d31565b61175861292d565b90611d31565b8083116117ed57506003600052600e6020529061179d7fe0283e559c29e31ee7f56467acc9dd307779c843a883aeeb3bf5c6128c9081445b5482611cba565b913483036117af57610afa8233612076565b604080517f9310692e000000000000000000000000000000000000000000000000000000008152349281019283526020830194909452839250010390fd5b604080517f9abbab07000000000000000000000000000000000000000000000000000000008152928301938452602084019190915290918291010390fd5b604080517f5aaca4e40000000000000000000000000000000000000000000000000000000081529182019283526002602084015290918291010390fd5b60249250604051917f5d80b9ec000000000000000000000000000000000000000000000000000000008352820152fd5b6040517f7fcfed3c000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e576118da61074d565b6001600160a01b039033826000541603610cdd57167fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955600080f35b503461000e57602060031936011261000e5761193761074d565b60009081546001600160a01b039081811691338303610cdd577fffffffffffffffffffffffff00000000000000000000000000000000000000009316928391161783557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b503461000e57600080600319360112610d0d5760408160ff6020935460a01c168152600e83522054604051908152f35b503461000e57602060031936011261000e576119eb610967565b6000908154336001600160a01b03821603610cdd5760ff82169160038311611a7a577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff821660a091821b74ff0000000000000000000000000000000000000000161784551c60ff167f7285522ec93a20dcefa1a1d057094a227073a5463b91c0c19a23c6ef5c9c1fe48380a380f35b602483604051907fb81f89930000000000000000000000000000000000000000000000000000000082526004820152fd5b503461000e57600060031936011261000e576020604051733cc6cdda760b79bafa08df41ecfa224f810dceb68152f35b5060a060031936011261000e5760048035611af536610977565b8115611c615760ff60005460a01c1690600182141580611c56575b611c2657611b22839160243533611d3e565b10611bf657611b38611b3261292d565b83612069565b611b4f8260ff16600052600f602052604060002090565b5410611bbc57611796611b6f9160ff16600052600e602052604060002090565b913483036117af57610afa82611b858133612076565b3360009081527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e06020526040902080549091019055565b6040517f5301a3b800000000000000000000000000000000000000000000000000000000815260ff90911681840190815281906020010390fd5b6040517f186a628d0000000000000000000000000000000000000000000000000000000081523381850152602490fd5b60248483604051917f5d80b9ec000000000000000000000000000000000000000000000000000000008352820152fd5b506002821415611b10565b826040517f7fcfed3c000000000000000000000000000000000000000000000000000000008152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810292918115918404141715611ccd57565b611cd5611c8a565b565b80158015611d18575b611d0557611cf361271091600354611cba565b04906001600160a01b03600454169190565b506001600160a01b036004541690600090565b5060035415611ce0565b906000198201918211611ccd57565b91908203918211611ccd57565b92916001600160a01b03611d5a6001546001600160a01b031690565b1615611e5d576001600052600260205281611da9857fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e05b906001600160a01b0316600052602052604060002090565b541015611e23576107f0611dbe918386611f7f565b611de957611ddf611de69293611d9160016000526002602052604060002090565b5490611d31565b90565b6040517f186a628d0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602490fd5b6040517f6acdb0950000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602490fd5b60046040517f93dff142000000000000000000000000000000000000000000000000000000008152fd5b93926001600160a01b03611ea36001546001600160a01b031690565b1615611e5d5782611ec586611d918560ff166000526002602052604060002090565b541015611f38576107f0611edb91848488612022565b611efe57611de69293611d91611ddf9260ff166000526002602052604060002090565b6040517f186a628d0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602490fd5b6040517f6acdb0950000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602490fd5b506040513d6000823e3d90fd5b916080600091602093604051858101916001835260408201526001600160a01b03809716606082015260608152611fb581610595565b5190209060ff6040820151169085815191015191604051938452868401526040830152606082015282805260015afa15612015575b6000519061200f6120036001546001600160a01b031690565b6001600160a01b031690565b91161490565b61201d611f72565b611fea565b926080906000926020946040519060ff8783019316835260408201526001600160a01b03809716606082015260608152611fb581610595565b9060018201809211611ccd57565b91908201809211611ccd57565b600754918201808311612172575b61208d81611d22565b6120a58361081186600052600d602052604060002090565b82848211612154575b50506120b981600755565b6120ce6107f06120c76105ff565b858561221f565b61211a57915b8281106120e057505050565b600190806001600160a01b03841660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4016120d4565b6040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602490fd5b61081161216b92600052600d602052604060002090565b38826120ae565b61217a611c8a565b612084565b9081602091031261000e5751611de681610383565b611de693926001600160a01b036080931682526000602083015260408201528160608201520190610654565b9092611de694936080936001600160a01b03809216845216602083015260408201528160608201520190610654565b3d1561221a573d90612200826105d4565b9161220e60405193846105b1565b82523d6000602084013e565b606090565b9291833b1561232c57602061226491604051809381927f150b7a0200000000000000000000000000000000000000000000000000000000968784523360048501612194565b038160006001600160a01b0389165af1600091816122fc575b506122d5578361228b6121ef565b80519190826122ce576040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602490fd5b9050602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000016149150565b61231e91925060203d8111612325575b61231681836105b1565b81019061217f565b903861227d565b503d61230c565b506001925050565b9093929091843b1561237e576122649160209160405193849283927f150b7a02000000000000000000000000000000000000000000000000000000009788855233600486016121c0565b50600193505050565b8015612394576007541190565b50600090565b6001600160a01b0380911690808316908282149485156123f6575b50505082156123c357505090565b60ff9250906123f191600052600c6020526040600020906001600160a01b0316600052602052604060002090565b541690565b6000908152600b6020526040902054161492503880806123b5565b806000908152600d906020918083526001600160a01b0391604091838383205416955b848716156124455750505050505090565b60001991929394959650801561246e575b01808352818652838320548516959493929190612434565b612476611c8a565b612456565b9291909261248882612387565b156108e5576001600160a01b0380851615610b8f576124a683612411565b908082169083160361256c576124c06107f084338461239a565b6125215791846124de94926124d983836107f0976125b5565b612334565b6124e55750565b6040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152602490fd5b6040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152336024820152604481019290925250606490fd5b6040517fe02b28e70000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529116602482015260448101829052606490fd5b906125ca83600052600b602052604060002090565b80547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560018311156127345761260283611d22565b8261260c8561205b565b918581109081612723575b816126fa575b8261262785612387565b92836126c4575b6126a6575b5050612688575b50506126548161081185600052600d602052604060002090565b6001600160a01b0380911691167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4565b61081161269f92600052600d602052604060002090565b388261263a565b6108116126bd92600052600d602052604060002090565b3882612633565b92506001600160a01b036126f26126e587600052600d602052604060002090565b546001600160a01b031690565b16159261262e565b90506001600160a01b0361271b6126e583600052600d602052604060002090565b16159061261d565b905061272e81612387565b90612617565b6001612602565b90336001600160a01b036000541603610cdd57815191815183036127fc57826000935b6127ad575050506008548082116127755703600855565b6040517f016c69db00000000000000000000000000000000000000000000000000000000815260048101929092526024820152604490fd5b6000196127c79101936127c08585612826565b5190612069565b92806127f76127e66127d98386612826565b516001600160a01b031690565b6127f08387612826565b5190612076565b61275e565b60046040517f88adebd2000000000000000000000000000000000000000000000000000000008152fd5b805182101561283a5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600182811c921680156128b2575b602083101461288357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612878565b601f81116128c8575050565b600090600a82527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8906020601f850160051c83019410612923575b601f0160051c01915b82811061291857505050565b81815560010161290c565b9092508290612903565b600754600019810190811161293f5790565b611de6611c8a565b6001600160a01b038091169081156129dc5760075460009260019284845b8481106129755750505050505090565b806129808792612387565b61298b575b01612965565b809150600052600d60205282604060002054166129bd575b82821684146129b4575b8590612985565b958501956129ad565b9050816129d482600052600d602052604060002090565b5416906129a3565b5050600090565b60019060001981146129f3570190565b6129fb611c8a565b0190565b9190600092612a0d81612947565b821015612a9557600091612a1f61292d565b9160015b838110612a31575050505050565b612a3a81612387565b80612a78575b612a53575b612a4e906129e3565b612a23565b93808314612a6f57612a67612a4e916129e3565b949050612a45565b50929450505050565b506001600160a01b0380612a8b83612411565b1690831614612a40565b6040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526001600160a01b039190911660048201526024810191909152604490fd5b600a5460009291612ae982612869565b91600190818116908115612b555750600114612b0457505050565b9091929350600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8906000915b848310612b42575050500190565b8181602092548587015201920191612b34565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001683525050811515909102019150565b906129fb60209282815194859201610631565b600a54612ba581612869565b612bb35750611de690612cd0565b612bbb61292d565b60065403612bf95750611de6612bd3612beb92612cd0565b604051928391612be560208401612ad9565b90612b86565b03601f1981018352826105b1565b6040519150816000612c0a83612869565b80835292600190818116908115612c905750600114612c31575b50611de6925003826105b1565b600a600090815291507fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a85b848310612c755750611de6935050810160200138612c24565b81935090816020925483858901015201910190918492612c5c565b60209350611de69592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612c24565b9060405160a08101604052600019608082019360008552935b0192600a90818106603001855304928315612d075760001990612ce9565b9250608083601f199203019201918252565b9081602091031261000e5751611de6816112e8565b612d436120036005546001600160a01b031690565b6001600160a01b038116151580612e35575b612d5d575050565b6040517fc61711340000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316602482015290602090829060449082905afa908115612e28575b600091612dfa575b5015612dbe5750565b6040517fede71dcc0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152602490fd5b612e1b915060203d8111612e21575b612e1381836105b1565b810190612d19565b38612db5565b503d612e09565b612e30611f72565b612dad565b50803b1515612d5556fea2646970667358221220195a19e2203dd7eec03600d2529ef0a60b329f231f5ecff027939d3f0e9e72e264736f6c63430008110033
Loading...
Loading
Loading...
Loading
[ 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.