Overview
TokenID
1991
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
NFT721
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 /** * Author: Lambdalf the White */ pragma solidity 0.8.17; 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/interfaces/IERC2981.sol'; import '../EthereumContracts/contracts/utils/IOwnable.sol'; import '../EthereumContracts/contracts/utils/IPausable.sol'; import '../EthereumContracts/contracts/utils/ITradable.sol'; import '../EthereumContracts/contracts/utils/IWhitelistable_ECDSA.sol'; import '../EthereumContracts/contracts/utils/ERC2981Base.sol'; contract NFT721 is IERC721, IERC721Metadata, IERC721Enumerable, ERC2981Base, IOwnable, IPausable, ITradable, IWhitelistable_ECDSA, IERC165 { // ************************************** // ***** ERRORS ***** // ************************************** /** * @dev Thrown when two related arrays have different lengths */ error ARRAY_LENGTH_MISMATCH(); /** * @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 ); /** * @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 ); /** * @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 INCORRECT_PRICE( uint256 amountReceived, uint256 amountExpected ); /** * @dev Thrown when trying to mint 0 token. */ error NFT_INVALID_QTY(); /** * @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 ); /** * @dev Thrown when trying to withdraw from the contract with no balance. */ error NO_ETHER_BALANCE(); // ************************************** /** * @dev A structure representing the deployment configuration of the contract. * It contains several pieces of information: * - reserve : The amount of tokens that are reserved for airdrops * - maxBatch : The maximum amount of tokens that can be minted in one transaction (for public sale) * - maxSupply : The maximum amount of tokens that can be minted * - publicSalePrice : The price of the tokens during public sale * - privateSalePrice : The price of the tokens during private sale * - treasury : The address that will receive the proceeds of the mint * - name : The name of the tokens, for token trackers (i.e. 'Cool Cats') * - symbol : The symbol of the tokens, for token trackers (i.e. 'COOL') */ struct Config { uint256 maxBatch; uint256 maxSupply; uint256 publicSalePrice; uint256 privateSalePrice; string name; string symbol; } // Constants uint8 public constant PUBLIC_SALE = 1; uint8 public constant PRIVATE_SALE = 2; uint8 public constant WAITLIST_SALE = 3; uint8 public constant CLAIM = 4; uint256 private _nextId = 1; uint256 private _reserve; string private _baseURI; Config private _config; address private _treasury; // 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; constructor( uint256 maxSupply_, uint256 maxBatch_, uint256 reserve_, uint256 salePrice_, uint256 royaltyRate_, address treasury_, string memory name_, string memory symbol_ ) { _config = Config( maxBatch_, maxSupply_, salePrice_, salePrice_, name_, symbol_ ); _reserve = reserve_; _treasury = treasury_; _setRoyaltyInfo( treasury_, royaltyRate_ ); _initIOwnable( msg.sender ); } // ************************************** // ***** 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 `{PRIVATE_SALE}` or `{WAITLIST_SALE}`. */ modifier isPrivateOrWaitlist() { uint8 _currentState_ = getPauseState(); if ( _currentState_ != PRIVATE_SALE && _currentState_ != WAITLIST_SALE ) { revert IPausable_INCORRECT_STATE( PRIVATE_SALE ); } _; } // ************************************** // ************************************** // ***** INTERNAL ***** // ************************************** /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from_ : address owning the token being transferred * @param to_ : address the token is being transferred to * @param tokenId_ : identifier of the NFT being referenced * @param data_ : optional data to send along with the call * * @return bool : whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from_, address to_, uint256 tokenId_, bytes memory data_ ) internal 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( to_ ) } // If address is a contract, check that it is aware of how to handle ERC721 tokens if ( _size_ > 0 ) { try IERC721Receiver( to_ ).onERC721Received( msg.sender, from_, tokenId_, data_ ) returns ( bytes4 retval ) { return retval == IERC721Receiver.onERC721Received.selector; } catch ( bytes memory reason ) { if ( reason.length == 0 ) { revert IERC721_NON_ERC721_RECEIVER( to_ ); } 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. * * Note: this function must be overriden if tokens are burnable. * * @param tokenId_ : identifier of the NFT being referenced * * @return bool : whether the token exists */ function _exists( uint256 tokenId_ ) internal view 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 manage the tokens */ function _isApprovedForAll( address tokenOwner_, address operator_ ) internal view returns ( bool ) { return _isRegisteredProxy( tokenOwner_, operator_ ) || _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 operator_ : address that tries to handle the token * @param tokenId_ : identifier of the NFT being referenced * * @return bool : whether `operator_` is allowed to manage the token */ function _isApprovedOrOwner( address tokenOwner_, address operator_, uint256 tokenId_ ) internal view returns ( bool ) { bool _isApproved_ = operator_ == tokenOwner_ || operator_ == getApproved( tokenId_ ) || isApprovedForAll( tokenOwner_, operator_ ); return _isApproved_; } /** * @dev Mints `qty_` tokens and transfers them to `to_`. * * This internal function can be used to perform token minting. * * @param to_ : address receiving the tokens * @param qty_ : the amount of tokens to be minted * * Emits one or more {Transfer} event. */ function _mint( address to_, uint256 qty_ ) internal { uint256 _firstToken_ = _nextId; uint256 _nextStart_ = _firstToken_ + qty_; uint256 _lastToken_ = _nextStart_ - 1; _owners[ _firstToken_ ] = to_; if ( _lastToken_ > _firstToken_ ) { _owners[ _lastToken_ ] = to_; } _nextId = _nextStart_; for ( uint256 i = _firstToken_; i < _nextStart_; ++i ) { emit Transfer( address( 0 ), to_, i ); } } /** * @dev Internal function returning the owner of the `tokenId_` token. * * @param tokenId_ : identifier of the NFT being referenced * * @return address the address of the token owner */ function _ownerOf( uint256 tokenId_ ) internal view returns ( address ) { uint256 _index_ = tokenId_; address _tokenOwner_ = _owners[ _index_ ]; while ( _tokenOwner_ == address( 0 ) ) { _index_ --; _tokenOwner_ = _owners[ _index_ ]; } return _tokenOwner_; } /** * @dev Internal function returning the total supply. * * Note: this function must be overriden if tokens are burnable. */ function _totalSupply() internal view returns ( uint256 ) { return supplyMinted(); } /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function _toString( uint256 value ) internal pure returns ( string memory ) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if ( value == 0 ) { return "0"; } uint256 temp = value; uint256 digits; while ( temp != 0 ) { digits ++; temp /= 10; } bytes memory buffer = new bytes( digits ); while ( value != 0 ) { digits -= 1; buffer[ digits ] = bytes1( uint8( 48 + uint256( value % 10 ) ) ); value /= 10; } return string( buffer ); } /** * @dev Transfers `tokenId_` from `from_` to `to_`. * * This internal function can be used to implement alternative mechanisms to perform * token transfer, such as signature-based, or token burning. * * @param from_ : the current owner of the NFT * @param to_ : the new owner * @param tokenId_ : identifier of the NFT being referenced * * Emits a {Transfer} event. */ function _transfer( address from_, address to_, uint256 tokenId_ ) internal { _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_ ] = from_; } if ( _nextShouldUpdate_ ) { _owners[ _nextId_ ] = from_; } _owners[ tokenId_ ] = to_; emit Transfer( from_, to_, tokenId_ ); } // ************************************** // ************************************** // ***** 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 {PRIVATE_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_ ) isPrivateOrWaitlist isWhitelisted( msg.sender, PRIVATE_SALE, alloted_, proof_, qty_ ) { uint256 _remainingSupply_ = _config.maxSupply - _reserve - supplyMinted(); if ( qty_ > _remainingSupply_ ) { revert NFT_MAX_SUPPLY( qty_, _remainingSupply_ ); } uint256 _expected_ = qty_ * _config.privateSalePrice; if ( _expected_ != msg.value ) { revert INCORRECT_PRICE( msg.value, _expected_ ); } _consumeWhitelist( msg.sender, PRIVATE_SALE, qty_ ); _mint( msg.sender, qty_ ); } /** * @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 {WAITLIST_SALE}. * - Caller must send enough ether to pay for `qty_` tokens at private sale price. */ function mintWaitlist( uint256 qty_, uint256 alloted_, Proof memory proof_ ) public payable validateAmount( qty_ ) isState( WAITLIST_SALE ) isWhitelisted( msg.sender, WAITLIST_SALE, alloted_, proof_, qty_ ) { uint256 _remainingSupply_ = _config.maxSupply - _reserve - supplyMinted(); if ( qty_ > _remainingSupply_ ) { revert NFT_MAX_SUPPLY( qty_, _remainingSupply_ ); } uint256 _expected_ = qty_ * _config.privateSalePrice; if ( _expected_ != msg.value ) { revert INCORRECT_PRICE( msg.value, _expected_ ); } _consumeWhitelist( msg.sender, WAITLIST_SALE, qty_ ); _mint( msg.sender, qty_ ); } /** * @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 * * - Sale state must not be {PAUSED}. * - Caller must send enough ether to pay for `qty_` tokens at private sale price. */ function claimDualSouls( uint256 qty_, uint256 alloted_, Proof memory proof_ ) public payable validateAmount( qty_ ) isPrivateOrWaitlist isWhitelisted( msg.sender, CLAIM, alloted_, proof_, qty_ ) { uint256 _remainingSupply_ = _config.maxSupply - _reserve - supplyMinted(); if ( qty_ > _remainingSupply_ ) { revert NFT_MAX_SUPPLY( qty_, _remainingSupply_ ); } uint256 _expected_ = qty_ * _config.privateSalePrice; if ( _expected_ != msg.value ) { revert INCORRECT_PRICE( msg.value, _expected_ ); } _consumeWhitelist( msg.sender, CLAIM, qty_ ); _mint( msg.sender, 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_ > _config.maxBatch ) { revert NFT_MAX_BATCH( qty_, _config.maxBatch ); } uint256 _remainingSupply_ = _config.maxSupply - _reserve - supplyMinted(); if ( qty_ > _remainingSupply_ ) { revert NFT_MAX_SUPPLY( qty_, _remainingSupply_ ); } uint256 _expected_ = qty_ * _config.publicSalePrice; if ( _expected_ != msg.value ) { revert INCORRECT_PRICE( msg.value, _expected_ ); } _mint( msg.sender, qty_ ); } // +---------+ // | IERC721 | // +---------+ /** * @notice Gives permission to `to_` to transfer the token number `tokenId_` on behalf of its owner. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * @param to_ : The new approved NFT controller * @param tokenId_ : The NFT to approve * * Requirements: * * - The token number `tokenId_` must exist. * - The caller must own the token or be an approved operator. * - Must emit an {Approval} event. */ function approve( address to_, uint256 tokenId_ ) public override exists( tokenId_ ) { 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_ ); } /** * @notice Transfers the token number `tokenId_` from `from_` to `to_`. * * @param from_ : The current owner of the NFT * @param to_ : The new owner * @param tokenId_ : identifier of the NFT being referenced * * Requirements: * * - The token number `tokenId_` must exist. * - `from_` must be the token owner. * - The caller must own the token or be an approved operator. * - `to_` must not be the zero address. * - If `to_` is a contract, it must implement {IERC721Receiver-onERC721Received} with a return value of `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, * - Must emit a {Transfer} event. */ function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) public override { safeTransferFrom( from_, to_, tokenId_, "" ); } /** * @notice Transfers the token number `tokenId_` from `from_` to `to_`. * * @param from_ : The current owner of the NFT * @param to_ : The new owner * @param tokenId_ : identifier of the NFT being referenced * @param data_ : Additional data with no specified format, sent in call to `to_` * * Requirements: * * - The token number `tokenId_` must exist. * - `from_` must be the token owner. * - The caller must own the token or be an approved operator. * - `to_` must not be the zero address. * - If `to_` is a contract, it must implement {IERC721Receiver-onERC721Received} with a return value of `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, * - Must emit a {Transfer} event. */ function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes memory data_ ) public override { transferFrom( from_, to_, tokenId_ ); if ( ! _checkOnERC721Received( from_, to_, tokenId_, data_ ) ) { revert IERC721_NON_ERC721_RECEIVER( to_ ); } } /** * @notice Allows or disallows `operator_` to manage the caller's tokens on their behalf. * * @param operator_ : Address to add to the set of authorized operators * @param approved_ : True if the operator is approved, false to revoke approval * * Requirements: * * - Must emit an {ApprovalForAll} event. */ function setApprovalForAll( address operator_, bool approved_ ) public override { address _account_ = msg.sender; if ( operator_ == _account_ ) { revert IERC721_INVALID_APPROVAL( operator_ ); } _operatorApprovals[ _account_ ][ operator_ ] = approved_; emit ApprovalForAll( _account_, operator_, approved_ ); } /** * @notice Transfers the token number `tokenId_` from `from_` to `to_`. * * @param from_ : the current owner of the NFT * @param to_ : the new owner * @param tokenId_ : identifier of the NFT being referenced * * Requirements: * * - The token number `tokenId_` must exist. * - `from_` must be the token owner. * - The caller must own the token or be an approved operator. * - `to_` must not be the zero address. * - Must emit a {Transfer} event. */ function transferFrom( address from_, address to_, uint256 tokenId_ ) public override exists( tokenId_ ) { 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 ***** // ************************************** /** * @dev Adds a proxy registry to the list of accepted proxy registries. * * @param proxyRegistryAddress_ : the address of the proxy registry to be added * * Requirements: * * - Caller must be the contract owner. */ function addProxyRegistry( address proxyRegistryAddress_ ) external onlyOwner { _addProxyRegistry( proxyRegistryAddress_ ); } /** * @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 _amountsLen_ = amounts_.length; if ( accounts_.length != _amountsLen_ ) { revert ARRAY_LENGTH_MISMATCH(); } uint256 _totalQty_; for ( uint256 i = _amountsLen_; i > 0; i -- ) { _totalQty_ += amounts_[ i - 1 ]; } if ( _totalQty_ > _reserve ) { revert NFT_MAX_RESERVE( _totalQty_, _reserve ); } unchecked { _reserve -= _totalQty_; } uint256 _count_ = _amountsLen_; while ( _count_ > 0 ) { unchecked { _count_ --; } _mint( accounts_[ _count_ ], amounts_[ _count_ ] ); } } /** * @dev Removes a proxy registry from the list of accepted proxy registries. * * @param proxyRegistryAddress_ : the address of the proxy registry to be removed * * Requirements: * * - Caller must be the contract owner. */ function removeProxyRegistry( address proxyRegistryAddress_ ) external onlyOwner { _removeProxyRegistry( proxyRegistryAddress_ ); } /** * @notice Updates the baseURI for the tokens. * * @param baseURI_ : the new baseURI for the tokens * * Requirements: * * - Caller must be the contract owner. */ function setBaseURI( string memory baseURI_ ) public onlyOwner { _baseURI = baseURI_; } /** * @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 setPauseState( uint8 newState_ ) external onlyOwner { if ( newState_ > CLAIM ) { revert IPausable_INVALID_STATE( newState_ ); } _setPauseState( newState_ ); } /** * @notice Updates the prices. * * Note: We shouldn't need to use this function, but just in case. * * @param publicSalePrice_ : the new public sale price * @param privateSalePrice_ : the new private sale price * * Requirements: * * - Caller must be the contract owner. */ function setPrice( uint256 publicSalePrice_, uint256 privateSalePrice_ ) external onlyOwner { _config.publicSalePrice = publicSalePrice_; _config.privateSalePrice = privateSalePrice_; } /** * @notice Updates the royalty recipient and rate. * * @param royaltyRecipient_ : the new recipient of the royalties * @param royaltyRate_ : the new royalty rate * * Requirements: * * - Caller must be the contract owner. * - `royaltyRate_` cannot be higher than 10,000. */ function setRoyaltyInfo( address royaltyRecipient_, uint256 royaltyRate_ ) external onlyOwner { _setRoyaltyInfo( royaltyRecipient_, royaltyRate_ ); } /** * @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 adminSigner_ : the new whitelist signer * * Requirements: * * - Caller must be the contract owner. */ function setWhitelist( address adminSigner_ ) external onlyOwner { _setWhitelist( adminSigner_ ); } /** * @notice Withdraws all the money stored in the contract and sends it to the treasury. * * Requirements: * * - Caller must be the contract owner. * - Contract must have a positive balance. */ function withdraw() public onlyOwner { uint256 _balance_ = address( this ).balance; if ( _balance_ == 0 ) { revert NO_ETHER_BALANCE(); } address _recipient_ = payable( _treasury ); ( bool _success_, ) = _recipient_.call{ value: _balance_ }( "" ); if ( ! _success_ ) { revert ETHER_TRANSFER_FAIL( _recipient_, _balance_ ); } } // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /** * @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; } /** * @notice Called with the sale price to determine how much royalty is owed and to whom. * * @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 exists( tokenId_ ) returns ( address, uint256 ) { return super.royaltyInfo( tokenId_, salePrice_ ); } // +---------+ // | IERC721 | // +---------+ /** * @notice Returns the number of tokens in `tokenOwner_`'s account. * * @param tokenOwner_ : address that owns tokens * * @return uint256 : the nomber of tokens owned by `tokenOwner_` */ function balanceOf( address tokenOwner_ ) public view override returns ( uint256 ) { if ( tokenOwner_ == address( 0 ) ) { return 0; } uint256 _count_ = 0; address _currentTokenOwner_; for ( uint256 i = 1; i < _nextId; ++ i ) { if ( _exists( i ) ) { if ( _owners[ i ] != address( 0 ) ) { _currentTokenOwner_ = _owners[ i ]; } if ( tokenOwner_ == _currentTokenOwner_ ) { _count_++; } } } return _count_; } /** * @notice Returns the address that has been specifically allowed to manage `tokenId_` on behalf of its owner. * * @param tokenId_ : the NFT that has been approved * * @return address : the address allowed to manage `tokenId_` * * Requirements: * * - `tokenId_` must exist. * * Note: See {Approve} */ function getApproved( uint256 tokenId_ ) public view override exists( tokenId_ ) returns ( address ) { return _approvals[ tokenId_ ]; } /** * @notice Returns 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 `tokenOwner`'s tokens * * Note: See {setApprovalForAll} */ function isApprovedForAll( address tokenOwner_, address operator_ ) public view override returns ( bool ) { return _operatorApprovals[ tokenOwner_ ][ operator_ ]; } /** * @notice Returns the owner of the token number `tokenId_`. * * @param tokenId_ : the NFT to verify ownership of * * @return address : the owner of token number `tokenId_` * * Requirements: * * - `tokenId_` must exist. */ function ownerOf( uint256 tokenId_ ) public view override exists( tokenId_ ) returns ( address ) { return _ownerOf( tokenId_ ); } // +---------+ // +-----------------+ // | IERC721Metadata | // +-----------------+ /** * @notice A descriptive name for a collection of NFTs in this contract. * * @return string : The name of the collection */ function name() public view override returns ( string memory ) { return _config.name; } /** * @notice An abbreviated name for NFTs in this contract. * * @return string : The abbreviated name of the collection */ function symbol() public view override returns ( string memory ) { return _config.symbol; } /** * @notice A distinct Uniform Resource Identifier (URI) for a given asset. * * @param tokenId_ : the NFT that has been approved * * @return string : the URI of the token * * Requirements: * * - `tokenId_` must exist. */ function tokenURI( uint256 tokenId_ ) public view override exists( tokenId_ ) returns ( string memory ) { return bytes( _baseURI ).length > 0 ? string( abi.encodePacked( _baseURI, _toString( tokenId_ ) ) ) : _toString( tokenId_ ); } // +---------+ // +-------------------+ // | IERC721Enumerable | // +-------------------+ /** * @notice Enumerate valid NFTs. * * @param index_ : a counter less than `totalSupply()` * * @return uint256 : the token identifier of the `index_`th NFT * * Requirements: * * - `index_` must be lower than `totalSupply()`. */ function tokenByIndex( uint256 index_ ) public view override returns ( uint256 ) { if ( index_ >= supplyMinted() ) { revert IERC721Enumerable_INDEX_OUT_OF_BOUNDS( index_ ); } return index_; } /** * @notice Enumerate NFTs assigned to an owner. * * @param tokenOwner_ : the address for which we want to know the tokens owned * @param index_ : a counter less than `balanceOf(tokenOwner_)` * * @return tokenId : the token identifier of the `index_`th NFT * * Requirements: * * - `index_` must be lower than `balanceOf(tokenOwner_)`. */ function tokenOfOwnerByIndex( address tokenOwner_, uint256 index_ ) public view override returns ( uint256 tokenId ) { if ( index_ >= balanceOf( tokenOwner_ ) ) { revert IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS( tokenOwner_, index_ ); } uint256 _count_ = 0; for ( uint256 i = 1; i < _nextId; ++i ) { if ( _exists( i ) && tokenOwner_ == _ownerOf( i ) ) { if ( index_ == _count_ ) { return i; } unchecked { _count_++; } } } } /** * @notice Count NFTs tracked by this contract. * * @return the total number of existing NFTs tracked by the contract */ function totalSupply() public view override returns ( uint256 ) { return _totalSupply(); } // +---------+ // +---------+ // | IERC165 | // +---------+ /** * @notice Query if a contract implements an interface. * @dev see https://eips.ethereum.org/EIPS/eip-165 * * @param interfaceId_ : the interface identifier, as specified in ERC-165 * * @return bool : true if the contract implements the specified interface, false otherwise * * Requirements: * * - This function must use less than 30,000 gas. */ function supportsInterface( bytes4 interfaceId_ ) public pure 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; } // +---------+ // ************************************** }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; import "../interfaces/IERC2981.sol"; abstract contract ERC2981Base 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 IWhitelistable_ECDSA { // Errors /** * @dev Thrown when trying to query the whitelist while it's not set */ error IWhitelistable_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 IWhitelistable_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 IWhitelistable_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 IWhitelistable_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 IWhitelistable_NOT_SET(); } if ( _consumed[ whitelistId_ ][ account_ ] >= alloted_ ) { revert IWhitelistable_CONSUMED( account_ ); } if ( ! _validateProof( account_, whitelistId_, alloted_, proof_ ) ) { revert IWhitelistable_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 {IWhitelistable-checkWhitelistAllowance}. */ function _consumeWhitelist( address account_, uint8 whitelistId_, uint256 qty_ ) internal { unchecked { _consumed[ whitelistId_ ][ account_ ] += qty_; } } }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; contract OwnableDelegateProxy {} contract ProxyRegistry { mapping( address => OwnableDelegateProxy ) public proxies; } abstract contract ITradable { // list of accepted proxy registries address[] public proxyRegistries; /** * @dev Internal function that adds a proxy registry to the list of accepted proxy registries. * * @param proxyRegistryAddress_ : the address of the new proxy registry */ function _addProxyRegistry( address proxyRegistryAddress_ ) internal { uint256 _index_ = proxyRegistries.length; while ( _index_ > 0 ) { unchecked { _index_ --; } if ( proxyRegistries[ _index_ ] == proxyRegistryAddress_ ) { return; } } proxyRegistries.push( proxyRegistryAddress_ ); } /** * @dev Internal function that removes a proxy registry from the list of accepted proxy registries. * * @param proxyRegistryAddress_ : the address of the proxy registry to remove */ function _removeProxyRegistry( address proxyRegistryAddress_ ) internal { uint256 _len_ = proxyRegistries.length; uint256 _index_ = _len_; while ( _index_ > 0 ) { unchecked { _index_ --; } if ( proxyRegistries[ _index_ ] == proxyRegistryAddress_ ) { if ( _index_ + 1 != _len_ ) { proxyRegistries[ _index_ ] = proxyRegistries[ _len_ - 1 ]; } proxyRegistries.pop(); } return; } } /** * @dev Internal function that checks if `operator_` is a registered proxy for `tokenOwner_`. * * Note: Use this function to allow whitelisting of registered proxy. * * @param tokenOwner_ : the address the proxy operates on the behalf of * @param operator_ : the proxy address that operates on behalf of the token owner * * @return bool : whether `operator_` is allowed to operate on behalf of `tokenOwner_` or not */ function _isRegisteredProxy( address tokenOwner_, address operator_ ) internal view returns ( bool ) { uint256 _index_ = proxyRegistries.length; while ( _index_ > 0 ) { unchecked { _index_ --; } ProxyRegistry _proxyRegistry_ = ProxyRegistry( proxyRegistries[ _index_ ] ); if ( address( _proxyRegistry_.proxies( tokenOwner_ ) ) == operator_ ) { return true; } } return false; } }
// SPDX-License-Identifier: MIT /** * Author: Lambdalf the White */ pragma solidity 0.8.17; abstract contract IPausable { // 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 IPausable_INCORRECT_STATE( uint8 currentState ); /** * @dev Thrown when trying to set the contract state to an invalid value. * * @param invalidState : the invalid contract state */ error IPausable_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 IPausable_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 IPausable_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 _setPauseState( 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 getPauseState() 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 IOwnable 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 Initializes the contract setting `owner_` as the initial 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 _initIOwnable( address owner_ ) internal { _owner = owner_; } /** * @dev Returns the address of the current 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 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 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 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 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 // 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; 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; }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"maxSupply_","type":"uint256"},{"internalType":"uint256","name":"maxBatch_","type":"uint256"},{"internalType":"uint256","name":"reserve_","type":"uint256"},{"internalType":"uint256","name":"salePrice_","type":"uint256"},{"internalType":"uint256","name":"royaltyRate_","type":"uint256"},{"internalType":"address","name":"treasury_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ARRAY_LENGTH_MISMATCH","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":[{"internalType":"uint256","name":"amountReceived","type":"uint256"},{"internalType":"uint256","name":"amountExpected","type":"uint256"}],"name":"INCORRECT_PRICE","type":"error"},{"inputs":[{"internalType":"uint8","name":"currentState","type":"uint8"}],"name":"IPausable_INCORRECT_STATE","type":"error"},{"inputs":[{"internalType":"uint8","name":"invalidState","type":"uint8"}],"name":"IPausable_INVALID_STATE","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"IWhitelistable_CONSUMED","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"IWhitelistable_FORBIDDEN","type":"error"},{"inputs":[],"name":"IWhitelistable_NOT_SET","type":"error"},{"inputs":[],"name":"NFT_INVALID_QTY","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":"NO_ETHER_BALANCE","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":"CLAIM","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSED","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRIVATE_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":[],"name":"WAITLIST_SALE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxyRegistryAddress_","type":"address"}],"name":"addProxyRegistry","outputs":[],"stateMutability":"nonpayable","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 IWhitelistable_ECDSA.Proof","name":"proof_","type":"tuple"}],"name":"checkWhitelistAllowance","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 IWhitelistable_ECDSA.Proof","name":"proof_","type":"tuple"}],"name":"claimDualSouls","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseState","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":[{"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 IWhitelistable_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":[{"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 IWhitelistable_ECDSA.Proof","name":"proof_","type":"tuple"}],"name":"mintWaitlist","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proxyRegistries","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxyRegistryAddress_","type":"address"}],"name":"removeProxyRegistry","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":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"newState_","type":"uint8"}],"name":"setPauseState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"publicSalePrice_","type":"uint256"},{"internalType":"uint256","name":"privateSalePrice_","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"royaltyRecipient_","type":"address"},{"internalType":"uint256","name":"royaltyRate_","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":"adminSigner_","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":"pure","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":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405260016006553480156200001657600080fd5b5060405162003c1e38038062003c1e83398101604081905262000039916200020d565b6040805160c081018252888152602081018a9052908101869052606081018690526080810183905260a081018290526009888155600a8a9055600b879055600c879055600d6200008a85826200035a565b5060a08201516005820190620000a190826200035a565b5050506007869055600f80546001600160a01b0319166001600160a01b038516179055620000d08385620000f0565b600280546001600160a01b03191633179055505050505050505062000426565b6127108111156200012357604051632761fe9d60e11b815260048101829052612710602482015260440160405180910390fd5b600055600180546001600160a01b0319166001600160a01b0392909216919091179055565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200017057600080fd5b81516001600160401b03808211156200018d576200018d62000148565b604051601f8301601f19908116603f01168101908282118183101715620001b857620001b862000148565b81604052838152602092508683858801011115620001d557600080fd5b600091505b83821015620001f95785820183015181830184015290820190620001da565b600093810190920192909252949350505050565b600080600080600080600080610100898b0312156200022b57600080fd5b885160208a015160408b015160608c015160808d015160a08e0151949c50929a50909850965094506001600160a01b03811681146200026957600080fd5b60c08a01519093506001600160401b03808211156200028757600080fd5b620002958c838d016200015e565b935060e08b0151915080821115620002ac57600080fd5b50620002bb8b828c016200015e565b9150509295985092959890939650565b600181811c90821680620002e057607f821691505b6020821081036200030157634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200035557600081815260208120601f850160051c81016020861015620003305750805b601f850160051c820191505b8181101562000351578281556001016200033c565b5050505b505050565b81516001600160401b0381111562000376576200037662000148565b6200038e81620003878454620002cb565b8462000307565b602080601f831160018114620003c65760008415620003ad5750858301515b600019600386901b1c1916600185901b17855562000351565b600085815260208120601f198616915b82811015620003f757888601518255948401946001909101908401620003d6565b5085821015620004165787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6137e880620004366000396000f3fe6080604052600436106102d15760003560e01c8063854cff2f11610179578063c87b56dd116100d6578063ef72f2761161008a578063f2fde38b11610064578063f2fde38b146107d3578063f7d97577146107f3578063ff21456b1461081357600080fd5b8063ef72f27614610780578063efd0cbf9146107a0578063f0f44260146107b357600080fd5b8063d37ce09f116100bb578063d37ce09f14610704578063e2e784d514610717578063e985e9c51461073757600080fd5b8063c87b56dd146106c4578063d0348b97146106e457600080fd5b80639a44f1fb1161012d578063a9aad58c11610112578063a9aad58c1461067a578063b88d4fde1461068f578063c50ef4d8146106af57600080fd5b80639a44f1fb1461062a578063a22cb4651461065a57600080fd5b80638da5cb5b1161015e5780638da5cb5b146105e257806395d89b411461060057806398c83a161461061557600080fd5b8063854cff2f146105af57806386c27ffc146105cf57600080fd5b806342842e0e116102325780636352211e116101e657806370a08231116101c057806370a082311461056557806373d74876146105855780637e9845f51461059a57600080fd5b80636352211e1461050557806367243482146105255780636dfa99fd1461054557600080fd5b806355f804b31161021757806355f804b31461049e5780635f89584e146104be57806363096509146104e557600080fd5b806342842e0e1461045e5780634f6ccce71461047e57600080fd5b80631a3f839d116102895780632a55205a1161026e5780632a55205a146103ea5780632f745c59146104295780633ccfd60b1461044957600080fd5b80631a3f839d146103aa57806323b872dd146103ca57600080fd5b8063081812fc116102ba578063081812fc1461032d578063095ea7b31461036557806318160ddd1461038757600080fd5b806301ffc9a7146102d657806306fdde031461030b575b600080fd5b3480156102e257600080fd5b506102f66102f1366004612df1565b610826565b60405190151581526020015b60405180910390f35b34801561031757600080fd5b506103206109ef565b6040516103029190612e5e565b34801561033957600080fd5b5061034d610348366004612e71565b610a84565b6040516001600160a01b039091168152602001610302565b34801561037157600080fd5b50610385610380366004612ea6565b610aef565b005b34801561039357600080fd5b5061039c610c6d565b604051908152602001610302565b3480156103b657600080fd5b5061039c6103c5366004612fa4565b610c7c565b3480156103d657600080fd5b506103856103e5366004612ff2565b610db4565b3480156103f657600080fd5b5061040a61040536600461302e565b610f1e565b604080516001600160a01b039093168352602083019190915201610302565b34801561043557600080fd5b5061039c610444366004612ea6565b610f7a565b34801561045557600080fd5b50610385611040565b34801561046a57600080fd5b50610385610479366004612ff2565b611184565b34801561048a57600080fd5b5061039c610499366004612e71565b6111a4565b3480156104aa57600080fd5b506103856104b93660046130a8565b6111ed565b3480156104ca57600080fd5b506104d3600181565b60405160ff9091168152602001610302565b3480156104f157600080fd5b506103856105003660046130f1565b611258565b34801561051157600080fd5b5061034d610520366004612e71565b611307565b34801561053157600080fd5b5061038561054036600461319b565b61135c565b34801561055157600080fd5b5061038561056036600461325b565b6114f2565b34801561057157600080fd5b5061039c61058036600461325b565b61155a565b34801561059157600080fd5b506104d3600481565b3480156105a657600080fd5b5061039c611608565b3480156105bb57600080fd5b506103856105ca36600461325b565b611619565b6103856105dd366004613276565b6116af565b3480156105ee57600080fd5b506002546001600160a01b031661034d565b34801561060c57600080fd5b506103206118be565b34801561062157600080fd5b506104d3600281565b34801561063657600080fd5b5060025474010000000000000000000000000000000000000000900460ff166104d3565b34801561066657600080fd5b506103856106753660046132ac565b6118d0565b34801561068657600080fd5b506104d3600081565b34801561069b57600080fd5b506103856106aa3660046132e8565b6119aa565b3480156106bb57600080fd5b506104d3600381565b3480156106d057600080fd5b506103206106df366004612e71565b611a02565b3480156106f057600080fd5b5061034d6106ff366004612e71565b611a9e565b610385610712366004613276565b611ac8565b34801561072357600080fd5b50610385610732366004612ea6565b611cce565b34801561074357600080fd5b506102f6610752366004613364565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205460ff1690565b34801561078c57600080fd5b5061038561079b36600461325b565b611d37565b6103856107ae366004612e71565b611d9f565b3480156107bf57600080fd5b506103856107ce36600461325b565b611f6c565b3480156107df57600080fd5b506103856107ee36600461325b565b612006565b3480156107ff57600080fd5b5061038561080e36600461302e565b6120d0565b610385610821366004613276565b61213b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806108b957507fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000145b8061090557507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061095157507fffffffff0000000000000000000000000000000000000000000000000000000082167f7f5828d000000000000000000000000000000000000000000000000000000000145b8061099d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b806109e957507fffffffff0000000000000000000000000000000000000000000000000000000082167f2a55205a00000000000000000000000000000000000000000000000000000000145b92915050565b606060096004018054610a0190613397565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2d90613397565b8015610a7a5780601f10610a4f57610100808354040283529160200191610a7a565b820191906000526020600020905b815481529060010190602001808311610a5d57829003601f168201915b5050505050905090565b600081610a9081612335565b610ace576040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6000838152601060205260409020546001600160a01b031691505b50919050565b80610af981612335565b610b32576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b336000610b3e8461234f565b9050806001600160a01b0316856001600160a01b031603610b96576040517ff2b21e1c0000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602401610ac5565b6000610ba38284876123a6565b905080610bf6576040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301528416602482015260448101869052606401610ac5565b60008581526010602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a811691821790925591518893918616917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050505050565b6000610c7761241b565b905090565b6004546000906001600160a01b0316610cc1576040517fc71bad4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff841660009081526005602090815260408083206001600160a01b03891684529091529020548311610d2b576040517f706e18b90000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602401610ac5565b610d3785858585612425565b610d78576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602401610ac5565b60ff841660009081526005602090815260408083206001600160a01b0389168452909152902054610da99084613413565b90505b949350505050565b80610dbe81612335565b610df7576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b6001600160a01b038316610e37576040517f14242cb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000610e438461234f565b9050806001600160a01b0316866001600160a01b031614610eaa576040517fe02b28e70000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528716602482015260448101859052606401610ac5565b6000610eb78284876123a6565b905080610f0a576040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301528416602482015260448101869052606401610ac5565b610f158287876124fa565b50505050505050565b60008083610f2b81612335565b610f64576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b610f6e85856126c3565b92509250509250929050565b6000610f858361155a565b8210610fcf576040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604401610ac5565b600060015b60065481101561103857610fe781612335565b801561100c5750610ff78161234f565b6001600160a01b0316856001600160a01b0316145b15611028578184036110215791506109e99050565b6001909101905b61103181613426565b9050610fd4565b505092915050565b33806110546002546001600160a01b031690565b6001600160a01b03161461109f576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b4760008190036110db576040517f1f84313900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f546040516001600160a01b0390911690600090829084908381818185875af1925050503d806000811461112c576040519150601f19603f3d011682016040523d82523d6000602084013e611131565b606091505b505090508061117e576040517f84020a7b0000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260248101849052604401610ac5565b50505050565b61119f838383604051806020016040528060008152506119aa565b505050565b60006111ae611608565b82106111e9576040517f125c19b000000000000000000000000000000000000000000000000000000000815260048101839052602401610ac5565b5090565b33806112016002546001600160a01b031690565b6001600160a01b03161461124c576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600861119f83826134a4565b338061126c6002546001600160a01b031690565b6001600160a01b0316146112b7576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600460ff831611156112fa576040517f9b7c47a200000000000000000000000000000000000000000000000000000000815260ff83166004820152602401610ac5565b61130382612723565b5050565b60008161131381612335565b61134c576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b6113558361234f565b9392505050565b33806113706002546001600160a01b031690565b6001600160a01b0316146113bb576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b8151835181146113f7576040517f88adebd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b8015611444578461140d600183613413565b8151811061141d5761141d6135a0565b60200260200101518261143091906135cf565b91508061143c816135e2565b9150506113fb565b5060075481111561148f576007546040517f016c69db000000000000000000000000000000000000000000000000000000008152610ac5918391600401918252602082015260400190565b600780548290039055815b80156114ea578080600190039150506114e58682815181106114be576114be6135a0565b60200260200101518683815181106114d8576114d86135a0565b60200260200101516127a1565b61149a565b505050505050565b33806115066002546001600160a01b031690565b6001600160a01b031614611551576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b6113038261289f565b60006001600160a01b03821661157257506000919050565b60008060015b6006548110156115ff5761158b81612335565b156115ef576000818152601260205260409020546001600160a01b0316156115c8576000818152601260205260409020546001600160a01b031691505b816001600160a01b0316856001600160a01b0316036115ef57826115eb81613426565b9350505b6115f881613426565b9050611578565b50909392505050565b60006001600654610c779190613413565b338061162d6002546001600160a01b031690565b6001600160a01b031614611678576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555050565b82806000036116ea576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805474010000000000000000000000000000000000000000900460ff1690811480159061171d575060ff8116600314155b15611757576040517f81d1489b00000000000000000000000000000000000000000000000000000000815260026004820152602401610ac5565b336004858588600061176b86868686610c7c565b9050818110156117b2576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b60006117bc611608565b600754600a546117cc9190613413565b6117d69190613413565b9050808c111561181c576040517f9abbab07000000000000000000000000000000000000000000000000000000008152600481018d905260248101829052604401610ac5565b600c5460009061182c908e613617565b9050348114611870576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b3360009081527f3eec716f11ba9e820c81ca75eb978ffb45831ef8b7a53e5e422c26008e1ca6d56020526040902080548e0190555b6118af338e6127a1565b50505050505050505050505050565b606060096005018054610a0190613397565b336001600160a01b03831681900361191f576040517ff2b21e1c0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610ac5565b6001600160a01b0381811660008181526011602090815260408083209488168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6119b5848484610db4565b6119c1848484846129e0565b61117e576040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610ac5565b606081611a0e81612335565b611a47576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b600060088054611a5690613397565b905011611a6b57611a6683612b49565b611355565b6008611a7684612b49565b604051602001611a8792919061362e565b604051602081830303815290604052915050919050565b60038181548110611aae57600080fd5b6000918252602090912001546001600160a01b0316905081565b8280600003611b03576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460039074010000000000000000000000000000000000000000900460ff168114611b7c576002546040517f81d1489b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910460ff166004820152602401610ac5565b3360038585886000611b9086868686610c7c565b905081811015611bd7576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b6000611be1611608565b600754600a54611bf19190613413565b611bfb9190613413565b9050808c1115611c41576040517f9abbab07000000000000000000000000000000000000000000000000000000008152600481018d905260248101829052604401610ac5565b600c54600090611c51908e613617565b9050348114611c95576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b3360009081527fa9bc9a3a348c357ba16b37005d7e6b3236198c0e939f4af8c5f19b8deeb8ebc06020526040902080548e0190556118a5565b3380611ce26002546001600160a01b031690565b6001600160a01b031614611d2d576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b61119f8383612c7e565b3380611d4b6002546001600160a01b031690565b6001600160a01b031614611d96576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b61130382612d02565b8080600003611dda576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460019074010000000000000000000000000000000000000000900460ff168114611e53576002546040517f81d1489b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910460ff166004820152602401610ac5565b600954831115611e9d576009546040517f5aaca4e4000000000000000000000000000000000000000000000000000000008152610ac5918591600401918252602082015260400190565b6000611ea7611608565b600754600a54611eb79190613413565b611ec19190613413565b905080841115611f07576040517f9abbab070000000000000000000000000000000000000000000000000000000081526004810185905260248101829052604401610ac5565b600b54600090611f179086613617565b9050348114611f5b576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b611f6533866127a1565b5050505050565b3380611f806002546001600160a01b031690565b6001600160a01b031614611fcb576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b50600f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b338061201a6002546001600160a01b031690565b6001600160a01b031614612065576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600280546001600160a01b038481167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b33806120e46002546001600160a01b031690565b6001600160a01b03161461212f576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b50600b91909155600c55565b8280600003612176576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805474010000000000000000000000000000000000000000900460ff169081148015906121a9575060ff8116600314155b156121e3576040517f81d1489b00000000000000000000000000000000000000000000000000000000815260026004820152602401610ac5565b33600285858860006121f786868686610c7c565b90508181101561223e576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b6000612248611608565b600754600a546122589190613413565b6122629190613413565b9050808c11156122a8576040517f9abbab07000000000000000000000000000000000000000000000000000000008152600481018d905260248101829052604401610ac5565b600c546000906122b8908e613617565b90503481146122fc576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b3360009081527f89832631fb3c3307a103ba2c84ab569c64d6182a18893dcd163f0f1c2090733a6020526040902080548e0190556118a5565b60008160000361234757506000919050565b506006541190565b60008181526012602052604081205482906001600160a01b03165b6001600160a01b0381166113555781612382816135e2565b6000818152601260205260409020549093506001600160a01b0316915061236a9050565b600080846001600160a01b0316846001600160a01b031614806123e257506123cd83610a84565b6001600160a01b0316846001600160a01b0316145b8061241257506001600160a01b0380861660009081526011602090815260408083209388168352929052205460ff165b95945050505050565b6000610c77611608565b6040805160ff851660208201529081018390526001600160a01b038516606082015260009081906080016040516020818303038152906040528051906020012090506000600182856040015186600001518760200151604051600081526020016040526040516124b1949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124d3573d6000803e3d6000fd5b5050604051601f1901516004546001600160a01b0390811691161498975050505050505050565b600081815260106020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556001821161253d576001612548565b612548600183613413565b905060006125578360016135cf565b90506000838310801561256e575061256e83612335565b801561258f57506000838152601260205260409020546001600160a01b0316155b9050600061259c83612335565b80156125bd57506000838152601260205260409020546001600160a01b0316155b9050811561260557600084815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b801561264b57600083815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b60008581526012602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a811691821790925591518893918b16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b6000808215806126d35750600054155b156126ed5750506001546001600160a01b0316600061271c565b6000612710846000546127009190613617565b61270a9190613702565b6001546001600160a01b031693509150505b9250929050565b6002805460ff838116740100000000000000000000000000000000000000008181027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff85161790945560405193909204169182907f7285522ec93a20dcefa1a1d057094a227073a5463b91c0c19a23c6ef5c9c1fe490600090a35050565b60065460006127b083836135cf565b905060006127bf600183613413565b600084815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03881617905590508281111561284857600081815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b6006829055825b828110156114ea5760405181906001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461289881613426565b905061284f565b60035480801561119f57808060019003915050826001600160a01b0316600382815481106128cf576128cf6135a0565b6000918252602090912001546001600160a01b03160361119f57816128f58260016135cf565b14612972576003612907600184613413565b81548110612917576129176135a0565b600091825260209091200154600380546001600160a01b039092169183908110612943576129436135a0565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b600380548061298357612983613716565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505050565b6000833b8015612b3f576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063150b7a0290612a359033908a9089908990600401613745565b6020604051808303816000875af1925050508015612a70575060408051601f3d908101601f19168201909252612a6d91810190613781565b60015b612af2573d808015612a9e576040519150601f19603f3d011682016040523d82523d6000602084013e612aa3565b606091505b508051600003612aea576040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149150610dac9050565b6001915050610dac565b606081600003612b8c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612bb65780612ba081613426565b9150612baf9050600a83613702565b9150612b90565b60008167ffffffffffffffff811115612bd157612bd1612ee1565b6040519080825280601f01601f191660200182016040528015612bfb576020820181803683370190505b5090505b8415610dac57612c10600183613413565b9150612c1d600a8661379e565b612c289060306135cf565b60f81b818381518110612c3d57612c3d6135a0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612c77600a86613702565b9450612bff565b612710811115612cc5576040517f4ec3fd3a000000000000000000000000000000000000000000000000000000008152600481018290526127106024820152604401610ac5565b600055600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6003545b8015612d5557808060019003915050816001600160a01b031660038281548110612d3257612d326135a0565b6000918252602090912001546001600160a01b031603612d50575050565b612d06565b50600380546001810182556000919091527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612dee57600080fd5b50565b600060208284031215612e0357600080fd5b813561135581612dc0565b60005b83811015612e29578181015183820152602001612e11565b50506000910152565b60008151808452612e4a816020860160208601612e0e565b601f01601f19169290920160200192915050565b6020815260006113556020830184612e32565b600060208284031215612e8357600080fd5b5035919050565b80356001600160a01b0381168114612ea157600080fd5b919050565b60008060408385031215612eb957600080fd5b612ec283612e8a565b946020939093013593505050565b803560ff81168114612ea157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612f3957612f39612ee1565b604052919050565b600060608284031215612f5357600080fd5b6040516060810181811067ffffffffffffffff82111715612f7657612f76612ee1565b80604052508091508235815260208301356020820152612f9860408401612ed0565b60408201525092915050565b60008060008060c08587031215612fba57600080fd5b612fc385612e8a565b9350612fd160208601612ed0565b925060408501359150612fe78660608701612f41565b905092959194509250565b60008060006060848603121561300757600080fd5b61301084612e8a565b925061301e60208501612e8a565b9150604084013590509250925092565b6000806040838503121561304157600080fd5b50508035926020909101359150565b600067ffffffffffffffff83111561306a5761306a612ee1565b61307d6020601f19601f86011601612f10565b905082815283838301111561309157600080fd5b828260208301376000602084830101529392505050565b6000602082840312156130ba57600080fd5b813567ffffffffffffffff8111156130d157600080fd5b8201601f810184136130e257600080fd5b610dac84823560208401613050565b60006020828403121561310357600080fd5b61135582612ed0565b600067ffffffffffffffff82111561312657613126612ee1565b5060051b60200190565b600082601f83011261314157600080fd5b813560206131566131518361310c565b612f10565b82815260059290921b8401810191818101908684111561317557600080fd5b8286015b848110156131905780358352918301918301613179565b509695505050505050565b600080604083850312156131ae57600080fd5b823567ffffffffffffffff808211156131c657600080fd5b818501915085601f8301126131da57600080fd5b813560206131ea6131518361310c565b82815260059290921b8401810191818101908984111561320957600080fd5b948201945b8386101561322e5761321f86612e8a565b8252948201949082019061320e565b9650508601359250508082111561324457600080fd5b5061325185828601613130565b9150509250929050565b60006020828403121561326d57600080fd5b61135582612e8a565b600080600060a0848603121561328b57600080fd5b83359250602084013591506132a38560408601612f41565b90509250925092565b600080604083850312156132bf57600080fd5b6132c883612e8a565b9150602083013580151581146132dd57600080fd5b809150509250929050565b600080600080608085870312156132fe57600080fd5b61330785612e8a565b935061331560208601612e8a565b925060408501359150606085013567ffffffffffffffff81111561333857600080fd5b8501601f8101871361334957600080fd5b61335887823560208401613050565b91505092959194509250565b6000806040838503121561337757600080fd5b61338083612e8a565b915061338e60208401612e8a565b90509250929050565b600181811c908216806133ab57607f821691505b602082108103610ae9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109e9576109e96133e4565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613457576134576133e4565b5060010190565b601f82111561119f57600081815260208120601f850160051c810160208610156134855750805b601f850160051c820191505b818110156114ea57828155600101613491565b815167ffffffffffffffff8111156134be576134be612ee1565b6134d2816134cc8454613397565b8461345e565b602080601f83116001811461352557600084156134ef5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556114ea565b600085815260208120601f198616915b8281101561355457888601518255948401946001909101908401613535565b508582101561359057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b808201808211156109e9576109e96133e4565b6000816135f1576135f16133e4565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b80820281158282048414176109e9576109e96133e4565b600080845461363c81613397565b600182811680156136545760018114613687576136b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506136b6565b8860005260208060002060005b858110156136ad5781548a820152908401908201613694565b50505082870194505b5050505083516136ca818360208801612e0e565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613711576137116136d3565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60006001600160a01b038087168352808616602084015250836040830152608060608301526137776080830184612e32565b9695505050505050565b60006020828403121561379357600080fd5b815161135581612dc0565b6000826137ad576137ad6136d3565b50069056fea264697066735822122021de66c5fe474d20aac363c752bb1d02980438178ac105c1eb6fb63f5363ae5864736f6c63430008110033000000000000000000000000000000000000000000000000000000000000177000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000000000003700000000000000000000000004a5ab7a444f92254123bdaedbefec6a2218b22c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000c537069726974204761746573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025347000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102d15760003560e01c8063854cff2f11610179578063c87b56dd116100d6578063ef72f2761161008a578063f2fde38b11610064578063f2fde38b146107d3578063f7d97577146107f3578063ff21456b1461081357600080fd5b8063ef72f27614610780578063efd0cbf9146107a0578063f0f44260146107b357600080fd5b8063d37ce09f116100bb578063d37ce09f14610704578063e2e784d514610717578063e985e9c51461073757600080fd5b8063c87b56dd146106c4578063d0348b97146106e457600080fd5b80639a44f1fb1161012d578063a9aad58c11610112578063a9aad58c1461067a578063b88d4fde1461068f578063c50ef4d8146106af57600080fd5b80639a44f1fb1461062a578063a22cb4651461065a57600080fd5b80638da5cb5b1161015e5780638da5cb5b146105e257806395d89b411461060057806398c83a161461061557600080fd5b8063854cff2f146105af57806386c27ffc146105cf57600080fd5b806342842e0e116102325780636352211e116101e657806370a08231116101c057806370a082311461056557806373d74876146105855780637e9845f51461059a57600080fd5b80636352211e1461050557806367243482146105255780636dfa99fd1461054557600080fd5b806355f804b31161021757806355f804b31461049e5780635f89584e146104be57806363096509146104e557600080fd5b806342842e0e1461045e5780634f6ccce71461047e57600080fd5b80631a3f839d116102895780632a55205a1161026e5780632a55205a146103ea5780632f745c59146104295780633ccfd60b1461044957600080fd5b80631a3f839d146103aa57806323b872dd146103ca57600080fd5b8063081812fc116102ba578063081812fc1461032d578063095ea7b31461036557806318160ddd1461038757600080fd5b806301ffc9a7146102d657806306fdde031461030b575b600080fd5b3480156102e257600080fd5b506102f66102f1366004612df1565b610826565b60405190151581526020015b60405180910390f35b34801561031757600080fd5b506103206109ef565b6040516103029190612e5e565b34801561033957600080fd5b5061034d610348366004612e71565b610a84565b6040516001600160a01b039091168152602001610302565b34801561037157600080fd5b50610385610380366004612ea6565b610aef565b005b34801561039357600080fd5b5061039c610c6d565b604051908152602001610302565b3480156103b657600080fd5b5061039c6103c5366004612fa4565b610c7c565b3480156103d657600080fd5b506103856103e5366004612ff2565b610db4565b3480156103f657600080fd5b5061040a61040536600461302e565b610f1e565b604080516001600160a01b039093168352602083019190915201610302565b34801561043557600080fd5b5061039c610444366004612ea6565b610f7a565b34801561045557600080fd5b50610385611040565b34801561046a57600080fd5b50610385610479366004612ff2565b611184565b34801561048a57600080fd5b5061039c610499366004612e71565b6111a4565b3480156104aa57600080fd5b506103856104b93660046130a8565b6111ed565b3480156104ca57600080fd5b506104d3600181565b60405160ff9091168152602001610302565b3480156104f157600080fd5b506103856105003660046130f1565b611258565b34801561051157600080fd5b5061034d610520366004612e71565b611307565b34801561053157600080fd5b5061038561054036600461319b565b61135c565b34801561055157600080fd5b5061038561056036600461325b565b6114f2565b34801561057157600080fd5b5061039c61058036600461325b565b61155a565b34801561059157600080fd5b506104d3600481565b3480156105a657600080fd5b5061039c611608565b3480156105bb57600080fd5b506103856105ca36600461325b565b611619565b6103856105dd366004613276565b6116af565b3480156105ee57600080fd5b506002546001600160a01b031661034d565b34801561060c57600080fd5b506103206118be565b34801561062157600080fd5b506104d3600281565b34801561063657600080fd5b5060025474010000000000000000000000000000000000000000900460ff166104d3565b34801561066657600080fd5b506103856106753660046132ac565b6118d0565b34801561068657600080fd5b506104d3600081565b34801561069b57600080fd5b506103856106aa3660046132e8565b6119aa565b3480156106bb57600080fd5b506104d3600381565b3480156106d057600080fd5b506103206106df366004612e71565b611a02565b3480156106f057600080fd5b5061034d6106ff366004612e71565b611a9e565b610385610712366004613276565b611ac8565b34801561072357600080fd5b50610385610732366004612ea6565b611cce565b34801561074357600080fd5b506102f6610752366004613364565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205460ff1690565b34801561078c57600080fd5b5061038561079b36600461325b565b611d37565b6103856107ae366004612e71565b611d9f565b3480156107bf57600080fd5b506103856107ce36600461325b565b611f6c565b3480156107df57600080fd5b506103856107ee36600461325b565b612006565b3480156107ff57600080fd5b5061038561080e36600461302e565b6120d0565b610385610821366004613276565b61213b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806108b957507fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000145b8061090557507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061095157507fffffffff0000000000000000000000000000000000000000000000000000000082167f7f5828d000000000000000000000000000000000000000000000000000000000145b8061099d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b806109e957507fffffffff0000000000000000000000000000000000000000000000000000000082167f2a55205a00000000000000000000000000000000000000000000000000000000145b92915050565b606060096004018054610a0190613397565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2d90613397565b8015610a7a5780601f10610a4f57610100808354040283529160200191610a7a565b820191906000526020600020905b815481529060010190602001808311610a5d57829003601f168201915b5050505050905090565b600081610a9081612335565b610ace576040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6000838152601060205260409020546001600160a01b031691505b50919050565b80610af981612335565b610b32576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b336000610b3e8461234f565b9050806001600160a01b0316856001600160a01b031603610b96576040517ff2b21e1c0000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602401610ac5565b6000610ba38284876123a6565b905080610bf6576040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301528416602482015260448101869052606401610ac5565b60008581526010602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a811691821790925591518893918616917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050505050565b6000610c7761241b565b905090565b6004546000906001600160a01b0316610cc1576040517fc71bad4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff841660009081526005602090815260408083206001600160a01b03891684529091529020548311610d2b576040517f706e18b90000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602401610ac5565b610d3785858585612425565b610d78576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602401610ac5565b60ff841660009081526005602090815260408083206001600160a01b0389168452909152902054610da99084613413565b90505b949350505050565b80610dbe81612335565b610df7576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b6001600160a01b038316610e37576040517f14242cb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000610e438461234f565b9050806001600160a01b0316866001600160a01b031614610eaa576040517fe02b28e70000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528716602482015260448101859052606401610ac5565b6000610eb78284876123a6565b905080610f0a576040517f19f48dff0000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301528416602482015260448101869052606401610ac5565b610f158287876124fa565b50505050505050565b60008083610f2b81612335565b610f64576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b610f6e85856126c3565b92509250509250929050565b6000610f858361155a565b8210610fcf576040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604401610ac5565b600060015b60065481101561103857610fe781612335565b801561100c5750610ff78161234f565b6001600160a01b0316856001600160a01b0316145b15611028578184036110215791506109e99050565b6001909101905b61103181613426565b9050610fd4565b505092915050565b33806110546002546001600160a01b031690565b6001600160a01b03161461109f576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b4760008190036110db576040517f1f84313900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f546040516001600160a01b0390911690600090829084908381818185875af1925050503d806000811461112c576040519150601f19603f3d011682016040523d82523d6000602084013e611131565b606091505b505090508061117e576040517f84020a7b0000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260248101849052604401610ac5565b50505050565b61119f838383604051806020016040528060008152506119aa565b505050565b60006111ae611608565b82106111e9576040517f125c19b000000000000000000000000000000000000000000000000000000000815260048101839052602401610ac5565b5090565b33806112016002546001600160a01b031690565b6001600160a01b03161461124c576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600861119f83826134a4565b338061126c6002546001600160a01b031690565b6001600160a01b0316146112b7576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600460ff831611156112fa576040517f9b7c47a200000000000000000000000000000000000000000000000000000000815260ff83166004820152602401610ac5565b61130382612723565b5050565b60008161131381612335565b61134c576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b6113558361234f565b9392505050565b33806113706002546001600160a01b031690565b6001600160a01b0316146113bb576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b8151835181146113f7576040517f88adebd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b8015611444578461140d600183613413565b8151811061141d5761141d6135a0565b60200260200101518261143091906135cf565b91508061143c816135e2565b9150506113fb565b5060075481111561148f576007546040517f016c69db000000000000000000000000000000000000000000000000000000008152610ac5918391600401918252602082015260400190565b600780548290039055815b80156114ea578080600190039150506114e58682815181106114be576114be6135a0565b60200260200101518683815181106114d8576114d86135a0565b60200260200101516127a1565b61149a565b505050505050565b33806115066002546001600160a01b031690565b6001600160a01b031614611551576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b6113038261289f565b60006001600160a01b03821661157257506000919050565b60008060015b6006548110156115ff5761158b81612335565b156115ef576000818152601260205260409020546001600160a01b0316156115c8576000818152601260205260409020546001600160a01b031691505b816001600160a01b0316856001600160a01b0316036115ef57826115eb81613426565b9350505b6115f881613426565b9050611578565b50909392505050565b60006001600654610c779190613413565b338061162d6002546001600160a01b031690565b6001600160a01b031614611678576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555050565b82806000036116ea576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805474010000000000000000000000000000000000000000900460ff1690811480159061171d575060ff8116600314155b15611757576040517f81d1489b00000000000000000000000000000000000000000000000000000000815260026004820152602401610ac5565b336004858588600061176b86868686610c7c565b9050818110156117b2576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b60006117bc611608565b600754600a546117cc9190613413565b6117d69190613413565b9050808c111561181c576040517f9abbab07000000000000000000000000000000000000000000000000000000008152600481018d905260248101829052604401610ac5565b600c5460009061182c908e613617565b9050348114611870576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b3360009081527f3eec716f11ba9e820c81ca75eb978ffb45831ef8b7a53e5e422c26008e1ca6d56020526040902080548e0190555b6118af338e6127a1565b50505050505050505050505050565b606060096005018054610a0190613397565b336001600160a01b03831681900361191f576040517ff2b21e1c0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610ac5565b6001600160a01b0381811660008181526011602090815260408083209488168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6119b5848484610db4565b6119c1848484846129e0565b61117e576040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610ac5565b606081611a0e81612335565b611a47576040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ac5565b600060088054611a5690613397565b905011611a6b57611a6683612b49565b611355565b6008611a7684612b49565b604051602001611a8792919061362e565b604051602081830303815290604052915050919050565b60038181548110611aae57600080fd5b6000918252602090912001546001600160a01b0316905081565b8280600003611b03576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460039074010000000000000000000000000000000000000000900460ff168114611b7c576002546040517f81d1489b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910460ff166004820152602401610ac5565b3360038585886000611b9086868686610c7c565b905081811015611bd7576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b6000611be1611608565b600754600a54611bf19190613413565b611bfb9190613413565b9050808c1115611c41576040517f9abbab07000000000000000000000000000000000000000000000000000000008152600481018d905260248101829052604401610ac5565b600c54600090611c51908e613617565b9050348114611c95576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b3360009081527fa9bc9a3a348c357ba16b37005d7e6b3236198c0e939f4af8c5f19b8deeb8ebc06020526040902080548e0190556118a5565b3380611ce26002546001600160a01b031690565b6001600160a01b031614611d2d576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b61119f8383612c7e565b3380611d4b6002546001600160a01b031690565b6001600160a01b031614611d96576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b61130382612d02565b8080600003611dda576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460019074010000000000000000000000000000000000000000900460ff168114611e53576002546040517f81d1489b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910460ff166004820152602401610ac5565b600954831115611e9d576009546040517f5aaca4e4000000000000000000000000000000000000000000000000000000008152610ac5918591600401918252602082015260400190565b6000611ea7611608565b600754600a54611eb79190613413565b611ec19190613413565b905080841115611f07576040517f9abbab070000000000000000000000000000000000000000000000000000000081526004810185905260248101829052604401610ac5565b600b54600090611f179086613617565b9050348114611f5b576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b611f6533866127a1565b5050505050565b3380611f806002546001600160a01b031690565b6001600160a01b031614611fcb576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b50600f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b338061201a6002546001600160a01b031690565b6001600160a01b031614612065576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b600280546001600160a01b038481167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b33806120e46002546001600160a01b031690565b6001600160a01b03161461212f576040517f55932a1b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610ac5565b50600b91909155600c55565b8280600003612176576040517f7fcfed3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805474010000000000000000000000000000000000000000900460ff169081148015906121a9575060ff8116600314155b156121e3576040517f81d1489b00000000000000000000000000000000000000000000000000000000815260026004820152602401610ac5565b33600285858860006121f786868686610c7c565b90508181101561223e576040517ff9790dfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b6000612248611608565b600754600a546122589190613413565b6122629190613413565b9050808c11156122a8576040517f9abbab07000000000000000000000000000000000000000000000000000000008152600481018d905260248101829052604401610ac5565b600c546000906122b8908e613617565b90503481146122fc576040517ff01adace00000000000000000000000000000000000000000000000000000000815234600482015260248101829052604401610ac5565b3360009081527f89832631fb3c3307a103ba2c84ab569c64d6182a18893dcd163f0f1c2090733a6020526040902080548e0190556118a5565b60008160000361234757506000919050565b506006541190565b60008181526012602052604081205482906001600160a01b03165b6001600160a01b0381166113555781612382816135e2565b6000818152601260205260409020549093506001600160a01b0316915061236a9050565b600080846001600160a01b0316846001600160a01b031614806123e257506123cd83610a84565b6001600160a01b0316846001600160a01b0316145b8061241257506001600160a01b0380861660009081526011602090815260408083209388168352929052205460ff165b95945050505050565b6000610c77611608565b6040805160ff851660208201529081018390526001600160a01b038516606082015260009081906080016040516020818303038152906040528051906020012090506000600182856040015186600001518760200151604051600081526020016040526040516124b1949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124d3573d6000803e3d6000fd5b5050604051601f1901516004546001600160a01b0390811691161498975050505050505050565b600081815260106020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556001821161253d576001612548565b612548600183613413565b905060006125578360016135cf565b90506000838310801561256e575061256e83612335565b801561258f57506000838152601260205260409020546001600160a01b0316155b9050600061259c83612335565b80156125bd57506000838152601260205260409020546001600160a01b0316155b9050811561260557600084815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b801561264b57600083815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b60008581526012602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a811691821790925591518893918b16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b6000808215806126d35750600054155b156126ed5750506001546001600160a01b0316600061271c565b6000612710846000546127009190613617565b61270a9190613702565b6001546001600160a01b031693509150505b9250929050565b6002805460ff838116740100000000000000000000000000000000000000008181027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff85161790945560405193909204169182907f7285522ec93a20dcefa1a1d057094a227073a5463b91c0c19a23c6ef5c9c1fe490600090a35050565b60065460006127b083836135cf565b905060006127bf600183613413565b600084815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03881617905590508281111561284857600081815260126020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b6006829055825b828110156114ea5760405181906001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461289881613426565b905061284f565b60035480801561119f57808060019003915050826001600160a01b0316600382815481106128cf576128cf6135a0565b6000918252602090912001546001600160a01b03160361119f57816128f58260016135cf565b14612972576003612907600184613413565b81548110612917576129176135a0565b600091825260209091200154600380546001600160a01b039092169183908110612943576129436135a0565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b600380548061298357612983613716565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505050565b6000833b8015612b3f576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063150b7a0290612a359033908a9089908990600401613745565b6020604051808303816000875af1925050508015612a70575060408051601f3d908101601f19168201909252612a6d91810190613781565b60015b612af2573d808015612a9e576040519150601f19603f3d011682016040523d82523d6000602084013e612aa3565b606091505b508051600003612aea576040517f015be56a0000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610ac5565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149150610dac9050565b6001915050610dac565b606081600003612b8c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612bb65780612ba081613426565b9150612baf9050600a83613702565b9150612b90565b60008167ffffffffffffffff811115612bd157612bd1612ee1565b6040519080825280601f01601f191660200182016040528015612bfb576020820181803683370190505b5090505b8415610dac57612c10600183613413565b9150612c1d600a8661379e565b612c289060306135cf565b60f81b818381518110612c3d57612c3d6135a0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612c77600a86613702565b9450612bff565b612710811115612cc5576040517f4ec3fd3a000000000000000000000000000000000000000000000000000000008152600481018290526127106024820152604401610ac5565b600055600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6003545b8015612d5557808060019003915050816001600160a01b031660038281548110612d3257612d326135a0565b6000918252602090912001546001600160a01b031603612d50575050565b612d06565b50600380546001810182556000919091527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612dee57600080fd5b50565b600060208284031215612e0357600080fd5b813561135581612dc0565b60005b83811015612e29578181015183820152602001612e11565b50506000910152565b60008151808452612e4a816020860160208601612e0e565b601f01601f19169290920160200192915050565b6020815260006113556020830184612e32565b600060208284031215612e8357600080fd5b5035919050565b80356001600160a01b0381168114612ea157600080fd5b919050565b60008060408385031215612eb957600080fd5b612ec283612e8a565b946020939093013593505050565b803560ff81168114612ea157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612f3957612f39612ee1565b604052919050565b600060608284031215612f5357600080fd5b6040516060810181811067ffffffffffffffff82111715612f7657612f76612ee1565b80604052508091508235815260208301356020820152612f9860408401612ed0565b60408201525092915050565b60008060008060c08587031215612fba57600080fd5b612fc385612e8a565b9350612fd160208601612ed0565b925060408501359150612fe78660608701612f41565b905092959194509250565b60008060006060848603121561300757600080fd5b61301084612e8a565b925061301e60208501612e8a565b9150604084013590509250925092565b6000806040838503121561304157600080fd5b50508035926020909101359150565b600067ffffffffffffffff83111561306a5761306a612ee1565b61307d6020601f19601f86011601612f10565b905082815283838301111561309157600080fd5b828260208301376000602084830101529392505050565b6000602082840312156130ba57600080fd5b813567ffffffffffffffff8111156130d157600080fd5b8201601f810184136130e257600080fd5b610dac84823560208401613050565b60006020828403121561310357600080fd5b61135582612ed0565b600067ffffffffffffffff82111561312657613126612ee1565b5060051b60200190565b600082601f83011261314157600080fd5b813560206131566131518361310c565b612f10565b82815260059290921b8401810191818101908684111561317557600080fd5b8286015b848110156131905780358352918301918301613179565b509695505050505050565b600080604083850312156131ae57600080fd5b823567ffffffffffffffff808211156131c657600080fd5b818501915085601f8301126131da57600080fd5b813560206131ea6131518361310c565b82815260059290921b8401810191818101908984111561320957600080fd5b948201945b8386101561322e5761321f86612e8a565b8252948201949082019061320e565b9650508601359250508082111561324457600080fd5b5061325185828601613130565b9150509250929050565b60006020828403121561326d57600080fd5b61135582612e8a565b600080600060a0848603121561328b57600080fd5b83359250602084013591506132a38560408601612f41565b90509250925092565b600080604083850312156132bf57600080fd5b6132c883612e8a565b9150602083013580151581146132dd57600080fd5b809150509250929050565b600080600080608085870312156132fe57600080fd5b61330785612e8a565b935061331560208601612e8a565b925060408501359150606085013567ffffffffffffffff81111561333857600080fd5b8501601f8101871361334957600080fd5b61335887823560208401613050565b91505092959194509250565b6000806040838503121561337757600080fd5b61338083612e8a565b915061338e60208401612e8a565b90509250929050565b600181811c908216806133ab57607f821691505b602082108103610ae9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109e9576109e96133e4565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613457576134576133e4565b5060010190565b601f82111561119f57600081815260208120601f850160051c810160208610156134855750805b601f850160051c820191505b818110156114ea57828155600101613491565b815167ffffffffffffffff8111156134be576134be612ee1565b6134d2816134cc8454613397565b8461345e565b602080601f83116001811461352557600084156134ef5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556114ea565b600085815260208120601f198616915b8281101561355457888601518255948401946001909101908401613535565b508582101561359057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b808201808211156109e9576109e96133e4565b6000816135f1576135f16133e4565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b80820281158282048414176109e9576109e96133e4565b600080845461363c81613397565b600182811680156136545760018114613687576136b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506136b6565b8860005260208060002060005b858110156136ad5781548a820152908401908201613694565b50505082870194505b5050505083516136ca818360208801612e0e565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613711576137116136d3565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60006001600160a01b038087168352808616602084015250836040830152608060608301526137776080830184612e32565b9695505050505050565b60006020828403121561379357600080fd5b815161135581612dc0565b6000826137ad576137ad6136d3565b50069056fea264697066735822122021de66c5fe474d20aac363c752bb1d02980438178ac105c1eb6fb63f5363ae5864736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000177000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000000000003700000000000000000000000004a5ab7a444f92254123bdaedbefec6a2218b22c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000c537069726974204761746573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025347000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : maxSupply_ (uint256): 6000
Arg [1] : maxBatch_ (uint256): 5
Arg [2] : reserve_ (uint256): 100
Arg [3] : salePrice_ (uint256): 80000000000000000
Arg [4] : royaltyRate_ (uint256): 880
Arg [5] : treasury_ (address): 0x4A5AB7A444F92254123BDAedbefec6a2218B22c0
Arg [6] : name_ (string): Spirit Gates
Arg [7] : symbol_ (string): SG
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000001770
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [3] : 000000000000000000000000000000000000000000000000011c37937e080000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000370
Arg [5] : 0000000000000000000000004a5ab7a444f92254123bdaedbefec6a2218b22c0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [9] : 5370697269742047617465730000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [11] : 5347000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.