ERC-721
NFT
Overview
Max Total Supply
1,930 ERCC
Holders
698
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 ERCCLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
ChainLinkNeowizERC721
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import "./libs/@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./libs/@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "./libs/@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "./NeowizERC721.sol"; contract ChainLinkNeowizERC721 is VRFConsumerBaseV2, NeowizERC721 { uint64 public subscriptionId; VRFCoordinatorV2Interface public COORDINATOR; /// @param _name The name of the token /// @param _symbol The symbol of the token /// @param _maxTotalSupply The max token amount allowed to mint regardless of how many tokens are burnt. /// @param _teamSupply The token amount reserved for team /// @param _team The address to receive tokens in team-minting /// @param _payment The address of token to pay when minting. Set zero to use ETH. /// @param _unrevealedURI The ipfs uri of metadata before reveal /// @param _trustedForwarder The address of ERC2771 forwarder /// @param _subscriptionId Your chainlink subscriptionId. Constants from https://docs.chain.link/docs/vrf-contracts/ /// @param _vrfCoordinator Chainlink vrfCoordinator in the network. See https://docs.chain.link/docs/vrf-contracts/#configurations constructor( string memory _name, string memory _symbol, uint256 _maxTotalSupply, uint256 _teamSupply, address _team, address _payment, string memory _unrevealedURI, address _trustedForwarder, uint64 _subscriptionId, address _vrfCoordinator, SalesInfo memory _salesInfo ) VRFConsumerBaseV2(_vrfCoordinator) NeowizERC721( _name, _symbol, _maxTotalSupply, _teamSupply, _team, _payment, _unrevealedURI, _trustedForwarder, _salesInfo ) { subscriptionId = _subscriptionId; COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); } /// @notice Request random number through Chainlink VRF. /// @dev The callback `_setRandomSeed` requires all tokens to be minted. /// @param _keyHash Chainlink-provided Key Hash /// @param _requestConfirmations Variable number of confirmations /// @param _callbackGasLimit Callback function gas limit function requestRandomSeed( bytes32 _keyHash, uint16 _requestConfirmations, // 3 uint32 _callbackGasLimit // 100000 ) external whenSoldout onlyOperator { COORDINATOR.requestRandomWords( _keyHash, subscriptionId, _requestConfirmations, _callbackGasLimit, 1 // numWords ); } function fulfillRandomWords(uint256, /* requestId */ uint256[] memory _randomWords) internal override { _setRandomSeed(_randomWords[0]); } }
//SPDX-License-Identifier: MIT // Reference: https://github.com/dievardump/erc721-with-permits/blob/main/contracts/ERC721WithPermit.sol pragma solidity 0.8.23; import "../libs/@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "../libs/@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import "../libs/@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./IERC721WithPermit.sol"; /// @title ERC721WithPermit /// @author Simon Fremaux (@dievardump) & William Schwab (@wschwab) /// @notice This implementation of Permits links the nonce to the tokenId instead of the owner /// This way, it is possible for a same account to create several usable permits at the same time, /// for different ids /// /// This implementation overrides _transfer and increments the nonce linked to a tokenId /// every time it is transfered abstract contract ERC721WithPermit is IERC721WithPermit, ERC721 { bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)"); mapping(uint256 => uint256) private _nonces; // this are saved as immutable for cheap access // the chainId is also saved to be able to recompute domainSeparator // in the case of a fork bytes32 private immutable _domainSeparator; uint256 private immutable _domainChainId; constructor() { uint256 chainId; //solhint-disable-next-line no-inline-assembly assembly { chainId := chainid() } _domainChainId = chainId; _domainSeparator = _calculateDomainSeparator(chainId); } /// @notice Builds the DOMAIN_SEPARATOR (eip712) at time of use /// @dev This is not set as a constant, to ensure that the chainId will change in the event of a chain fork /// @return the DOMAIN_SEPARATOR of eip712 function DOMAIN_SEPARATOR() public view returns (bytes32) { uint256 chainId; //solhint-disable-next-line no-inline-assembly assembly { chainId := chainid() } return (chainId == _domainChainId) ? _domainSeparator : _calculateDomainSeparator(chainId); } function _calculateDomainSeparator(uint256 chainId) internal view returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name())), keccak256(bytes("1")), chainId, address(this) ) ); } /// @notice Allows to retrieve current nonce for token /// @param tokenId token id /// @return current token nonce function nonces(uint256 tokenId) public view returns (uint256) { require(_exists(tokenId), "!UNKNOWN_TOKEN!"); return _nonces[tokenId]; } /// @notice function to be called by anyone to approve `spender` using a Permit signature /// @dev Anyone can call this to approve `spender`, even a third-party /* /// @param owner the owner of the token */ /// @param spender the actor to approve /// @param tokenId the token id /// @param deadline the deadline for the permit to be used /// @param signature permit function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory signature) public { require(deadline >= block.timestamp, "!PERMIT_DEADLINE_EXPIRED!"); bytes32 digest = _buildDigest( // owner, spender, tokenId, _nonces[tokenId], deadline ); (address recoveredAddress, ) = ECDSA.tryRecover(digest, signature); require( // verify if the recovered address is owner or approved on tokenId // and make sure recoveredAddress is not address(0), else getApproved(tokenId) might match (recoveredAddress != address(0) && _isApprovedOrOwner(recoveredAddress, tokenId)) || // else try to recover signature using SignatureChecker, which also allows to recover signature made by contracts SignatureChecker.isValidSignatureNow(ownerOf(tokenId), digest, signature), "!INVALID_PERMIT_SIGNATURE!" ); _approve(spender, tokenId); } /// @notice Builds the permit digest to sign /// @param spender the token spender /// @param tokenId the tokenId /// @param nonce the nonce to make a permit for /// @param deadline the deadline before when the permit can be used /// @return the digest (following eip712) to sign function _buildDigest( address spender, uint256 tokenId, uint256 nonce, uint256 deadline ) public view returns (bytes32) { return ECDSA.toTypedDataHash( DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonce, deadline)) ); } /// @dev helper to easily increment a nonce for a given tokenId /// @param tokenId the tokenId to increment the nonce for function _incrementNonce(uint256 tokenId) internal { _nonces[tokenId]++; } /// @dev _transfer override to be able to increment the nonce /// @inheritdoc ERC721 function _transfer(address from, address to, uint256 tokenId) internal virtual override { // increment the nonce to be sure it can't be reused _incrementNonce(tokenId); // do normal transfer super._transfer(from, to, tokenId); } /// @notice Query if a contract implements an interface /// @param interfaceId The interface identifier, as specified in ERC-165 /// @dev Overriden from ERC721 here in order to include the interface of this EIP /// @return `true` if the contract implements `interfaceID` and /// `interfaceID` is not 0xffffffff, `false` otherwise function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC721WithPermit).interfaceId || // 0x5604e225 super.supportsInterface(interfaceId); } }
//SPDX-License-Identifier: MIT // Reference: https://github.com/dievardump/erc721-with-permits/blob/main/contracts/IERC721WithPermit.sol pragma solidity 0.8.23; import "../libs/@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "../libs/@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import "../libs/@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /// @title IERC721WithPermit /// @author Simon Fremaux (@dievardump) & William Schwab /// @notice Required interface interface IERC721WithPermit { function DOMAIN_SEPARATOR() external view returns (bytes32); /// @notice Allows to retrieve current nonce for token /// @param tokenId token id /// @return current token nonce function nonces(uint256 tokenId) external view returns (uint256); /// @notice function to be called by anyone to approve `spender` using a Permit signature /// @dev Anyone can call this to approve `spender`, even a third-party /// @param spender the actor to approve /// @param tokenId the token id /// @param deadline the deadline for the permit to be used /// @param signature permit function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory signature) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; interface INeowizERC721 { event PaymentUpdated(address payment); event UnrevealedURIUpdated(string uri); event RoundAdded( uint256 indexed roundId, uint256 state, uint256 maxMintPerAccount, uint256 maxMint, uint256 price, bytes32 merkleRoot, uint256 startTs, uint256 endTs ); event StateUpdated(uint256 indexed roundId, uint256 state); event MaxMintUpdated(uint256 indexed roundId, uint256 maxMint); event MaxMintPerAccountUpdated(uint256 indexed roundId, uint256 maxMint); event PriceUpdated(uint256 indexed roundId, uint256 price); event MerkleRootUpdated(uint256 indexed roundId, bytes32 merkleRoot); event RoundTimestampUpdated(uint256 indexed roundId, uint256 startTs, uint256 endTs); event BaseURIUpdated(string uri); event RoyaltyInfoUpdated(address receiver, uint96 feeBasisPoints); event Revealed(); event NewOperator(address operator); function isRevealed() external returns (bool); function burn(uint256 _tokenId) external; function randomSeed() external view returns (uint256); function MAX_TOTAL_SUPPLY() external view returns (uint256); function TEAM_SUPPLY() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Receiver.sol) pragma solidity ^0.8.0; interface IERC1363Receiver { /* * Note: the ERC-165 identifier for this interface is 0x88a7ca5c. * 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)")) */ /** * @notice Handle the receipt of ERC1363 tokens * @dev Any ERC1363 smart contract calls this function on the recipient * after a `transfer` or a `transferFrom`. 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 token contract address is always the message sender. * @param operator address The address which called `transferAndCall` or `transferFromAndCall` function * @param from address The address which are token transferred from * @param value uint256 The amount of tokens transferred * @param data bytes Additional data with no specified format * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` * unless throwing */ function onTransferReceived( address operator, address from, uint256 value, bytes memory data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Spender.sol) pragma solidity ^0.8.0; interface IERC1363Spender { /* * Note: the ERC-165 identifier for this interface is 0x7b04a2d0. * 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)")) */ /** * @notice Handle the approval of ERC1363 tokens * @dev Any ERC1363 smart contract calls this function on the recipient * after an `approve`. This function MAY throw to revert and reject the * approval. Return of other than the magic value MUST result in the * transaction being reverted. * Note: the token contract address is always the message sender. * @param owner address The address which called `approveAndCall` function * @param value uint256 The amount of tokens to be spent * @param data bytes Additional data with no specified format * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` * unless throwing */ function onApprovalReceived( address owner, uint256 value, bytes memory data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol) pragma solidity ^0.8.0; import "../../interfaces/IERC2981.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981 */ function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) { RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId]; if (royalty.receiver == address(0)) { royalty = _defaultRoyaltyInfo; } uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator(); return (royalty.receiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: invalid receiver"); _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty( uint256 tokenId, address receiver, uint96 feeNumerator ) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: Invalid parameters"); _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol) pragma solidity ^0.8.0; import "./draft-IERC20Permit.sol"; import "../ERC20.sol"; import "../../../utils/cryptography/draft-EIP712.sol"; import "../../../utils/cryptography/ECDSA.sol"; import "../../../utils/Counters.sol"; /** * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * _Available since v3.4._ */ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { using Counters for Counters.Counter; mapping(address => Counters.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /** * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. * However, to ensure consistency with the upgradeable transpiler, we will continue * to reserve a slot. * @custom:oz-renamed-from _PERMIT_TYPEHASH */ // solhint-disable-next-line var-name-mixedcase bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ constructor(string memory name) EIP712(name, "1") {} /** * @dev See {IERC20Permit-permit}. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual override { require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _approve(owner, spender, value); } /** * @dev See {IERC20Permit-nonces}. */ function nonces(address owner) public view virtual override returns (uint256) { return _nonces[owner].current(); } /** * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } /** * @dev "Consume a nonce": return the current value and increment. * * _Available since v4.1._ */ function _useNonce(address owner) internal virtual returns (uint256 current) { Counters.Counter storage nonce = _nonces[owner]; current = nonce.current(); nonce.increment(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721Burnable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../../utils/Context.sol"; /** * @title ERC721 Burnable Token * @dev ERC721 Token that can be burned (destroyed). */ abstract contract ERC721Burnable is Context, ERC721 { /** * @dev Burns `tokenId`. See {ERC721-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) public virtual { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _burn(tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/ERC721Royalty.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../common/ERC2981.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment * information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC721Royalty is ERC2981, ERC721 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) { return super.supportsInterface(interfaceId); } /** * @dev See {ERC721-_burn}. This override additionally clears the royalty information for the token. */ function _burn(uint256 tokenId) internal virtual override { super._burn(tokenId); _resetTokenRoyalty(tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`, * consuming from one or the other at each step according to the instructions given by * `proofFlags`. * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof} * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.1) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; import "../Address.sol"; import "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * _Available since v4.1._ */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature); if (error == ECDSA.RecoverError.NoError && recovered == signer) { return true; } (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature) ); return (success && result.length == 32 && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // 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 Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /// @notice OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol) import "../libs/@openzeppelin/contracts/utils/Context.sol"; /** * @dev Context variant with ERC2771 support using a non-immutable storage variable. */ abstract contract ERC2771ContextFromStorage is Context { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal _trustedForwarder; event NewTrustedForwarder(address indexed trustedForwarder); /// @custom:oz-upgrades-unsafe-allow constructor constructor(address trustedForwarder) { _trustedForwarder = trustedForwarder; } function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view virtual override returns (address sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. /// @solidity memory-safe-assembly assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } else { return super._msgSender(); } } function _msgData() internal view virtual override returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return super._msgData(); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import "./libs/@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./libs/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol"; import "./libs/@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; import "./libs/@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol"; import "./libs/@openzeppelin/contracts/access/Ownable.sol"; import "./libs/@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "./libs/@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "./libs/@openzeppelin/contracts/interfaces/IERC1363Receiver.sol"; import "./libs/@openzeppelin/contracts/interfaces/IERC1363Spender.sol"; import "./metatx/ERC2771ContextFromStorage.sol"; import "./erc721-permits/ERC721WithPermit.sol"; import "./interfaces/INeowizERC721.sol"; /** * @title NeowiERC721 * @notice The minting process goes as follows. * 0. setBaseURI * 1. teamMint: The contract owner can call anytime even during the minting round. It is usually called before the first minting round starts. * 2. privateMint, publicMint: The total mintable amount in the last round is (round.maxMint + leftover amounts in the previous rounds). * 3. mintResidue: The owner should mint all to reveal the collection. * 4. requestRandomSeed: To reveal, the contract owner should call this function to get the random seed. */ abstract contract NeowizERC721 is INeowizERC721, IERC1363Receiver, IERC1363Spender, ERC721Burnable, ERC721Royalty, ERC721WithPermit, ERC2771ContextFromStorage, ReentrancyGuard, Ownable { error NotExistingRound(); error ZeroMaxTotalSupply(); error WrongSaleRound(); error RoundNotStarted(); error InvalidTimestamp(); error RoundEnded(); error NotPublic(); error NotPrivate(); error NotSoldout(); error NotAllRoundsFinished(); error IncorrectProof(); error NotEnoughFund(); error NotEnoughERC20Fund(); error PriceNotSet(); error MaxMintExceeded(uint256 round); error MaxMintPerAccountExceeded(uint256 round, address account); error MaxTotalSupplyExceeded(); error MaxTotalTeamMintExceeded(); error AlreadyRevealed(); error InvalidCollectorRatio(); error AddressZero(); address public immutable team; // base uri for nfts string private baseURI; // Valid currentRound starts from 1, and default is 0. uint256 private _currentRound; // The next token ID to be team-minted. uint256 private _currentTeamIndex; // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Operator address private _operator; uint256 public numRounds; mapping(uint256 => Round) public rounds; address public payment; uint256 public randomSeed; bool public revealed; string public unrevealedURI; uint256 public immutable TEAM_SUPPLY; uint256 public immutable MAX_TOTAL_SUPPLY; struct SalesInfo { address collector1; address collector2; uint16 collector1Ratio; } SalesInfo public salesInfo; uint16 public constant ratioDenominator = 10000; enum SaleState { PRIVATE, PUBLIC } /** * @dev In a round, users can mint until `round.totalMinted` == `round.maxMint`. * If it is the last round, users can mint more than maxMint until totalSupply() == MAX_TOTAL_SUPPLY. * `numberMinted` is necessary to allow users to mint multiple times in a round, * as long as they have minted less than `MAX_MINT_PER_ACCOUNT` in the round.; * @param state The minting round proceeds like CLOSED -> OG -> WL -> PUBLIC_0 -> PUBLIC_1. * However, any rounds may be omitted, i.e. a minting with only WL round is possible. */ struct Round { mapping(address => uint256) numberMinted; uint256 maxMintPerAccount; uint256 maxMint; uint256 totalMinted; uint256 price; SaleState state; bytes32 merkleRoot; uint64 startTs; uint64 endTs; } /// @param _name name in ERC721 /// @param _symbol symbol in ERC721 /// @param _maxTotalSupply The max number of NFTs to be minted /// @param _teamSupply The reserved quantity for team /// @param _team address of team /// @param _payment address of ERC20 token to be paid when minting NFT. address(0) is ETH. /// @param _unrevealedURI ipfs uri when NFT has not yet revealed /// @param _trustedForwarder address of ERC2771 forwarder constructor( string memory _name, string memory _symbol, uint256 _maxTotalSupply, uint256 _teamSupply, address _team, address _payment, string memory _unrevealedURI, address _trustedForwarder, SalesInfo memory _salesInfo ) ERC721(_name, _symbol) ERC2771ContextFromStorage(_trustedForwarder) { if (_salesInfo.collector1 == address(0) || _salesInfo.collector2 == address(0)) { revert AddressZero(); } if (_maxTotalSupply == 0) { revert ZeroMaxTotalSupply(); } if (_salesInfo.collector1Ratio > ratioDenominator) { revert InvalidCollectorRatio(); } MAX_TOTAL_SUPPLY = _maxTotalSupply; TEAM_SUPPLY = _currentIndex = _teamSupply; team = _team; payment = _payment; unrevealedURI = _unrevealedURI; salesInfo = _salesInfo; } modifier onlyOperator() { require( operator() == _msgSender() || owner() == _msgSender(), "NeowizERC721: caller is not the operator or owner" ); _; } modifier whenSoldout() { if (totalMinted() < MAX_TOTAL_SUPPLY) { revert NotSoldout(); } _; } modifier inRound(uint256 _round) { Round storage round = rounds[_round]; if (numRounds < _round) { revert WrongSaleRound(); } if (block.timestamp < round.startTs) { revert RoundNotStarted(); } if (round.endTs <= block.timestamp) { revert RoundEnded(); } _; } modifier isPublic(uint256 _round) { if (rounds[_round].state != SaleState.PUBLIC) { revert NotPublic(); } _; } modifier isPrivate(uint256 _round) { SaleState state = rounds[_round].state; if (state != SaleState.PRIVATE) { revert NotPrivate(); } _; } modifier checkRound(uint256 _roundId) { if (numRounds < _roundId) { revert NotExistingRound(); } _; } /// @dev onlyOwner function setOperator(address newOperator) external onlyOwner { require(newOperator != address(0), "NeowizERC721: new operator is the zero address"); _setOperator(newOperator); } /// @dev onlyOwner function setTrustedForwarder(address _forwarder) external onlyOwner { _trustedForwarder = _forwarder; emit NewTrustedForwarder(_forwarder); } function burn(uint256 tokenId) public override(INeowizERC721, ERC721Burnable) { super.burn(tokenId); _burnCounter++; } /// @dev onlyOperator function setPayment(address _payment) external onlyOperator { payment = _payment; emit PaymentUpdated(_payment); } /// @dev onlyOperator function setUnRevealedURI(string memory _unrevealedURI) external onlyOperator { unrevealedURI = _unrevealedURI; emit UnrevealedURIUpdated(_unrevealedURI); } /// @notice Add a minting round /// @dev onlyOperator /// @param _state private or public /// @param _maxMintPerAccount The max amount of tokens one account can mint in this round /// @param _maxMint The max amount of tokens reserved in this round /// @param _price The unit price per token /// @param _merkleRoot This is useful only in a private round /// @param _startTs The timestamp when this round starts /// @param _endTs The timestamp when this round ends function addRound( SaleState _state, uint256 _maxMintPerAccount, uint256 _maxMint, uint256 _price, bytes32 _merkleRoot, uint256 _startTs, uint256 _endTs ) external onlyOperator { if (_endTs < _startTs) { revert InvalidTimestamp(); } if (_startTs < rounds[numRounds].endTs) { revert InvalidTimestamp(); } Round storage r = rounds[++numRounds]; r.state = _state; r.maxMintPerAccount = _maxMintPerAccount; r.maxMint = _maxMint; r.price = _price; r.merkleRoot = _merkleRoot; r.startTs = uint64(_startTs); r.endTs = uint64(_endTs); emit RoundAdded( numRounds, uint256(_state), _maxMintPerAccount, _maxMint, _price, _merkleRoot, _startTs, _endTs ); } /// @dev onlyOperator function updateState(uint256 _roundId, SaleState _state) external checkRound(_roundId) onlyOperator { Round storage r = rounds[_roundId]; r.state = _state; emit StateUpdated(_roundId, uint256(_state)); } /// @dev onlyOperator function updateMaxMint(uint256 _roundId, uint256 _maxMint) external checkRound(_roundId) onlyOperator { Round storage r = rounds[_roundId]; r.maxMint = _maxMint; emit MaxMintUpdated(_roundId, _maxMint); } /// @dev onlyOperator function updateMaxMintPerAccount( uint256 _roundId, uint256 _maxMintPerAccount ) external checkRound(_roundId) onlyOperator { Round storage r = rounds[_roundId]; r.maxMintPerAccount = _maxMintPerAccount; emit MaxMintPerAccountUpdated(_roundId, _maxMintPerAccount); } /// @dev onlyOperator function updatePrice(uint256 _roundId, uint256 _price) external checkRound(_roundId) onlyOperator { Round storage r = rounds[_roundId]; r.price = _price; emit PriceUpdated(_roundId, _price); } /// @dev onlyOperator function updateMerkleRoot(uint256 _roundId, bytes32 _merkleRoot) external checkRound(_roundId) onlyOperator { Round storage r = rounds[_roundId]; r.merkleRoot = _merkleRoot; emit MerkleRootUpdated(_roundId, _merkleRoot); } /// @dev onlyOperator /// @param _startTs _startTs must >= endTs of the previous round /// @param _endTs _endTs must <= startTs of the next round function updateRoundTimestamp( uint256 _roundId, uint256 _startTs, uint256 _endTs ) external checkRound(_roundId) onlyOperator { if (_endTs < _startTs) { revert InvalidTimestamp(); } Round storage r = rounds[_roundId]; if (_roundId < numRounds && rounds[_roundId + 1].startTs < _endTs) { revert InvalidTimestamp(); } if (1 < _roundId && _startTs < rounds[_roundId - 1].endTs) { revert InvalidTimestamp(); } r.startTs = uint64(_startTs); r.endTs = uint64(_endTs); emit RoundTimestampUpdated(_roundId, _startTs, _endTs); } /// @dev onlyOperator function setBaseURI(string memory _uri) external onlyOperator { require(bytes(_uri).length > 0, "wrong base uri"); baseURI = _uri; emit BaseURIUpdated(_uri); } /// @notice Sets the contract-wide ERC-2981 royalty info. /// @dev onlyOwner /// @param receiver Royalty receiver address /// @param feeBasisPoints The fee rate is equal to `feeBasisPoint / ERC2981._feeDenominator()` function setRoyaltyInfo(address receiver, uint96 feeBasisPoints) external onlyOwner { _setDefaultRoyalty(receiver, feeBasisPoints); emit RoyaltyInfoUpdated(receiver, feeBasisPoints); } /// @notice Mint unminted nfts to `team` before the reveal. This excludes the team amount. /// @dev onlyOperator /// @param _quantity Given type(uint256).max, mint all remainders except for the team amount. function mintResidue(uint256 _quantity) external onlyOperator { // Check if (_quantity == type(uint256).max) { _quantity = _notTeamResidue(); } if (block.timestamp < rounds[numRounds].endTs) { revert NotAllRoundsFinished(); } if (_notTeamResidue() < _quantity) { revert MaxTotalSupplyExceeded(); } // Effect _currentIndex += _quantity; // Interaction _mintNotTeamQuantity(team, _quantity); } /// @notice Mint to `team` /// @dev onlyOperator /// @param _quantity The number of tokens to mint. function teamMint(uint256 _quantity) external onlyOperator { if (_quantity == type(uint256).max) { _quantity = TEAM_SUPPLY - totalTeamMinted(); } if (TEAM_SUPPLY < totalTeamMinted() + _quantity) { revert MaxTotalTeamMintExceeded(); } _currentTeamIndex += _quantity; _mintTeamQuantity(team, _quantity); } /// @notice Mint a public drop /// @param _quantity The number of tokens to mint. /// @param _round The round id /// @param _payment The payment token address /// @param _price The price of one nft function publicMint(uint256 _quantity, uint256 _round, address _payment, uint256 _price) external payable { _publicMint(_msgSender(), false, _quantity, _round, _payment, _price); } function _publicMint( address _from, bool _isPaid, uint256 _quantity, uint256 _round, address _payment, uint256 _price ) internal inRound(_round) isPublic(_round) { Round storage round = rounds[_round]; require(_payment == address(payment), "payment is different"); require(_price == round.price, "round price is different"); if (!_isPaid) { _payMintFee(_from, round.price * _quantity); } _mintInRound(_round, _from, _quantity); } /// @notice Mint a private drop /// @dev Private round only allows whitelisted users. /// @param _merkleProof The proof for the leaf of the whitelist. /// @param _quantity The number of tokens to mint. /// @param _round The round id /// @param _payment The payment token address /// @param _price The price of one nft function privateMint( bytes32[] calldata _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price ) external payable { _privateMint(_msgSender(), false, _merkleProof, _quantity, _round, _payment, _price); } function _privateMint( address _from, bool _isPaid, bytes32[] memory _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price ) internal inRound(_round) isPrivate(_round) { Round storage round = rounds[_round]; require(_payment == address(payment), "payment is different"); require(_price == round.price, "round price is different"); checkValidity(_merkleProof, rounds[_round].merkleRoot, _from); if (!_isPaid) { _payMintFee(_from, round.price * _quantity); } _mintInRound(_round, _from, _quantity); } /// @notice Mint a public drop with ERC20 permit signature /// @param _quantity The number of tokens to mint. /// @param _round The round id /// @param _payment The payment token address /// @param _price The price of one nft /// @param v ERC20Permit signature v from the`owner` /// @param r ERC20Permit signature r from the`owner` /// @param s ERC20Permit signature s from the`owner` function publicMintWithPermit( uint256 _quantity, uint256 _round, address _payment, uint256 _price, uint256 _deadline, uint8 v, bytes32 r, bytes32 s ) external { _permitPayment(_price * _quantity, _deadline, v, r, s); _publicMint(_msgSender(), false, _quantity, _round, _payment, _price); } /// @notice Mint a private drop with ERC20 permit signature /// @dev Private round only allows whitelisted users. /// @param _merkleProof The proof for the leaf of the whitelist. /// @param _quantity The number of tokens to mint. /// @param _round The round id /// @param _payment The payment token address /// @param _price The price of one nft /// @param v ERC20Permit signature v from the`owner` /// @param r ERC20Permit signature r from the`owner` /// @param s ERC20Permit signature s from the`owner` function privateMintWithPermit( bytes32[] calldata _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price, uint256 _deadline, uint8 v, bytes32 r, bytes32 s ) external payable { _permitPayment(_price * _quantity, _deadline, v, r, s); _privateMint(_msgSender(), false, _merkleProof, _quantity, _round, _payment, _price); } /// @notice Check the given merkle proof is valid /// @dev All leaf nodes are hashed using keccak256 /// @param _merkleProof The proof for the leaf of the whitelist. /// @param _root The merkle root /// @param _to The address to be checked function checkValidity(bytes32[] memory _merkleProof, bytes32 _root, address _to) public pure { bytes32 leaf = keccak256(abi.encodePacked(_to)); if (!MerkleProof.verify(_merkleProof, _root, leaf)) { revert IncorrectProof(); } } /// @notice Withdraw the minting revenue /// @dev onlyOperator /// @param _amount the amount to send function withdraw(uint256 _amount) external onlyOperator nonReentrant { uint256 amount = _amount; if (amount == type(uint256).max) { amount = payment == address(0) ? address(this).balance : IERC20(payment).balanceOf(address(this)); } uint256 amount1 = (amount * salesInfo.collector1Ratio) / ratioDenominator; uint256 amount2 = amount - amount1; if (address(payment) == address(0)) { (bool success, ) = payable(salesInfo.collector1).call{value: amount1}(""); require(success); (success, ) = payable(salesInfo.collector2).call{value: amount2}(""); require(success); } else { IERC20(payment).transfer(salesInfo.collector1, amount1); IERC20(payment).transfer(salesInfo.collector2, amount2); } } // ************* internal functions ************* function _setOperator(address newOperator) internal virtual { _operator = newOperator; emit NewOperator(newOperator); } /** * @notice It is allowed to set the random seed after all tokens are minted. */ function _setRandomSeed(uint256 _randomSeed) internal { if (revealed) { revert AlreadyRevealed(); } randomSeed = _randomSeed % (MAX_TOTAL_SUPPLY - TEAM_SUPPLY); revealed = true; emit Revealed(); } function _permitPayment(uint256 value, uint256 _deadline, uint8 v, bytes32 r, bytes32 s) internal { IERC20Permit(payment).permit(_msgSender(), address(this), value, _deadline, v, r, s); } function _payMintFee(address _payer, uint256 _amount) internal { if (payment != address(0)) { if (IERC20(payment).balanceOf(_payer) < _amount) { revert NotEnoughERC20Fund(); } IERC20(payment).transferFrom(_payer, address(this), _amount); } else { if (msg.value < _amount) { revert NotEnoughFund(); } } } /// @dev tokenId is guaranteed to be less than `MAX_TOTAL_SUPPLY`. function _mintInRound(uint256 _round, address _to, uint256 _quantity) internal { // check Round storage round = rounds[_round]; if (round.maxMintPerAccount < round.numberMinted[_to] + _quantity) { revert MaxMintPerAccountExceeded(_round, _to); } // Skip round.maxMint check if it is the last round if (_round != numRounds && round.maxMint < (round.totalMinted + _quantity)) { revert MaxMintExceeded(_round); } if (_notTeamResidue() < _quantity) { revert MaxTotalSupplyExceeded(); } // effect round.numberMinted[_to] += _quantity; round.totalMinted += _quantity; _currentIndex += _quantity; // interaction _mintNotTeamQuantity(_to, _quantity); } function _transfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721WithPermit) { super._transfer(from, to, tokenId); } function _burn(uint256 tokenId) internal override(ERC721, ERC721Royalty) { super._burn(tokenId); } /// @dev Before this, increase _currentTeamIndex and check all validations function _mintTeamQuantity(address _to, uint256 _quantity) private { uint256 startId = _currentTeamIndex - _quantity; for (uint256 i = startId; i < startId + _quantity; i++) { _safeMint(_to, i); } } /// @dev Before this, increase _currentIndex and check all validations function _mintNotTeamQuantity(address _to, uint256 _quantity) private { uint256 startId = _currentIndex - _quantity; for (uint256 i = startId; i < startId + _quantity; i++) { _safeMint(_to, i); } } // ************* view functions ************* /// @notice Query if a contract implements an interface /// @param interfaceId The interface identifier, as specified in ERC-165 function supportsInterface( bytes4 interfaceId ) public view override(ERC721, ERC721Royalty, ERC721WithPermit) returns (bool) { return super.supportsInterface(interfaceId); } /** * @notice Returns the address of operator */ function operator() public view virtual returns (address) { return _operator; } /// @notice Returns whether the NFT is revealed function isRevealed() public view override returns (bool) { return revealed; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented more than `_currentIndex` times. unchecked { return totalMinted() - _burnCounter; } } /** * @notice Returns the total amount of tokens minted in the contract. */ function totalMinted() public view returns (uint256) { unchecked { return _currentIndex - TEAM_SUPPLY + _currentTeamIndex; } } /** * @notice Returns the total amount of tokens minted by the team. */ function totalTeamMinted() public view returns (uint256) { return _currentTeamIndex; } /** * @notice Returns the current round number */ function currentRound() public view returns (uint256) { Round storage r; for (uint256 i = 1; i <= numRounds; i++) { r = rounds[i]; if (r.startTs <= block.timestamp && block.timestamp < r.endTs) { return i; } } return 0; } /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. /// @dev Throws if `_tokenId` is not a valid NFT. function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); if (!revealed) { return unrevealedURI; } uint256 shiftedId; if (tokenId < TEAM_SUPPLY) { shiftedId = tokenId; } else { shiftedId = ((tokenId - TEAM_SUPPLY + randomSeed) % (MAX_TOTAL_SUPPLY - TEAM_SUPPLY)) + TEAM_SUPPLY; } return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, Strings.toString(shiftedId))) : ""; } /// @notice Returns how many tokens the account minted in the round function numberMintedInRound(address _account, uint256 _round) external view returns (uint256) { return rounds[_round].numberMinted[_account]; } function _notTeamResidue() internal view returns (uint256) { unchecked { return MAX_TOTAL_SUPPLY - _currentIndex; } } function _baseURI() internal view override returns (string memory) { return baseURI; } event TransferReceived(address token, address operator, address from, uint256 amount, bytes data); event ApprovalReceived(address token, address owner, uint256 amount, bytes data); modifier onlyPayment() { require(msg.sender == address(payment), "only ERC1363 payment"); _; } function onTransferReceived( address _sender, address _from, uint256 _amount, bytes calldata _data ) external override onlyPayment returns (bytes4) { emit TransferReceived(msg.sender, _sender, _from, _amount, _data); bytes4 selector = bytes4(_data[:4]); bytes calldata data = _data[4:]; if (selector == this.publicMint.selector) { (uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi.decode( data, (uint256, uint256, address, uint256) ); require(_quantity * _price == _amount, "onTransferReceived: invalid amount"); _publicMint(_from, true, _quantity, _round, _payment, _price); } else if (selector == this.privateMint.selector) { (bytes32[] memory _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi .decode(data, (bytes32[], uint256, uint256, address, uint256)); require(_quantity * _price == _amount, "onTransferReceived: invalid amount"); _privateMint(_from, true, _merkleProof, _quantity, _round, _payment, _price); } else { revert("onTransferReceived: function selector not supported"); } return this.onTransferReceived.selector; } function onApprovalReceived( address _owner, uint256 _amount, bytes calldata _data ) external override onlyPayment returns (bytes4) { emit ApprovalReceived(msg.sender, _owner, _amount, _data); bytes4 selector = bytes4(_data[:4]); bytes memory data = _data[4:]; if (selector == this.publicMint.selector) { (uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi.decode( data, (uint256, uint256, address, uint256) ); _publicMint(_owner, false, _quantity, _round, _payment, _price); } else if (selector == this.privateMint.selector) { (bytes32[] memory _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi .decode(data, (bytes32[], uint256, uint256, address, uint256)); _privateMint(_owner, false, _merkleProof, _quantity, _round, _payment, _price); } else { revert("onApprovalReceived: function selector not supported"); } return this.onApprovalReceived.selector; } function _msgSender() internal view virtual override(Context, ERC2771ContextFromStorage) returns (address sender) { return super._msgSender(); } function _msgData() internal view virtual override(Context, ERC2771ContextFromStorage) returns (bytes calldata) { return super._msgData(); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_maxTotalSupply","type":"uint256"},{"internalType":"uint256","name":"_teamSupply","type":"uint256"},{"internalType":"address","name":"_team","type":"address"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"string","name":"_unrevealedURI","type":"string"},{"internalType":"address","name":"_trustedForwarder","type":"address"},{"internalType":"uint64","name":"_subscriptionId","type":"uint64"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"components":[{"internalType":"address","name":"collector1","type":"address"},{"internalType":"address","name":"collector2","type":"address"},{"internalType":"uint16","name":"collector1Ratio","type":"uint16"}],"internalType":"struct NeowizERC721.SalesInfo","name":"_salesInfo","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"AlreadyRevealed","type":"error"},{"inputs":[],"name":"IncorrectProof","type":"error"},{"inputs":[],"name":"InvalidCollectorRatio","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[{"internalType":"uint256","name":"round","type":"uint256"}],"name":"MaxMintExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"MaxMintPerAccountExceeded","type":"error"},{"inputs":[],"name":"MaxTotalSupplyExceeded","type":"error"},{"inputs":[],"name":"MaxTotalTeamMintExceeded","type":"error"},{"inputs":[],"name":"NotAllRoundsFinished","type":"error"},{"inputs":[],"name":"NotEnoughERC20Fund","type":"error"},{"inputs":[],"name":"NotEnoughFund","type":"error"},{"inputs":[],"name":"NotExistingRound","type":"error"},{"inputs":[],"name":"NotPrivate","type":"error"},{"inputs":[],"name":"NotPublic","type":"error"},{"inputs":[],"name":"NotSoldout","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"PriceNotSet","type":"error"},{"inputs":[],"name":"RoundEnded","type":"error"},{"inputs":[],"name":"RoundNotStarted","type":"error"},{"inputs":[],"name":"WrongSaleRound","type":"error"},{"inputs":[],"name":"ZeroMaxTotalSupply","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ApprovalReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMint","type":"uint256"}],"name":"MaxMintPerAccountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMint","type":"uint256"}],"name":"MaxMintUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"MerkleRootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"NewOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trustedForwarder","type":"address"}],"name":"NewTrustedForwarder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"payment","type":"address"}],"name":"PaymentUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Revealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"state","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMintPerAccount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMint","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"startTs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTs","type":"uint256"}],"name":"RoundAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTs","type":"uint256"}],"name":"RoundTimestampUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeBasisPoints","type":"uint96"}],"name":"RoyaltyInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"state","type":"uint256"}],"name":"StateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"TransferReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"UnrevealedURIUpdated","type":"event"},{"inputs":[],"name":"COORDINATOR","outputs":[{"internalType":"contract VRFCoordinatorV2Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEAM_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"_buildDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum NeowizERC721.SaleState","name":"_state","type":"uint8"},{"internalType":"uint256","name":"_maxMintPerAccount","type":"uint256"},{"internalType":"uint256","name":"_maxMint","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"_startTs","type":"uint256"},{"internalType":"uint256","name":"_endTs","type":"uint256"}],"name":"addRound","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":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"address","name":"_to","type":"address"}],"name":"checkValidity","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"currentRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"mintResidue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numRounds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"numberMintedInRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onApprovalReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onTransferReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payment","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"privateMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"privateMintWithPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"publicMintWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"randomSeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ratioDenominator","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"uint16","name":"_requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"requestRandomSeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rounds","outputs":[{"internalType":"uint256","name":"maxMintPerAccount","type":"uint256"},{"internalType":"uint256","name":"maxMint","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum NeowizERC721.SaleState","name":"state","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint64","name":"startTs","type":"uint64"},{"internalType":"uint64","name":"endTs","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"salesInfo","outputs":[{"internalType":"address","name":"collector1","type":"address"},{"internalType":"address","name":"collector2","type":"address"},{"internalType":"uint16","name":"collector1Ratio","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOperator","type":"address"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payment","type":"address"}],"name":"setPayment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeBasisPoints","type":"uint96"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_forwarder","type":"address"}],"name":"setTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_unrevealedURI","type":"string"}],"name":"setUnRevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"team","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTeamMinted","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":"unrevealedURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_maxMint","type":"uint256"}],"name":"updateMaxMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_maxMintPerAccount","type":"uint256"}],"name":"updateMaxMintPerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"updateMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_startTs","type":"uint256"},{"internalType":"uint256","name":"_endTs","type":"uint256"}],"name":"updateRoundTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"enum NeowizERC721.SaleState","name":"_state","type":"uint8"}],"name":"updateState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b50604051620064ad380380620064ad833981016040819052620000359162000595565b6001600160a01b0382166080528a8a8a8a8a8a8a8a8881898960026200005c83826200074c565b5060036200006b82826200074c565b50504660c08190529050620000808162000236565b60a05250600980546001600160a01b0319166001600160a01b03929092169190911790556001600a55620000bd620000b7620002e4565b620002f5565b80516001600160a01b03161580620000e0575060208101516001600160a01b0316155b15620000ff57604051639fabe1c160e01b815260040160405180910390fd5b8660000362000121576040516308bdabe560e21b815260040160405180910390fd5b61271061ffff16816040015161ffff1611156200015157604051632a2a033560e21b815260040160405180910390fd5b610120879052600f8690556101008690526001600160a01b0385811660e052601480546001600160a01b03191691861691909117905560176200019584826200074c565b508051601880546001600160a01b039283166001600160a01b031990911617905560208201516019805460409094015161ffff16600160a01b026001600160b01b03199094169183169190911792909217909155601a80549b90911668010000000000000000026001600160e01b0319909b166001600160401b03909c169b909b179990991790995550620008189f50505050505050505050505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200026362000347565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6000620002f0620003e1565b905090565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060600280546200035890620006bb565b80601f01602080910402602001604051908101604052809291908181526020018280546200038690620006bb565b8015620003d75780601f10620003ab57610100808354040283529160200191620003d7565b820191906000526020600020905b815481529060010190602001808311620003b957829003601f168201915b5050505050905090565b6009546000906001600160a01b0316330362000404575060131936013560601c90565b503390565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200044a576200044a62000409565b604052919050565b600082601f8301126200046457600080fd5b81516001600160401b0381111562000480576200048062000409565b602062000496601f8301601f191682016200041f565b8281528582848701011115620004ab57600080fd5b60005b83811015620004cb578581018301518282018401528201620004ae565b506000928101909101919091529392505050565b80516001600160a01b0381168114620004f757600080fd5b919050565b80516001600160401b0381168114620004f757600080fd5b6000606082840312156200052757600080fd5b604051606081016001600160401b03811182821017156200054c576200054c62000409565b6040529050806200055d83620004df565b81526200056d60208401620004df565b6020820152604083015161ffff811681146200058857600080fd5b6040919091015292915050565b60008060008060008060008060008060006101a08c8e031215620005b857600080fd5b8b516001600160401b03811115620005cf57600080fd5b620005dd8e828f0162000452565b60208e0151909c5090506001600160401b03811115620005fc57600080fd5b6200060a8e828f0162000452565b9a505060408c0151985060608c015197506200062960808d01620004df565b96506200063960a08d01620004df565b60c08d01519096506001600160401b038111156200065657600080fd5b620006648e828f0162000452565b9550506200067560e08d01620004df565b9350620006866101008d01620004fc565b9250620006976101208d01620004df565b9150620006a98d6101408e0162000514565b90509295989b509295989b9093969950565b600181811c90821680620006d057607f821691505b602082108103620006f157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000747576000816000526020600020601f850160051c81016020861015620007225750805b601f850160051c820191505b8181101562000743578281556001016200072e565b5050505b505050565b81516001600160401b0381111562000768576200076862000409565b6200078081620007798454620006bb565b84620006f7565b602080601f831160018114620007b857600084156200079f5750858301515b600019600386901b1c1916600185901b17855562000743565b600085815260208120601f198616915b82811015620007e957888601518255948401946001909101908401620007c8565b5085821015620008085787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516101005161012051615bc7620008e6600039600081816106bb01528181611c6201528181612690015281816126ff01528181612dc20152818161406501526142f5015260008181610be401528181610c5d0152818161139d0152818161193b0152818161197801528181611c8c01528181612d6e01528181612d9d01528181612dee01526140440152600081816109e8015281816119d3015261275e01526000611a0001526000611a350152600081816113d301526114150152615bc76000f3fe6080604052600436106103fa5760003560e01c80637035bf18116102135780639d31d92f11610123578063da742228116100ab578063f1e331151161007a578063f1e3311514610d7d578063f2fde38b14610d9d578063f6e76aa314610dbd578063fb38e00b14610dd0578063ffbafdfe14610df057600080fd5b8063da74222814610cbf578063e985e9c514610cdf578063ecb3197b14610d28578063ef90084814610d3b57600080fd5b8063b3ab15fb116100f2578063b3ab15fb14610c0b578063b88d4fde14610c2b578063b9c3a81814610c4b578063c87b56dd14610c7f578063d48ed40614610c9f57600080fd5b80639d31d92f14610b795780639d78325d14610b99578063a22cb46514610baf578063a2309ff814610bcf57600080fd5b806388a7ca5c116101a6578063950fca2911610175578063950fca2914610ae457806395d89b4114610b04578063969e447414610b1957806397b03b5714610b395780639ab06fcb14610b5957600080fd5b806388a7ca5c14610a0a5780638a19c8bc14610a2a5780638c65c81f14610a3f5780638da5cb5b14610ac657600080fd5b80637b04a2d0116101e25780637b04a2d01461095d57806382367b2d1461099657806384ea048a146109b657806385f2aef2146109d657600080fd5b80637035bf18146108f357806370a0823114610908578063715018a614610928578063745a41bc1461093d57600080fd5b806330adf81f1161030e57806351830227116102a1578063570ca73511610270578063570ca73514610853578063572b6c05146108715780635d81f3ec146108a05780636352211e146108b35780636f0aa387146108d357600080fd5b806351830227146107a257806354214f69146107bc57806355d1be4c146107d457806355f804b31461083357600080fd5b80633b2bcbf1116102dd5780633b2bcbf11461071b57806342842e0e1461074257806342966c681461076257806342f6487a1461078257600080fd5b806330adf81f1461067557806333039d3d146106a95780633644e515146106dd5780633b242439146106f257600080fd5b806313c530d0116103915780631fe543e3116103605780631fe543e3146105b657806323b872dd146105d65780632a55205a146105f65780632e1a7d4d146106355780632fbba1151461065557600080fd5b806313c530d01461054c578063141a468c1461056c57806318160ddd1461058c5780631a2832e8146105a157600080fd5b8063081812fc116103cd578063081812fc14610498578063095ea7b3146104d057806309c1ba2e146104f05780630b747d911461052857600080fd5b806301aade7b146103ff57806301ffc9a71461042157806302fa7c471461045657806306fdde0314610476575b600080fd5b34801561040b57600080fd5b5061041f61041a366004614af6565b610e10565b005b34801561042d57600080fd5b5061044161043c366004614b54565b610edd565b60405190151581526020015b60405180910390f35b34801561046257600080fd5b5061041f610471366004614b86565b610eee565b34801561048257600080fd5b5061048b610f4e565b60405161044d9190614c1b565b3480156104a457600080fd5b506104b86104b3366004614c2e565b610fe0565b6040516001600160a01b03909116815260200161044d565b3480156104dc57600080fd5b5061041f6104eb366004614c47565b611007565b3480156104fc57600080fd5b50601a54610510906001600160401b031681565b6040516001600160401b03909116815260200161044d565b34801561053457600080fd5b5061053e60155481565b60405190815260200161044d565b34801561055857600080fd5b5061041f610567366004614c87565b61112e565b34801561057857600080fd5b5061053e610587366004614c2e565b611324565b34801561059857600080fd5b5061053e61138d565b3480156105ad57600080fd5b50600e5461053e565b3480156105c257600080fd5b5061041f6105d1366004614cfd565b6113c8565b3480156105e257600080fd5b5061041f6105f1366004614d9e565b611450565b34801561060257600080fd5b50610616610611366004614ddf565b611488565b604080516001600160a01b03909316835260208301919091520161044d565b34801561064157600080fd5b5061041f610650366004614c2e565b611536565b34801561066157600080fd5b5061041f610670366004614c2e565b6118ac565b34801561068157600080fd5b5061053e7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b3480156106b557600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106e957600080fd5b5061053e6119fb565b3480156106fe57600080fd5b5061070861271081565b60405161ffff909116815260200161044d565b34801561072757600080fd5b50601a546104b890600160401b90046001600160a01b031681565b34801561074e57600080fd5b5061041f61075d366004614d9e565b611a5b565b34801561076e57600080fd5b5061041f61077d366004614c2e565b611a76565b34801561078e57600080fd5b506014546104b8906001600160a01b031681565b3480156107ae57600080fd5b506016546104419060ff1681565b3480156107c857600080fd5b5060165460ff16610441565b3480156107e057600080fd5b50601854601954610809916001600160a01b039081169190811690600160a01b900461ffff1683565b604080516001600160a01b03948516815293909216602084015261ffff169082015260600161044d565b34801561083f57600080fd5b5061041f61084e366004614af6565b611a97565b34801561085f57600080fd5b506011546001600160a01b03166104b8565b34801561087d57600080fd5b5061044161088c366004614e01565b6009546001600160a01b0391821691161490565b61041f6108ae366004614e73565b611b92565b3480156108bf57600080fd5b506104b86108ce366004614c2e565b611c00565b3480156108df57600080fd5b5061041f6108ee366004614f13565b611c60565b3480156108ff57600080fd5b5061048b611df4565b34801561091457600080fd5b5061053e610923366004614e01565b611e82565b34801561093457600080fd5b5061041f611f08565b34801561094957600080fd5b5061041f610958366004614f85565b611f1c565b34801561096957600080fd5b5061097d610978366004615028565b61202e565b6040516001600160e01b0319909116815260200161044d565b3480156109a257600080fd5b5061041f6109b1366004614ddf565b612244565b3480156109c257600080fd5b5061041f6109d1366004615083565b612337565b3480156109e257600080fd5b506104b87f000000000000000000000000000000000000000000000000000000000000000081565b348015610a1657600080fd5b5061097d610a253660046150f2565b612364565b348015610a3657600080fd5b5061053e61258c565b348015610a4b57600080fd5b50610ab2610a5a366004614c2e565b6013602052600090815260409020600181015460028201546003830154600484015460058501546006860154600790960154949593949293919260ff90911691906001600160401b0380821691600160401b90041688565b60405161044d98979695949392919061517a565b348015610ad257600080fd5b50600b546001600160a01b03166104b8565b348015610af057600080fd5b5061041f610aff366004614c2e565b612604565b348015610b1057600080fd5b5061048b612783565b348015610b2557600080fd5b5061053e610b343660046151e5565b612792565b348015610b4557600080fd5b5061041f610b54366004614ddf565b612848565b348015610b6557600080fd5b5061041f610b74366004614e01565b612931565b348015610b8557600080fd5b5061041f610b94366004615220565b6129fc565b348015610ba557600080fd5b5061053e60125481565b348015610bbb57600080fd5b5061041f610bca36600461525a565b612bfa565b348015610bdb57600080fd5b50600e54600f547f000000000000000000000000000000000000000000000000000000000000000090030161053e565b348015610c1757600080fd5b5061041f610c26366004614e01565b612c0c565b348015610c3757600080fd5b5061041f610c46366004615288565b612c8a565b348015610c5757600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c8b57600080fd5b5061048b610c9a366004614c2e565b612cc3565b348015610cab57600080fd5b5061041f610cba366004615345565b612e92565b348015610ccb57600080fd5b5061041f610cda366004614e01565b612ef3565b348015610ceb57600080fd5b50610441610cfa366004615394565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61041f610d363660046153c2565b612f45565b348015610d4757600080fd5b5061053e610d56366004614c47565b60009081526013602090815260408083206001600160a01b03949094168352929052205490565b348015610d8957600080fd5b5061041f610d98366004614ddf565b612f5b565b348015610da957600080fd5b5061041f610db8366004614e01565b613044565b61041f610dcb366004615401565b6130ba565b348015610ddc57600080fd5b5061041f610deb366004614ddf565b613106565b348015610dfc57600080fd5b5061041f610e0b366004615473565b6131ef565b610e18613305565b6001600160a01b0316610e336011546001600160a01b031690565b6001600160a01b03161480610e715750610e4b613305565b6001600160a01b0316610e66600b546001600160a01b031690565b6001600160a01b0316145b610e965760405162461bcd60e51b8152600401610e8d9061549f565b60405180910390fd5b6017610ea28282615572565b507f1d7696984a6c8e76fa7d719b93812fa99fec684deb7fef436692056e4c4aab8981604051610ed29190614c1b565b60405180910390a150565b6000610ee882613314565b92915050565b610ef6613339565b610f0082826133b2565b604080516001600160a01b03841681526001600160601b03831660208201527fae1d656a1268648b04ffa79c1416f05879338ae295aae3234d8db217356a1c62910160405180910390a15050565b606060028054610f5d906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610f89906154f0565b8015610fd65780601f10610fab57610100808354040283529160200191610fd6565b820191906000526020600020905b815481529060010190602001808311610fb957829003601f168201915b5050505050905090565b6000610feb826134af565b506000908152600660205260409020546001600160a01b031690565b600061101282611c00565b9050806001600160a01b0316836001600160a01b03160361107f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610e8d565b806001600160a01b0316611091613305565b6001600160a01b031614806110ad57506110ad81610cfa613305565b61111f5760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610e8d565b611129838361350e565b505050565b611136613305565b6001600160a01b03166111516011546001600160a01b031690565b6001600160a01b0316148061118f5750611169613305565b6001600160a01b0316611184600b546001600160a01b031690565b6001600160a01b0316145b6111ab5760405162461bcd60e51b8152600401610e8d9061549f565b818110156111cc5760405163b7d0949760e01b815260040160405180910390fd5b601254600090815260136020526040902060070154600160401b90046001600160401b03168210156112115760405163b7d0949760e01b815260040160405180910390fd5b60006013600060126000815461122690615647565b918290555081526020810191909152604001600020600581018054919250899160ff19166001838181111561125d5761125d615164565b021790555060018082018890556002820187905560048201869055600682018590556007820180546001600160401b03858116600160401b026001600160801b031990921690871617179055601254907f2f97fd490e935512c57b9c40169523f1fffb4291d075d10c2de74783f22ef95c908a908111156112e0576112e0615164565b60408051918252602082018b90528101899052606081018890526080810187905260a0810186905260c0810185905260e00160405180910390a25050505050505050565b6000818152600460205260408120546001600160a01b031661137a5760405162461bcd60e51b815260206004820152600f60248201526e21554e4b4e4f574e5f544f4b454e2160881b6044820152606401610e8d565b5060009081526008602052604090205490565b60006010546113c2600e54600f547f000000000000000000000000000000000000000000000000000000000000000090030190565b03905090565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146114425760405163073e64fd60e21b81523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610e8d565b61144c828261357c565b5050565b61146161145b613305565b8261359f565b61147d5760405162461bcd60e51b8152600401610e8d90615660565b61112983838361361d565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916114fd5750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061151c906001600160601b0316876156ae565b61152691906156db565b91519350909150505b9250929050565b61153e613305565b6001600160a01b03166115596011546001600160a01b031690565b6001600160a01b031614806115975750611571613305565b6001600160a01b031661158c600b546001600160a01b031690565b6001600160a01b0316145b6115b35760405162461bcd60e51b8152600401610e8d9061549f565b6002600a54036116055760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b6002600a55806001810161169a576014546001600160a01b031615611695576014546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561166c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169091906156ef565b611697565b475b90505b601954600090612710906116b990600160a01b900461ffff16846156ae565b6116c391906156db565b905060006116d18284615708565b6014549091506001600160a01b03166117ac576018546040516000916001600160a01b03169084908381818185875af1925050503d8060008114611731576040519150601f19603f3d011682016040523d82523d6000602084013e611736565b606091505b505090508061174457600080fd5b6019546040516001600160a01b03909116908390600081818185875af1925050503d8060008114611791576040519150601f19603f3d011682016040523d82523d6000602084013e611796565b606091505b505080915050806117a657600080fd5b506118a1565b60145460185460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303816000875af1158015611801573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611825919061571b565b5060145460195460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af115801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f919061571b565b505b50506001600a555050565b6118b4613305565b6001600160a01b03166118cf6011546001600160a01b031690565b6001600160a01b0316148061190d57506118e7613305565b6001600160a01b0316611902600b546001600160a01b031690565b6001600160a01b0316145b6119295760405162461bcd60e51b8152600401610e8d9061549f565b600019810361196257600e5461195f907f0000000000000000000000000000000000000000000000000000000000000000615708565b90505b8061196c600e5490565b6119769190615738565b7f000000000000000000000000000000000000000000000000000000000000000010156119b657604051636ee3e45960e11b815260040160405180910390fd5b80600e60008282546119c89190615738565b909155506119f890507f000000000000000000000000000000000000000000000000000000000000000082613628565b50565b6000467f00000000000000000000000000000000000000000000000000000000000000008114611a3357611a2e8161365f565b611a55565b7f00000000000000000000000000000000000000000000000000000000000000005b91505090565b61112983838360405180602001604052806000815250612c8a565b611a7f8161370b565b60108054906000611a8f83615647565b919050555050565b611a9f613305565b6001600160a01b0316611aba6011546001600160a01b031690565b6001600160a01b03161480611af85750611ad2613305565b6001600160a01b0316611aed600b546001600160a01b031690565b6001600160a01b0316145b611b145760405162461bcd60e51b8152600401610e8d9061549f565b6000815111611b565760405162461bcd60e51b815260206004820152600e60248201526d77726f6e6720626173652075726960901b6044820152606401610e8d565b600c611b628282615572565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad81604051610ed29190614c1b565b611ba8611b9f89876156ae565b8585858561373b565b611bf4611bb3613305565b60008c8c808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d91508c90508b6137df565b50505050505050505050565b6000818152600460205260408120546001600160a01b031680610ee85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b7f0000000000000000000000000000000000000000000000000000000000000000611cb1600e54600f547f000000000000000000000000000000000000000000000000000000000000000090030190565b1015611cd0576040516303ba630160e01b815260040160405180910390fd5b611cd8613305565b6001600160a01b0316611cf36011546001600160a01b031690565b6001600160a01b03161480611d315750611d0b613305565b6001600160a01b0316611d26600b546001600160a01b031690565b6001600160a01b0316145b611d4d5760405162461bcd60e51b8152600401610e8d9061549f565b601a546040516305d3b1d360e41b8152600481018590526001600160401b038216602482015261ffff8416604482015263ffffffff8316606482015260016084820152600160401b9091046001600160a01b031690635d3b1d309060a4016020604051808303816000875af1158015611dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dee91906156ef565b50505050565b60178054611e01906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2d906154f0565b8015611e7a5780601f10611e4f57610100808354040283529160200191611e7a565b820191906000526020600020905b815481529060010190602001808311611e5d57829003601f168201915b505050505081565b60006001600160a01b038216611eec5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b031660009081526005602052604090205490565b611f10613339565b611f1a60006139c5565b565b42821015611f6c5760405162461bcd60e51b815260206004820152601960248201527f215045524d49545f444541444c494e455f4558504952454421000000000000006044820152606401610e8d565b600083815260086020526040812054611f89908690869086612792565b90506000611f978284613a17565b5090506001600160a01b03811615801590611fb75750611fb7818661359f565b80611fd05750611fd0611fc986611c00565b8385613a59565b61201c5760405162461bcd60e51b815260206004820152601a60248201527f21494e56414c49445f5045524d49545f5349474e4154555245210000000000006044820152606401610e8d565b612026868661350e565b505050505050565b6014546000906001600160a01b031633146120825760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7f71d859275b482dfe1e2d14bfd2863dbe5cc9914143fea269841eb035fd6afaf533868686866040516120b9959493929190615774565b60405180910390a160006120d060048285876157b3565b6120d9916157dd565b905060006120ea84600481886157b3565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b0319821663134ce68560e01b0161217357600080600080848060200190518101906121539190615818565b935093509350935061216a8b600086868686613b9b565b5050505061222f565b630918955d60e01b6001600160e01b03198316016121cb576000806000806000858060200190518101906121a79190615857565b945094509450945094506121c18c600087878787876137df565b505050505061222f565b60405162461bcd60e51b815260206004820152603360248201527f6f6e417070726f76616c52656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b506307b04a2d60e41b9150505b949350505050565b818060125410156122685760405163ed6b05a360e01b815260040160405180910390fd5b612270613305565b6001600160a01b031661228b6011546001600160a01b031690565b6001600160a01b031614806122c957506122a3613305565b6001600160a01b03166122be600b546001600160a01b031690565b6001600160a01b0316145b6122e55760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060048101859055915184815285917f945c1c4e99aa89f648fbfe3df471b916f719e16d960fcec0737d4d56bd69683891015b60405180910390a250505050565b612344611b9f89876156ae565b61235a61234f613305565b60008a8a8a8a613b9b565b5050505050505050565b6014546000906001600160a01b031633146123b85760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7fa10ea941849680df7289f12b45394b2f603bb88bfd7346374c8e6dbb8fd27fb83387878787876040516123f196959493929190615917565b60405180910390a1600061240860048285876157b3565b612411916157dd565b905036600061242385600481896157b3565b909250905063134ce68560e01b6001600160e01b031984160161249b576000808080612451858701876153c2565b93509350935093508a818561246691906156ae565b146124835760405162461bcd60e51b8152600401610e8d90615953565b6124928c600186868686613b9b565b50505050612577565b630918955d60e01b6001600160e01b0319841601612513576000808080806124c586880188615995565b945094509450945094508b81856124dc91906156ae565b146124f95760405162461bcd60e51b8152600401610e8d90615953565b6125098d600187878787876137df565b5050505050612577565b60405162461bcd60e51b815260206004820152603360248201527f6f6e5472616e7366657252656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b50632229f29760e21b98975050505050505050565b60008060015b60125481116125fb5760008181526013602052604090206007810154909250426001600160401b03909116118015906125de57506007820154600160401b90046001600160401b031642105b156125e95792915050565b806125f381615647565b915050612592565b50600091505090565b61260c613305565b6001600160a01b03166126276011546001600160a01b031690565b6001600160a01b03161480612665575061263f613305565b6001600160a01b031661265a600b546001600160a01b031690565b6001600160a01b0316145b6126815760405162461bcd60e51b8152600401610e8d9061549f565b60001981036126b15750600f547f0000000000000000000000000000000000000000000000000000000000000000035b601254600090815260136020526040902060070154600160401b90046001600160401b03164210156126f657604051632e25514d60e11b815260040160405180910390fd5b80612722600f547f00000000000000000000000000000000000000000000000000000000000000000390565b101561274157604051630a5b751b60e41b815260040160405180910390fd5b80600f60008282546127539190615738565b909155506119f890507f000000000000000000000000000000000000000000000000000000000000000082613d4d565b606060038054610f5d906154f0565b600061283f61279f6119fb565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad6020808301919091526001600160a01b038a1682840152606082018990526080820188905260a08083018890528351808403909101815260c08301845280519082012061190160f01b60e084015260e28301949094526101028083019490945282518083039094018452610122909101909152815191012090565b95945050505050565b8180601254101561286c5760405163ed6b05a360e01b815260040160405180910390fd5b612874613305565b6001600160a01b031661288f6011546001600160a01b031690565b6001600160a01b031614806128cd57506128a7613305565b6001600160a01b03166128c2600b546001600160a01b031690565b6001600160a01b0316145b6128e95760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060028101859055915184815285917fc37cc9c3c37fdcacbe05156c2f68f96e3d3ecec5a381a8929651bf7a317f0d1c9101612329565b612939613305565b6001600160a01b03166129546011546001600160a01b031690565b6001600160a01b03161480612992575061296c613305565b6001600160a01b0316612987600b546001600160a01b031690565b6001600160a01b0316145b6129ae5760405162461bcd60e51b8152600401610e8d9061549f565b601480546001600160a01b0319166001600160a01b0383169081179091556040519081527f424cf801e48c82bd3bcec24e3c7b5912fbdd079dad1e9137321af112db07381f90602001610ed2565b82806012541015612a205760405163ed6b05a360e01b815260040160405180910390fd5b612a28613305565b6001600160a01b0316612a436011546001600160a01b031690565b6001600160a01b03161480612a815750612a5b613305565b6001600160a01b0316612a76600b546001600160a01b031690565b6001600160a01b0316145b612a9d5760405162461bcd60e51b8152600401610e8d9061549f565b82821015612abe5760405163b7d0949760e01b815260040160405180910390fd5b600084815260136020526040902060125485108015612b0757508260136000612ae8886001615738565b81526020810191909152604001600020600701546001600160401b0316105b15612b255760405163b7d0949760e01b815260040160405180910390fd5b846001108015612b66575060136000612b3f600188615708565b8152602081019190915260400160002060070154600160401b90046001600160401b031684105b15612b845760405163b7d0949760e01b815260040160405180910390fd5b6007810180546001600160401b03858116600160401b026001600160801b03199092169087161717905560405185907f2ce088ba9de5c469723f27edb3150dd5b001a016d992fed4a7e1d0c1cc39137290612beb9087908790918252602082015260400190565b60405180910390a25050505050565b61144c612c05613305565b8383613d84565b612c14613339565b6001600160a01b038116612c815760405162461bcd60e51b815260206004820152602e60248201527f4e656f77697a4552433732313a206e6577206f70657261746f7220697320746860448201526d65207a65726f206164647265737360901b6064820152608401610e8d565b6119f881613e52565b612c9b612c95613305565b8361359f565b612cb75760405162461bcd60e51b8152600401610e8d90615660565b611dee84848484613ea0565b6060612cce826134af565b60165460ff16612d6a5760178054612ce5906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054612d11906154f0565b8015612d5e5780601f10612d3357610100808354040283529160200191612d5e565b820191906000526020600020905b815481529060010190602001808311612d4157829003601f168201915b50505050509050919050565b60007f0000000000000000000000000000000000000000000000000000000000000000831015612d9b575081612e34565b7f0000000000000000000000000000000000000000000000000000000000000000612de6817f0000000000000000000000000000000000000000000000000000000000000000615708565b601554612e137f000000000000000000000000000000000000000000000000000000000000000087615708565b612e1d9190615738565b612e2791906159ff565b612e319190615738565b90505b6000600c8054612e43906154f0565b905011612e5f5760405180602001604052806000815250612e8b565b600c612e6a82613ed3565b604051602001612e7b929190615a13565b6040516020818303038152906040525b9392505050565b6040516bffffffffffffffffffffffff19606083901b166020820152600090603401604051602081830303815290604052805190602001209050612ed7848483613fd3565b611dee576040516227b15560e01b815260040160405180910390fd5b612efb613339565b600980546001600160a01b0319166001600160a01b0383169081179091556040517fffd948da7ce0ac541cf3790b301b0df6af19e474ed095744d1460a7ea6b7d15390600090a250565b611dee612f50613305565b600086868686613b9b565b81806012541015612f7f5760405163ed6b05a360e01b815260040160405180910390fd5b612f87613305565b6001600160a01b0316612fa26011546001600160a01b031690565b6001600160a01b03161480612fe05750612fba613305565b6001600160a01b0316612fd5600b546001600160a01b031690565b6001600160a01b0316145b612ffc5760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060068101859055915184815285917f9ff79792a92b66fee090acb66e07837a2edb31ee6b9780fa551fd04b79dffcd29101612329565b61304c613339565b6001600160a01b0381166130b15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b6119f8816139c5565b6120266130c5613305565b60008888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250899150889050876137df565b8180601254101561312a5760405163ed6b05a360e01b815260040160405180910390fd5b613132613305565b6001600160a01b031661314d6011546001600160a01b031690565b6001600160a01b0316148061318b5750613165613305565b6001600160a01b0316613180600b546001600160a01b031690565b6001600160a01b0316145b6131a75760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060018101859055915184815285917f258fa6ef7a3f3b3f76e4871e78d8e046e00bcf3f3e2662a58b3da774a2a74f399101612329565b818060125410156132135760405163ed6b05a360e01b815260040160405180910390fd5b61321b613305565b6001600160a01b03166132366011546001600160a01b031690565b6001600160a01b03161480613274575061324e613305565b6001600160a01b0316613269600b546001600160a01b031690565b6001600160a01b0316145b6132905760405162461bcd60e51b8152600401610e8d9061549f565b600083815260136020526040902060058101805484919060ff1916600183818111156132be576132be615164565b0217905550837f210cbb60935822c957f36bfad9f082e34516b470d608565d6e21abfd2d771beb8460018111156132f7576132f7615164565b604051908152602001612329565b600061330f613fe9565b905090565b60006001600160e01b03198216635604e22560e01b1480610ee85750610ee882614010565b613341613305565b6001600160a01b031661335c600b546001600160a01b031690565b6001600160a01b031614611f1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b6127106001600160601b03821611156134205760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610e8d565b6001600160a01b0382166134765760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610e8d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600055565b6000818152600460205260409020546001600160a01b03166119f85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061354382611c00565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61144c8160008151811061359257613592615a9a565b602002602001015161401b565b6000806135ab83611c00565b9050806001600160a01b0316846001600160a01b031614806135f257506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff165b8061223c5750836001600160a01b031661360b84610fe0565b6001600160a01b031614949350505050565b6111298383836140cf565b600081600e546136389190615708565b9050805b6136468383615738565b811015611dee5761365784826140e3565b60010161363c565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61368a610f4e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b61371661145b613305565b6137325760405162461bcd60e51b8152600401610e8d90615660565b6119f8816140fd565b6014546001600160a01b031663d505accf613754613305565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c4810184905260e401600060405180830381600087803b1580156137c057600080fd5b505af11580156137d4573d6000803e3d6000fd5b505050505050505050565b60008381526013602052604090206012548491908211156138135760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613841576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b03161161387657604051636b5fd31b60e01b815260040160405180910390fd5b600085815260136020526040812060050154869160ff909116908160018111156138a2576138a2615164565b146138c057604051630a7bec6d60e21b815260040160405180910390fd5b60008781526013602052604090206014546001600160a01b038881169116146139225760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b806004015486146139705760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b60008881526013602052604090206006015461398e908b908e612e92565b8a6139ac576139ac8c8a83600401546139a791906156ae565b614106565b6139b7888d8b614242565b505050505050505050505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000808251604103613a4d5760208301516040840151606085015160001a613a41878285856143a3565b9450945050505061152f565b5060009050600261152f565b6000806000613a688585613a17565b90925090506000816004811115613a8157613a81615164565b148015613a9f5750856001600160a01b0316826001600160a01b0316145b15613aaf57600192505050612e8b565b600080876001600160a01b0316631626ba7e60e01b8888604051602401613ad7929190615ab0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613b159190615ac9565b600060405180830381855afa9150503d8060008114613b50576040519150601f19603f3d011682016040523d82523d6000602084013e613b55565b606091505b5091509150818015613b68575080516020145b8015613b8f57508051630b135d3f60e11b90613b8d90830160209081019084016156ef565b145b98975050505050505050565b6000838152601360205260409020601254849190821115613bcf5760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613bfd576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b031611613c3257604051636b5fd31b60e01b815260040160405180910390fd5b84600160008281526013602052604090206005015460ff166001811115613c5b57613c5b615164565b14613c7957604051637002ac7160e11b815260040160405180910390fd5b60008681526013602052604090206014546001600160a01b03878116911614613cdb5760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b80600401548514613d295760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b88613d4257613d428a8983600401546139a791906156ae565b611bf4878b8a614242565b600081600f54613d5d9190615708565b9050805b613d6b8383615738565b811015611dee57613d7c84826140e3565b600101613d61565b816001600160a01b0316836001600160a01b031603613de55760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527fda12ee837e6978172aaf54b16145ffe08414fd8710092ef033c71b8eb6ec189a90602001610ed2565b613eab84848461361d565b613eb784848484614490565b611dee5760405162461bcd60e51b8152600401610e8d90615ae5565b606081600003613efa5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613f245780613f0e81615647565b9150613f1d9050600a836156db565b9150613efe565b6000816001600160401b03811115613f3e57613f3e614a59565b6040519080825280601f01601f191660200182016040528015613f68576020820181803683370190505b5090505b841561223c57613f7d600183615708565b9150613f8a600a866159ff565b613f95906030615738565b60f81b818381518110613faa57613faa615a9a565b60200101906001600160f81b031916908160001a905350613fcc600a866156db565b9450613f6c565b600082613fe08584614595565b14949350505050565b6009546000906001600160a01b0316330361400b575060131936013560601c90565b503390565b6000610ee8826145d8565b60165460ff161561403f5760405163a89ac15160e01b815260040160405180910390fd5b6140897f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000615708565b61409390826159ff565b6015556016805460ff191660011790556040517fe2a7169cedebe39671840370ae19ca4fc41be6191d4c77f174f189a4d8cd08c890600090a150565b6140d881614618565b611129838383614632565b61144c8282604051806020016040528060008152506147ce565b6119f881614801565b6014546001600160a01b031615614221576014546040516370a0823160e01b81526001600160a01b038481166004830152839216906370a0823190602401602060405180830381865afa158015614161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418591906156ef565b10156141a4576040516302b1b38b60e61b815260040160405180910390fd5b6014546040516323b872dd60e01b81526001600160a01b03848116600483015230602483015260448201849052909116906323b872dd906064016020604051808303816000875af11580156141fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611129919061571b565b8034101561144c57604051634a531cfd60e01b815260040160405180910390fd5b60008381526013602090815260408083206001600160a01b03861684529182905290912054614272908390615738565b816001015410156142a85760405163c86a5f3560e01b8152600481018590526001600160a01b0384166024820152604401610e8d565b60125484141580156142cc57508181600301546142c59190615738565b8160020154105b156142ec57604051626dc22f60e91b815260048101859052602401610e8d565b81614318600f547f00000000000000000000000000000000000000000000000000000000000000000390565b101561433757604051630a5b751b60e41b815260040160405180910390fd5b6001600160a01b0383166000908152602082905260408120805484929061435f908490615738565b925050819055508181600301600082825461437a9190615738565b9250508190555081600f60008282546143939190615738565b90915550611dee90508383613d4d565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143da5750600090506003614487565b8460ff16601b141580156143f257508460ff16601c14155b156144035750600090506004614487565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614457573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661448057600060019250925050614487565b9150600090505b94509492505050565b60006001600160a01b0384163b1561458d57836001600160a01b031663150b7a026144b9613305565b8786866040518563ffffffff1660e01b81526004016144db9493929190615b37565b6020604051808303816000875af1925050508015614516575060408051601f3d908101601f1916820190925261451391810190615b74565b60015b614573573d808015614544576040519150601f19603f3d011682016040523d82523d6000602084013e614549565b606091505b50805160000361456b5760405162461bcd60e51b8152600401610e8d90615ae5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061223c565b50600161223c565b600081815b84518110156145d0576145c6828683815181106145b9576145b9615a9a565b602002602001015161481b565b915060010161459a565b509392505050565b60006001600160e01b031982166380ac58cd60e01b148061460957506001600160e01b03198216635b5e139f60e01b145b80610ee85750610ee882614847565b6000818152600860205260408120805491611a8f83615647565b826001600160a01b031661464582611c00565b6001600160a01b0316146146a95760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610e8d565b6001600160a01b03821661470b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b61471660008261350e565b6001600160a01b038316600090815260056020526040812080546001929061473f908490615708565b90915550506001600160a01b038216600090815260056020526040812080546001929061476d908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6147d8838361487c565b6147e56000848484614490565b6111295760405162461bcd60e51b8152600401610e8d90615ae5565b61480a816149be565b600090815260016020526040812055565b6000818310614837576000828152602084905260409020612e8b565b5060009182526020526040902090565b60006001600160e01b0319821663152a902d60e11b1480610ee857506301ffc9a760e01b6001600160e01b0319831614610ee8565b6001600160a01b0382166148d25760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b6000818152600460205260409020546001600160a01b0316156149375760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b0382166000908152600560205260408120805460019290614960908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006149c982611c00565b90506149d660008361350e565b6001600160a01b03811660009081526005602052604081208054600192906149ff908490615708565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614a9757614a97614a59565b604052919050565b60006001600160401b03831115614ab857614ab8614a59565b614acb601f8401601f1916602001614a6f565b9050828152838383011115614adf57600080fd5b828260208301376000602084830101529392505050565b600060208284031215614b0857600080fd5b81356001600160401b03811115614b1e57600080fd5b8201601f81018413614b2f57600080fd5b61223c84823560208401614a9f565b6001600160e01b0319811681146119f857600080fd5b600060208284031215614b6657600080fd5b8135612e8b81614b3e565b6001600160a01b03811681146119f857600080fd5b60008060408385031215614b9957600080fd5b8235614ba481614b71565b915060208301356001600160601b0381168114614bc057600080fd5b809150509250929050565b60005b83811015614be6578181015183820152602001614bce565b50506000910152565b60008151808452614c07816020860160208601614bcb565b601f01601f19169290920160200192915050565b602081526000612e8b6020830184614bef565b600060208284031215614c4057600080fd5b5035919050565b60008060408385031215614c5a57600080fd5b8235614c6581614b71565b946020939093013593505050565b803560028110614c8257600080fd5b919050565b600080600080600080600060e0888a031215614ca257600080fd5b614cab88614c73565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b60006001600160401b03821115614cf357614cf3614a59565b5060051b60200190565b60008060408385031215614d1057600080fd5b823591506020808401356001600160401b03811115614d2e57600080fd5b8401601f81018613614d3f57600080fd5b8035614d52614d4d82614cda565b614a6f565b81815260059190911b82018301908381019088831115614d7157600080fd5b928401925b82841015614d8f57833582529284019290840190614d76565b80955050505050509250929050565b600080600060608486031215614db357600080fd5b8335614dbe81614b71565b92506020840135614dce81614b71565b929592945050506040919091013590565b60008060408385031215614df257600080fd5b50508035926020909101359150565b600060208284031215614e1357600080fd5b8135612e8b81614b71565b60008083601f840112614e3057600080fd5b5081356001600160401b03811115614e4757600080fd5b6020830191508360208260051b850101111561152f57600080fd5b803560ff81168114614c8257600080fd5b6000806000806000806000806000806101208b8d031215614e9357600080fd5b8a356001600160401b03811115614ea957600080fd5b614eb58d828e01614e1e565b909b5099505060208b0135975060408b0135965060608b0135614ed781614b71565b955060808b0135945060a08b01359350614ef360c08c01614e62565b925060e08b013591506101008b013590509295989b9194979a5092959850565b600080600060608486031215614f2857600080fd5b83359250602084013561ffff81168114614f4157600080fd5b9150604084013563ffffffff81168114614f5a57600080fd5b809150509250925092565b600082601f830112614f7657600080fd5b612e8b83833560208501614a9f565b60008060008060808587031215614f9b57600080fd5b8435614fa681614b71565b9350602085013592506040850135915060608501356001600160401b03811115614fcf57600080fd5b614fdb87828801614f65565b91505092959194509250565b60008083601f840112614ff957600080fd5b5081356001600160401b0381111561501057600080fd5b60208301915083602082850101111561152f57600080fd5b6000806000806060858703121561503e57600080fd5b843561504981614b71565b93506020850135925060408501356001600160401b0381111561506b57600080fd5b61507787828801614fe7565b95989497509550505050565b600080600080600080600080610100898b0312156150a057600080fd5b883597506020890135965060408901356150b981614b71565b955060608901359450608089013593506150d560a08a01614e62565b925060c0890135915060e089013590509295985092959890939650565b60008060008060006080868803121561510a57600080fd5b853561511581614b71565b9450602086013561512581614b71565b93506040860135925060608601356001600160401b0381111561514757600080fd5b61515388828901614fe7565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b600061010082019050898252886020830152876040830152866060830152600286106151b657634e487b7160e01b600052602160045260246000fd5b608082019590955260a08101939093526001600160401b0391821660c08401521660e090910152949350505050565b600080600080608085870312156151fb57600080fd5b843561520681614b71565b966020860135965060408601359560600135945092505050565b60008060006060848603121561523557600080fd5b505081359360208301359350604090920135919050565b80151581146119f857600080fd5b6000806040838503121561526d57600080fd5b823561527881614b71565b91506020830135614bc08161524c565b6000806000806080858703121561529e57600080fd5b84356152a981614b71565b935060208501356152b981614b71565b92506040850135915060608501356001600160401b03811115614fcf57600080fd5b600082601f8301126152ec57600080fd5b813560206152fc614d4d83614cda565b8083825260208201915060208460051b87010193508684111561531e57600080fd5b602086015b8481101561533a5780358352918301918301615323565b509695505050505050565b60008060006060848603121561535a57600080fd5b83356001600160401b0381111561537057600080fd5b61537c868287016152db565b935050602084013591506040840135614f5a81614b71565b600080604083850312156153a757600080fd5b82356153b281614b71565b91506020830135614bc081614b71565b600080600080608085870312156153d857600080fd5b843593506020850135925060408501356153f181614b71565b9396929550929360600135925050565b60008060008060008060a0878903121561541a57600080fd5b86356001600160401b0381111561543057600080fd5b61543c89828a01614e1e565b9097509550506020870135935060408701359250606087013561545e81614b71565b80925050608087013590509295509295509295565b6000806040838503121561548657600080fd5b8235915061549660208401614c73565b90509250929050565b60208082526031908201527f4e656f77697a4552433732313a2063616c6c6572206973206e6f74207468652060408201527037b832b930ba37b91037b91037bbb732b960791b606082015260800190565b600181811c9082168061550457607f821691505b60208210810361552457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611129576000816000526020600020601f850160051c810160208610156155535750805b601f850160051c820191505b818110156120265782815560010161555f565b81516001600160401b0381111561558b5761558b614a59565b61559f8161559984546154f0565b8461552a565b602080601f8311600181146155d457600084156155bc5750858301515b600019600386901b1c1916600185901b178555612026565b600085815260208120601f198616915b82811015615603578886015182559484019460019091019084016155e4565b50858210156156215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b60006001820161565957615659615631565b5060010190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b8082028115828204841417610ee857610ee8615631565b634e487b7160e01b600052601260045260246000fd5b6000826156ea576156ea6156c5565b500490565b60006020828403121561570157600080fd5b5051919050565b81810381811115610ee857610ee8615631565b60006020828403121561572d57600080fd5b8151612e8b8161524c565b80820180821115610ee857610ee8615631565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03868116825285166020820152604081018490526080606082018190526000906157a8908301848661574b565b979650505050505050565b600080858511156157c357600080fd5b838611156157d057600080fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156158055780818660040360031b1b83161692505b505092915050565b8051614c8281614b71565b6000806000806080858703121561582e57600080fd5b8451935060208501519250604085015161584781614b71565b6060959095015193969295505050565b600080600080600060a0868803121561586f57600080fd5b85516001600160401b0381111561588557600080fd5b8601601f8101881361589657600080fd5b805160206158a6614d4d83614cda565b82815260059290921b8301810191818101908b8411156158c557600080fd5b938201935b838510156158e3578451825293820193908201906158ca565b8099505050808901519650505050604086015192506159046060870161580d565b9150608086015190509295509295909350565b6001600160a01b0387811682528681166020830152851660408201526060810184905260a060808201819052600090613b8f908301848661574b565b60208082526022908201527f6f6e5472616e7366657252656365697665643a20696e76616c696420616d6f756040820152611b9d60f21b606082015260800190565b600080600080600060a086880312156159ad57600080fd5b85356001600160401b038111156159c357600080fd5b6159cf888289016152db565b955050602086013593506040860135925060608601356159ee81614b71565b949793965091946080013592915050565b600082615a0e57615a0e6156c5565b500690565b6000808454615a21816154f0565b60018281168015615a395760018114615a4e57615a7d565b60ff1984168752821515830287019450615a7d565b8860005260208060002060005b85811015615a745781548a820152908401908201615a5b565b50505082870194505b505050508351615a91818360208801614bcb565b01949350505050565b634e487b7160e01b600052603260045260246000fd5b82815260406020820152600061223c6040830184614bef565b60008251615adb818460208701614bcb565b9190910192915050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615b6a90830184614bef565b9695505050505050565b600060208284031215615b8657600080fd5b8151612e8b81614b3e56fea26469706673582212202fb497ab354989fe8376313f570296e60952c6e1a03c9c7f953a822b9686986464736f6c6343000817003300000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000078a00000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000d255647b9f573916e676db77cd34c9e8bd00528a000000000000000000000000cb9440b0d963c54a6d68aa847517f2ed5311d4ba000000000000000000000000000000000000000000000000000000000000232800000000000000000000000000000000000000000000000000000000000000174561726c792052657469726564204361747320436c7562000000000000000000000000000000000000000000000000000000000000000000000000000000000445524343000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d6648797635587a50723878336355474679623575316e694d666e315268337a336a74715033693842656a6b460000000000000000000000
Deployed Bytecode
0x6080604052600436106103fa5760003560e01c80637035bf18116102135780639d31d92f11610123578063da742228116100ab578063f1e331151161007a578063f1e3311514610d7d578063f2fde38b14610d9d578063f6e76aa314610dbd578063fb38e00b14610dd0578063ffbafdfe14610df057600080fd5b8063da74222814610cbf578063e985e9c514610cdf578063ecb3197b14610d28578063ef90084814610d3b57600080fd5b8063b3ab15fb116100f2578063b3ab15fb14610c0b578063b88d4fde14610c2b578063b9c3a81814610c4b578063c87b56dd14610c7f578063d48ed40614610c9f57600080fd5b80639d31d92f14610b795780639d78325d14610b99578063a22cb46514610baf578063a2309ff814610bcf57600080fd5b806388a7ca5c116101a6578063950fca2911610175578063950fca2914610ae457806395d89b4114610b04578063969e447414610b1957806397b03b5714610b395780639ab06fcb14610b5957600080fd5b806388a7ca5c14610a0a5780638a19c8bc14610a2a5780638c65c81f14610a3f5780638da5cb5b14610ac657600080fd5b80637b04a2d0116101e25780637b04a2d01461095d57806382367b2d1461099657806384ea048a146109b657806385f2aef2146109d657600080fd5b80637035bf18146108f357806370a0823114610908578063715018a614610928578063745a41bc1461093d57600080fd5b806330adf81f1161030e57806351830227116102a1578063570ca73511610270578063570ca73514610853578063572b6c05146108715780635d81f3ec146108a05780636352211e146108b35780636f0aa387146108d357600080fd5b806351830227146107a257806354214f69146107bc57806355d1be4c146107d457806355f804b31461083357600080fd5b80633b2bcbf1116102dd5780633b2bcbf11461071b57806342842e0e1461074257806342966c681461076257806342f6487a1461078257600080fd5b806330adf81f1461067557806333039d3d146106a95780633644e515146106dd5780633b242439146106f257600080fd5b806313c530d0116103915780631fe543e3116103605780631fe543e3146105b657806323b872dd146105d65780632a55205a146105f65780632e1a7d4d146106355780632fbba1151461065557600080fd5b806313c530d01461054c578063141a468c1461056c57806318160ddd1461058c5780631a2832e8146105a157600080fd5b8063081812fc116103cd578063081812fc14610498578063095ea7b3146104d057806309c1ba2e146104f05780630b747d911461052857600080fd5b806301aade7b146103ff57806301ffc9a71461042157806302fa7c471461045657806306fdde0314610476575b600080fd5b34801561040b57600080fd5b5061041f61041a366004614af6565b610e10565b005b34801561042d57600080fd5b5061044161043c366004614b54565b610edd565b60405190151581526020015b60405180910390f35b34801561046257600080fd5b5061041f610471366004614b86565b610eee565b34801561048257600080fd5b5061048b610f4e565b60405161044d9190614c1b565b3480156104a457600080fd5b506104b86104b3366004614c2e565b610fe0565b6040516001600160a01b03909116815260200161044d565b3480156104dc57600080fd5b5061041f6104eb366004614c47565b611007565b3480156104fc57600080fd5b50601a54610510906001600160401b031681565b6040516001600160401b03909116815260200161044d565b34801561053457600080fd5b5061053e60155481565b60405190815260200161044d565b34801561055857600080fd5b5061041f610567366004614c87565b61112e565b34801561057857600080fd5b5061053e610587366004614c2e565b611324565b34801561059857600080fd5b5061053e61138d565b3480156105ad57600080fd5b50600e5461053e565b3480156105c257600080fd5b5061041f6105d1366004614cfd565b6113c8565b3480156105e257600080fd5b5061041f6105f1366004614d9e565b611450565b34801561060257600080fd5b50610616610611366004614ddf565b611488565b604080516001600160a01b03909316835260208301919091520161044d565b34801561064157600080fd5b5061041f610650366004614c2e565b611536565b34801561066157600080fd5b5061041f610670366004614c2e565b6118ac565b34801561068157600080fd5b5061053e7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b3480156106b557600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000078a81565b3480156106e957600080fd5b5061053e6119fb565b3480156106fe57600080fd5b5061070861271081565b60405161ffff909116815260200161044d565b34801561072757600080fd5b50601a546104b890600160401b90046001600160a01b031681565b34801561074e57600080fd5b5061041f61075d366004614d9e565b611a5b565b34801561076e57600080fd5b5061041f61077d366004614c2e565b611a76565b34801561078e57600080fd5b506014546104b8906001600160a01b031681565b3480156107ae57600080fd5b506016546104419060ff1681565b3480156107c857600080fd5b5060165460ff16610441565b3480156107e057600080fd5b50601854601954610809916001600160a01b039081169190811690600160a01b900461ffff1683565b604080516001600160a01b03948516815293909216602084015261ffff169082015260600161044d565b34801561083f57600080fd5b5061041f61084e366004614af6565b611a97565b34801561085f57600080fd5b506011546001600160a01b03166104b8565b34801561087d57600080fd5b5061044161088c366004614e01565b6009546001600160a01b0391821691161490565b61041f6108ae366004614e73565b611b92565b3480156108bf57600080fd5b506104b86108ce366004614c2e565b611c00565b3480156108df57600080fd5b5061041f6108ee366004614f13565b611c60565b3480156108ff57600080fd5b5061048b611df4565b34801561091457600080fd5b5061053e610923366004614e01565b611e82565b34801561093457600080fd5b5061041f611f08565b34801561094957600080fd5b5061041f610958366004614f85565b611f1c565b34801561096957600080fd5b5061097d610978366004615028565b61202e565b6040516001600160e01b0319909116815260200161044d565b3480156109a257600080fd5b5061041f6109b1366004614ddf565b612244565b3480156109c257600080fd5b5061041f6109d1366004615083565b612337565b3480156109e257600080fd5b506104b87f000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab081565b348015610a1657600080fd5b5061097d610a253660046150f2565b612364565b348015610a3657600080fd5b5061053e61258c565b348015610a4b57600080fd5b50610ab2610a5a366004614c2e565b6013602052600090815260409020600181015460028201546003830154600484015460058501546006860154600790960154949593949293919260ff90911691906001600160401b0380821691600160401b90041688565b60405161044d98979695949392919061517a565b348015610ad257600080fd5b50600b546001600160a01b03166104b8565b348015610af057600080fd5b5061041f610aff366004614c2e565b612604565b348015610b1057600080fd5b5061048b612783565b348015610b2557600080fd5b5061053e610b343660046151e5565b612792565b348015610b4557600080fd5b5061041f610b54366004614ddf565b612848565b348015610b6557600080fd5b5061041f610b74366004614e01565b612931565b348015610b8557600080fd5b5061041f610b94366004615220565b6129fc565b348015610ba557600080fd5b5061053e60125481565b348015610bbb57600080fd5b5061041f610bca36600461525a565b612bfa565b348015610bdb57600080fd5b50600e54600f547f00000000000000000000000000000000000000000000000000000000000000e690030161053e565b348015610c1757600080fd5b5061041f610c26366004614e01565b612c0c565b348015610c3757600080fd5b5061041f610c46366004615288565b612c8a565b348015610c5757600080fd5b5061053e7f00000000000000000000000000000000000000000000000000000000000000e681565b348015610c8b57600080fd5b5061048b610c9a366004614c2e565b612cc3565b348015610cab57600080fd5b5061041f610cba366004615345565b612e92565b348015610ccb57600080fd5b5061041f610cda366004614e01565b612ef3565b348015610ceb57600080fd5b50610441610cfa366004615394565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61041f610d363660046153c2565b612f45565b348015610d4757600080fd5b5061053e610d56366004614c47565b60009081526013602090815260408083206001600160a01b03949094168352929052205490565b348015610d8957600080fd5b5061041f610d98366004614ddf565b612f5b565b348015610da957600080fd5b5061041f610db8366004614e01565b613044565b61041f610dcb366004615401565b6130ba565b348015610ddc57600080fd5b5061041f610deb366004614ddf565b613106565b348015610dfc57600080fd5b5061041f610e0b366004615473565b6131ef565b610e18613305565b6001600160a01b0316610e336011546001600160a01b031690565b6001600160a01b03161480610e715750610e4b613305565b6001600160a01b0316610e66600b546001600160a01b031690565b6001600160a01b0316145b610e965760405162461bcd60e51b8152600401610e8d9061549f565b60405180910390fd5b6017610ea28282615572565b507f1d7696984a6c8e76fa7d719b93812fa99fec684deb7fef436692056e4c4aab8981604051610ed29190614c1b565b60405180910390a150565b6000610ee882613314565b92915050565b610ef6613339565b610f0082826133b2565b604080516001600160a01b03841681526001600160601b03831660208201527fae1d656a1268648b04ffa79c1416f05879338ae295aae3234d8db217356a1c62910160405180910390a15050565b606060028054610f5d906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610f89906154f0565b8015610fd65780601f10610fab57610100808354040283529160200191610fd6565b820191906000526020600020905b815481529060010190602001808311610fb957829003601f168201915b5050505050905090565b6000610feb826134af565b506000908152600660205260409020546001600160a01b031690565b600061101282611c00565b9050806001600160a01b0316836001600160a01b03160361107f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610e8d565b806001600160a01b0316611091613305565b6001600160a01b031614806110ad57506110ad81610cfa613305565b61111f5760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610e8d565b611129838361350e565b505050565b611136613305565b6001600160a01b03166111516011546001600160a01b031690565b6001600160a01b0316148061118f5750611169613305565b6001600160a01b0316611184600b546001600160a01b031690565b6001600160a01b0316145b6111ab5760405162461bcd60e51b8152600401610e8d9061549f565b818110156111cc5760405163b7d0949760e01b815260040160405180910390fd5b601254600090815260136020526040902060070154600160401b90046001600160401b03168210156112115760405163b7d0949760e01b815260040160405180910390fd5b60006013600060126000815461122690615647565b918290555081526020810191909152604001600020600581018054919250899160ff19166001838181111561125d5761125d615164565b021790555060018082018890556002820187905560048201869055600682018590556007820180546001600160401b03858116600160401b026001600160801b031990921690871617179055601254907f2f97fd490e935512c57b9c40169523f1fffb4291d075d10c2de74783f22ef95c908a908111156112e0576112e0615164565b60408051918252602082018b90528101899052606081018890526080810187905260a0810186905260c0810185905260e00160405180910390a25050505050505050565b6000818152600460205260408120546001600160a01b031661137a5760405162461bcd60e51b815260206004820152600f60248201526e21554e4b4e4f574e5f544f4b454e2160881b6044820152606401610e8d565b5060009081526008602052604090205490565b60006010546113c2600e54600f547f00000000000000000000000000000000000000000000000000000000000000e690030190565b03905090565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990916146114425760405163073e64fd60e21b81523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909166024820152604401610e8d565b61144c828261357c565b5050565b61146161145b613305565b8261359f565b61147d5760405162461bcd60e51b8152600401610e8d90615660565b61112983838361361d565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916114fd5750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061151c906001600160601b0316876156ae565b61152691906156db565b91519350909150505b9250929050565b61153e613305565b6001600160a01b03166115596011546001600160a01b031690565b6001600160a01b031614806115975750611571613305565b6001600160a01b031661158c600b546001600160a01b031690565b6001600160a01b0316145b6115b35760405162461bcd60e51b8152600401610e8d9061549f565b6002600a54036116055760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b6002600a55806001810161169a576014546001600160a01b031615611695576014546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561166c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169091906156ef565b611697565b475b90505b601954600090612710906116b990600160a01b900461ffff16846156ae565b6116c391906156db565b905060006116d18284615708565b6014549091506001600160a01b03166117ac576018546040516000916001600160a01b03169084908381818185875af1925050503d8060008114611731576040519150601f19603f3d011682016040523d82523d6000602084013e611736565b606091505b505090508061174457600080fd5b6019546040516001600160a01b03909116908390600081818185875af1925050503d8060008114611791576040519150601f19603f3d011682016040523d82523d6000602084013e611796565b606091505b505080915050806117a657600080fd5b506118a1565b60145460185460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303816000875af1158015611801573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611825919061571b565b5060145460195460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af115801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f919061571b565b505b50506001600a555050565b6118b4613305565b6001600160a01b03166118cf6011546001600160a01b031690565b6001600160a01b0316148061190d57506118e7613305565b6001600160a01b0316611902600b546001600160a01b031690565b6001600160a01b0316145b6119295760405162461bcd60e51b8152600401610e8d9061549f565b600019810361196257600e5461195f907f00000000000000000000000000000000000000000000000000000000000000e6615708565b90505b8061196c600e5490565b6119769190615738565b7f00000000000000000000000000000000000000000000000000000000000000e610156119b657604051636ee3e45960e11b815260040160405180910390fd5b80600e60008282546119c89190615738565b909155506119f890507f000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab082613628565b50565b6000467f00000000000000000000000000000000000000000000000000000000000000018114611a3357611a2e8161365f565b611a55565b7f40deacfbaa8dcc30194d0604af7f4186163cabcefa314ac885f33ea4baf258345b91505090565b61112983838360405180602001604052806000815250612c8a565b611a7f8161370b565b60108054906000611a8f83615647565b919050555050565b611a9f613305565b6001600160a01b0316611aba6011546001600160a01b031690565b6001600160a01b03161480611af85750611ad2613305565b6001600160a01b0316611aed600b546001600160a01b031690565b6001600160a01b0316145b611b145760405162461bcd60e51b8152600401610e8d9061549f565b6000815111611b565760405162461bcd60e51b815260206004820152600e60248201526d77726f6e6720626173652075726960901b6044820152606401610e8d565b600c611b628282615572565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad81604051610ed29190614c1b565b611ba8611b9f89876156ae565b8585858561373b565b611bf4611bb3613305565b60008c8c808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d91508c90508b6137df565b50505050505050505050565b6000818152600460205260408120546001600160a01b031680610ee85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b7f000000000000000000000000000000000000000000000000000000000000078a611cb1600e54600f547f00000000000000000000000000000000000000000000000000000000000000e690030190565b1015611cd0576040516303ba630160e01b815260040160405180910390fd5b611cd8613305565b6001600160a01b0316611cf36011546001600160a01b031690565b6001600160a01b03161480611d315750611d0b613305565b6001600160a01b0316611d26600b546001600160a01b031690565b6001600160a01b0316145b611d4d5760405162461bcd60e51b8152600401610e8d9061549f565b601a546040516305d3b1d360e41b8152600481018590526001600160401b038216602482015261ffff8416604482015263ffffffff8316606482015260016084820152600160401b9091046001600160a01b031690635d3b1d309060a4016020604051808303816000875af1158015611dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dee91906156ef565b50505050565b60178054611e01906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2d906154f0565b8015611e7a5780601f10611e4f57610100808354040283529160200191611e7a565b820191906000526020600020905b815481529060010190602001808311611e5d57829003601f168201915b505050505081565b60006001600160a01b038216611eec5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b031660009081526005602052604090205490565b611f10613339565b611f1a60006139c5565b565b42821015611f6c5760405162461bcd60e51b815260206004820152601960248201527f215045524d49545f444541444c494e455f4558504952454421000000000000006044820152606401610e8d565b600083815260086020526040812054611f89908690869086612792565b90506000611f978284613a17565b5090506001600160a01b03811615801590611fb75750611fb7818661359f565b80611fd05750611fd0611fc986611c00565b8385613a59565b61201c5760405162461bcd60e51b815260206004820152601a60248201527f21494e56414c49445f5045524d49545f5349474e4154555245210000000000006044820152606401610e8d565b612026868661350e565b505050505050565b6014546000906001600160a01b031633146120825760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7f71d859275b482dfe1e2d14bfd2863dbe5cc9914143fea269841eb035fd6afaf533868686866040516120b9959493929190615774565b60405180910390a160006120d060048285876157b3565b6120d9916157dd565b905060006120ea84600481886157b3565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b0319821663134ce68560e01b0161217357600080600080848060200190518101906121539190615818565b935093509350935061216a8b600086868686613b9b565b5050505061222f565b630918955d60e01b6001600160e01b03198316016121cb576000806000806000858060200190518101906121a79190615857565b945094509450945094506121c18c600087878787876137df565b505050505061222f565b60405162461bcd60e51b815260206004820152603360248201527f6f6e417070726f76616c52656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b506307b04a2d60e41b9150505b949350505050565b818060125410156122685760405163ed6b05a360e01b815260040160405180910390fd5b612270613305565b6001600160a01b031661228b6011546001600160a01b031690565b6001600160a01b031614806122c957506122a3613305565b6001600160a01b03166122be600b546001600160a01b031690565b6001600160a01b0316145b6122e55760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060048101859055915184815285917f945c1c4e99aa89f648fbfe3df471b916f719e16d960fcec0737d4d56bd69683891015b60405180910390a250505050565b612344611b9f89876156ae565b61235a61234f613305565b60008a8a8a8a613b9b565b5050505050505050565b6014546000906001600160a01b031633146123b85760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7fa10ea941849680df7289f12b45394b2f603bb88bfd7346374c8e6dbb8fd27fb83387878787876040516123f196959493929190615917565b60405180910390a1600061240860048285876157b3565b612411916157dd565b905036600061242385600481896157b3565b909250905063134ce68560e01b6001600160e01b031984160161249b576000808080612451858701876153c2565b93509350935093508a818561246691906156ae565b146124835760405162461bcd60e51b8152600401610e8d90615953565b6124928c600186868686613b9b565b50505050612577565b630918955d60e01b6001600160e01b0319841601612513576000808080806124c586880188615995565b945094509450945094508b81856124dc91906156ae565b146124f95760405162461bcd60e51b8152600401610e8d90615953565b6125098d600187878787876137df565b5050505050612577565b60405162461bcd60e51b815260206004820152603360248201527f6f6e5472616e7366657252656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b50632229f29760e21b98975050505050505050565b60008060015b60125481116125fb5760008181526013602052604090206007810154909250426001600160401b03909116118015906125de57506007820154600160401b90046001600160401b031642105b156125e95792915050565b806125f381615647565b915050612592565b50600091505090565b61260c613305565b6001600160a01b03166126276011546001600160a01b031690565b6001600160a01b03161480612665575061263f613305565b6001600160a01b031661265a600b546001600160a01b031690565b6001600160a01b0316145b6126815760405162461bcd60e51b8152600401610e8d9061549f565b60001981036126b15750600f547f000000000000000000000000000000000000000000000000000000000000078a035b601254600090815260136020526040902060070154600160401b90046001600160401b03164210156126f657604051632e25514d60e11b815260040160405180910390fd5b80612722600f547f000000000000000000000000000000000000000000000000000000000000078a0390565b101561274157604051630a5b751b60e41b815260040160405180910390fd5b80600f60008282546127539190615738565b909155506119f890507f000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab082613d4d565b606060038054610f5d906154f0565b600061283f61279f6119fb565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad6020808301919091526001600160a01b038a1682840152606082018990526080820188905260a08083018890528351808403909101815260c08301845280519082012061190160f01b60e084015260e28301949094526101028083019490945282518083039094018452610122909101909152815191012090565b95945050505050565b8180601254101561286c5760405163ed6b05a360e01b815260040160405180910390fd5b612874613305565b6001600160a01b031661288f6011546001600160a01b031690565b6001600160a01b031614806128cd57506128a7613305565b6001600160a01b03166128c2600b546001600160a01b031690565b6001600160a01b0316145b6128e95760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060028101859055915184815285917fc37cc9c3c37fdcacbe05156c2f68f96e3d3ecec5a381a8929651bf7a317f0d1c9101612329565b612939613305565b6001600160a01b03166129546011546001600160a01b031690565b6001600160a01b03161480612992575061296c613305565b6001600160a01b0316612987600b546001600160a01b031690565b6001600160a01b0316145b6129ae5760405162461bcd60e51b8152600401610e8d9061549f565b601480546001600160a01b0319166001600160a01b0383169081179091556040519081527f424cf801e48c82bd3bcec24e3c7b5912fbdd079dad1e9137321af112db07381f90602001610ed2565b82806012541015612a205760405163ed6b05a360e01b815260040160405180910390fd5b612a28613305565b6001600160a01b0316612a436011546001600160a01b031690565b6001600160a01b03161480612a815750612a5b613305565b6001600160a01b0316612a76600b546001600160a01b031690565b6001600160a01b0316145b612a9d5760405162461bcd60e51b8152600401610e8d9061549f565b82821015612abe5760405163b7d0949760e01b815260040160405180910390fd5b600084815260136020526040902060125485108015612b0757508260136000612ae8886001615738565b81526020810191909152604001600020600701546001600160401b0316105b15612b255760405163b7d0949760e01b815260040160405180910390fd5b846001108015612b66575060136000612b3f600188615708565b8152602081019190915260400160002060070154600160401b90046001600160401b031684105b15612b845760405163b7d0949760e01b815260040160405180910390fd5b6007810180546001600160401b03858116600160401b026001600160801b03199092169087161717905560405185907f2ce088ba9de5c469723f27edb3150dd5b001a016d992fed4a7e1d0c1cc39137290612beb9087908790918252602082015260400190565b60405180910390a25050505050565b61144c612c05613305565b8383613d84565b612c14613339565b6001600160a01b038116612c815760405162461bcd60e51b815260206004820152602e60248201527f4e656f77697a4552433732313a206e6577206f70657261746f7220697320746860448201526d65207a65726f206164647265737360901b6064820152608401610e8d565b6119f881613e52565b612c9b612c95613305565b8361359f565b612cb75760405162461bcd60e51b8152600401610e8d90615660565b611dee84848484613ea0565b6060612cce826134af565b60165460ff16612d6a5760178054612ce5906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054612d11906154f0565b8015612d5e5780601f10612d3357610100808354040283529160200191612d5e565b820191906000526020600020905b815481529060010190602001808311612d4157829003601f168201915b50505050509050919050565b60007f00000000000000000000000000000000000000000000000000000000000000e6831015612d9b575081612e34565b7f00000000000000000000000000000000000000000000000000000000000000e6612de6817f000000000000000000000000000000000000000000000000000000000000078a615708565b601554612e137f00000000000000000000000000000000000000000000000000000000000000e687615708565b612e1d9190615738565b612e2791906159ff565b612e319190615738565b90505b6000600c8054612e43906154f0565b905011612e5f5760405180602001604052806000815250612e8b565b600c612e6a82613ed3565b604051602001612e7b929190615a13565b6040516020818303038152906040525b9392505050565b6040516bffffffffffffffffffffffff19606083901b166020820152600090603401604051602081830303815290604052805190602001209050612ed7848483613fd3565b611dee576040516227b15560e01b815260040160405180910390fd5b612efb613339565b600980546001600160a01b0319166001600160a01b0383169081179091556040517fffd948da7ce0ac541cf3790b301b0df6af19e474ed095744d1460a7ea6b7d15390600090a250565b611dee612f50613305565b600086868686613b9b565b81806012541015612f7f5760405163ed6b05a360e01b815260040160405180910390fd5b612f87613305565b6001600160a01b0316612fa26011546001600160a01b031690565b6001600160a01b03161480612fe05750612fba613305565b6001600160a01b0316612fd5600b546001600160a01b031690565b6001600160a01b0316145b612ffc5760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060068101859055915184815285917f9ff79792a92b66fee090acb66e07837a2edb31ee6b9780fa551fd04b79dffcd29101612329565b61304c613339565b6001600160a01b0381166130b15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b6119f8816139c5565b6120266130c5613305565b60008888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250899150889050876137df565b8180601254101561312a5760405163ed6b05a360e01b815260040160405180910390fd5b613132613305565b6001600160a01b031661314d6011546001600160a01b031690565b6001600160a01b0316148061318b5750613165613305565b6001600160a01b0316613180600b546001600160a01b031690565b6001600160a01b0316145b6131a75760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060018101859055915184815285917f258fa6ef7a3f3b3f76e4871e78d8e046e00bcf3f3e2662a58b3da774a2a74f399101612329565b818060125410156132135760405163ed6b05a360e01b815260040160405180910390fd5b61321b613305565b6001600160a01b03166132366011546001600160a01b031690565b6001600160a01b03161480613274575061324e613305565b6001600160a01b0316613269600b546001600160a01b031690565b6001600160a01b0316145b6132905760405162461bcd60e51b8152600401610e8d9061549f565b600083815260136020526040902060058101805484919060ff1916600183818111156132be576132be615164565b0217905550837f210cbb60935822c957f36bfad9f082e34516b470d608565d6e21abfd2d771beb8460018111156132f7576132f7615164565b604051908152602001612329565b600061330f613fe9565b905090565b60006001600160e01b03198216635604e22560e01b1480610ee85750610ee882614010565b613341613305565b6001600160a01b031661335c600b546001600160a01b031690565b6001600160a01b031614611f1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b6127106001600160601b03821611156134205760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610e8d565b6001600160a01b0382166134765760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610e8d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600055565b6000818152600460205260409020546001600160a01b03166119f85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061354382611c00565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61144c8160008151811061359257613592615a9a565b602002602001015161401b565b6000806135ab83611c00565b9050806001600160a01b0316846001600160a01b031614806135f257506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff165b8061223c5750836001600160a01b031661360b84610fe0565b6001600160a01b031614949350505050565b6111298383836140cf565b600081600e546136389190615708565b9050805b6136468383615738565b811015611dee5761365784826140e3565b60010161363c565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61368a610f4e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b61371661145b613305565b6137325760405162461bcd60e51b8152600401610e8d90615660565b6119f8816140fd565b6014546001600160a01b031663d505accf613754613305565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c4810184905260e401600060405180830381600087803b1580156137c057600080fd5b505af11580156137d4573d6000803e3d6000fd5b505050505050505050565b60008381526013602052604090206012548491908211156138135760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613841576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b03161161387657604051636b5fd31b60e01b815260040160405180910390fd5b600085815260136020526040812060050154869160ff909116908160018111156138a2576138a2615164565b146138c057604051630a7bec6d60e21b815260040160405180910390fd5b60008781526013602052604090206014546001600160a01b038881169116146139225760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b806004015486146139705760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b60008881526013602052604090206006015461398e908b908e612e92565b8a6139ac576139ac8c8a83600401546139a791906156ae565b614106565b6139b7888d8b614242565b505050505050505050505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000808251604103613a4d5760208301516040840151606085015160001a613a41878285856143a3565b9450945050505061152f565b5060009050600261152f565b6000806000613a688585613a17565b90925090506000816004811115613a8157613a81615164565b148015613a9f5750856001600160a01b0316826001600160a01b0316145b15613aaf57600192505050612e8b565b600080876001600160a01b0316631626ba7e60e01b8888604051602401613ad7929190615ab0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613b159190615ac9565b600060405180830381855afa9150503d8060008114613b50576040519150601f19603f3d011682016040523d82523d6000602084013e613b55565b606091505b5091509150818015613b68575080516020145b8015613b8f57508051630b135d3f60e11b90613b8d90830160209081019084016156ef565b145b98975050505050505050565b6000838152601360205260409020601254849190821115613bcf5760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613bfd576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b031611613c3257604051636b5fd31b60e01b815260040160405180910390fd5b84600160008281526013602052604090206005015460ff166001811115613c5b57613c5b615164565b14613c7957604051637002ac7160e11b815260040160405180910390fd5b60008681526013602052604090206014546001600160a01b03878116911614613cdb5760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b80600401548514613d295760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b88613d4257613d428a8983600401546139a791906156ae565b611bf4878b8a614242565b600081600f54613d5d9190615708565b9050805b613d6b8383615738565b811015611dee57613d7c84826140e3565b600101613d61565b816001600160a01b0316836001600160a01b031603613de55760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527fda12ee837e6978172aaf54b16145ffe08414fd8710092ef033c71b8eb6ec189a90602001610ed2565b613eab84848461361d565b613eb784848484614490565b611dee5760405162461bcd60e51b8152600401610e8d90615ae5565b606081600003613efa5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613f245780613f0e81615647565b9150613f1d9050600a836156db565b9150613efe565b6000816001600160401b03811115613f3e57613f3e614a59565b6040519080825280601f01601f191660200182016040528015613f68576020820181803683370190505b5090505b841561223c57613f7d600183615708565b9150613f8a600a866159ff565b613f95906030615738565b60f81b818381518110613faa57613faa615a9a565b60200101906001600160f81b031916908160001a905350613fcc600a866156db565b9450613f6c565b600082613fe08584614595565b14949350505050565b6009546000906001600160a01b0316330361400b575060131936013560601c90565b503390565b6000610ee8826145d8565b60165460ff161561403f5760405163a89ac15160e01b815260040160405180910390fd5b6140897f00000000000000000000000000000000000000000000000000000000000000e67f000000000000000000000000000000000000000000000000000000000000078a615708565b61409390826159ff565b6015556016805460ff191660011790556040517fe2a7169cedebe39671840370ae19ca4fc41be6191d4c77f174f189a4d8cd08c890600090a150565b6140d881614618565b611129838383614632565b61144c8282604051806020016040528060008152506147ce565b6119f881614801565b6014546001600160a01b031615614221576014546040516370a0823160e01b81526001600160a01b038481166004830152839216906370a0823190602401602060405180830381865afa158015614161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418591906156ef565b10156141a4576040516302b1b38b60e61b815260040160405180910390fd5b6014546040516323b872dd60e01b81526001600160a01b03848116600483015230602483015260448201849052909116906323b872dd906064016020604051808303816000875af11580156141fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611129919061571b565b8034101561144c57604051634a531cfd60e01b815260040160405180910390fd5b60008381526013602090815260408083206001600160a01b03861684529182905290912054614272908390615738565b816001015410156142a85760405163c86a5f3560e01b8152600481018590526001600160a01b0384166024820152604401610e8d565b60125484141580156142cc57508181600301546142c59190615738565b8160020154105b156142ec57604051626dc22f60e91b815260048101859052602401610e8d565b81614318600f547f000000000000000000000000000000000000000000000000000000000000078a0390565b101561433757604051630a5b751b60e41b815260040160405180910390fd5b6001600160a01b0383166000908152602082905260408120805484929061435f908490615738565b925050819055508181600301600082825461437a9190615738565b9250508190555081600f60008282546143939190615738565b90915550611dee90508383613d4d565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143da5750600090506003614487565b8460ff16601b141580156143f257508460ff16601c14155b156144035750600090506004614487565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614457573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661448057600060019250925050614487565b9150600090505b94509492505050565b60006001600160a01b0384163b1561458d57836001600160a01b031663150b7a026144b9613305565b8786866040518563ffffffff1660e01b81526004016144db9493929190615b37565b6020604051808303816000875af1925050508015614516575060408051601f3d908101601f1916820190925261451391810190615b74565b60015b614573573d808015614544576040519150601f19603f3d011682016040523d82523d6000602084013e614549565b606091505b50805160000361456b5760405162461bcd60e51b8152600401610e8d90615ae5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061223c565b50600161223c565b600081815b84518110156145d0576145c6828683815181106145b9576145b9615a9a565b602002602001015161481b565b915060010161459a565b509392505050565b60006001600160e01b031982166380ac58cd60e01b148061460957506001600160e01b03198216635b5e139f60e01b145b80610ee85750610ee882614847565b6000818152600860205260408120805491611a8f83615647565b826001600160a01b031661464582611c00565b6001600160a01b0316146146a95760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610e8d565b6001600160a01b03821661470b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b61471660008261350e565b6001600160a01b038316600090815260056020526040812080546001929061473f908490615708565b90915550506001600160a01b038216600090815260056020526040812080546001929061476d908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6147d8838361487c565b6147e56000848484614490565b6111295760405162461bcd60e51b8152600401610e8d90615ae5565b61480a816149be565b600090815260016020526040812055565b6000818310614837576000828152602084905260409020612e8b565b5060009182526020526040902090565b60006001600160e01b0319821663152a902d60e11b1480610ee857506301ffc9a760e01b6001600160e01b0319831614610ee8565b6001600160a01b0382166148d25760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b6000818152600460205260409020546001600160a01b0316156149375760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b0382166000908152600560205260408120805460019290614960908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006149c982611c00565b90506149d660008361350e565b6001600160a01b03811660009081526005602052604081208054600192906149ff908490615708565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614a9757614a97614a59565b604052919050565b60006001600160401b03831115614ab857614ab8614a59565b614acb601f8401601f1916602001614a6f565b9050828152838383011115614adf57600080fd5b828260208301376000602084830101529392505050565b600060208284031215614b0857600080fd5b81356001600160401b03811115614b1e57600080fd5b8201601f81018413614b2f57600080fd5b61223c84823560208401614a9f565b6001600160e01b0319811681146119f857600080fd5b600060208284031215614b6657600080fd5b8135612e8b81614b3e565b6001600160a01b03811681146119f857600080fd5b60008060408385031215614b9957600080fd5b8235614ba481614b71565b915060208301356001600160601b0381168114614bc057600080fd5b809150509250929050565b60005b83811015614be6578181015183820152602001614bce565b50506000910152565b60008151808452614c07816020860160208601614bcb565b601f01601f19169290920160200192915050565b602081526000612e8b6020830184614bef565b600060208284031215614c4057600080fd5b5035919050565b60008060408385031215614c5a57600080fd5b8235614c6581614b71565b946020939093013593505050565b803560028110614c8257600080fd5b919050565b600080600080600080600060e0888a031215614ca257600080fd5b614cab88614c73565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b60006001600160401b03821115614cf357614cf3614a59565b5060051b60200190565b60008060408385031215614d1057600080fd5b823591506020808401356001600160401b03811115614d2e57600080fd5b8401601f81018613614d3f57600080fd5b8035614d52614d4d82614cda565b614a6f565b81815260059190911b82018301908381019088831115614d7157600080fd5b928401925b82841015614d8f57833582529284019290840190614d76565b80955050505050509250929050565b600080600060608486031215614db357600080fd5b8335614dbe81614b71565b92506020840135614dce81614b71565b929592945050506040919091013590565b60008060408385031215614df257600080fd5b50508035926020909101359150565b600060208284031215614e1357600080fd5b8135612e8b81614b71565b60008083601f840112614e3057600080fd5b5081356001600160401b03811115614e4757600080fd5b6020830191508360208260051b850101111561152f57600080fd5b803560ff81168114614c8257600080fd5b6000806000806000806000806000806101208b8d031215614e9357600080fd5b8a356001600160401b03811115614ea957600080fd5b614eb58d828e01614e1e565b909b5099505060208b0135975060408b0135965060608b0135614ed781614b71565b955060808b0135945060a08b01359350614ef360c08c01614e62565b925060e08b013591506101008b013590509295989b9194979a5092959850565b600080600060608486031215614f2857600080fd5b83359250602084013561ffff81168114614f4157600080fd5b9150604084013563ffffffff81168114614f5a57600080fd5b809150509250925092565b600082601f830112614f7657600080fd5b612e8b83833560208501614a9f565b60008060008060808587031215614f9b57600080fd5b8435614fa681614b71565b9350602085013592506040850135915060608501356001600160401b03811115614fcf57600080fd5b614fdb87828801614f65565b91505092959194509250565b60008083601f840112614ff957600080fd5b5081356001600160401b0381111561501057600080fd5b60208301915083602082850101111561152f57600080fd5b6000806000806060858703121561503e57600080fd5b843561504981614b71565b93506020850135925060408501356001600160401b0381111561506b57600080fd5b61507787828801614fe7565b95989497509550505050565b600080600080600080600080610100898b0312156150a057600080fd5b883597506020890135965060408901356150b981614b71565b955060608901359450608089013593506150d560a08a01614e62565b925060c0890135915060e089013590509295985092959890939650565b60008060008060006080868803121561510a57600080fd5b853561511581614b71565b9450602086013561512581614b71565b93506040860135925060608601356001600160401b0381111561514757600080fd5b61515388828901614fe7565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b600061010082019050898252886020830152876040830152866060830152600286106151b657634e487b7160e01b600052602160045260246000fd5b608082019590955260a08101939093526001600160401b0391821660c08401521660e090910152949350505050565b600080600080608085870312156151fb57600080fd5b843561520681614b71565b966020860135965060408601359560600135945092505050565b60008060006060848603121561523557600080fd5b505081359360208301359350604090920135919050565b80151581146119f857600080fd5b6000806040838503121561526d57600080fd5b823561527881614b71565b91506020830135614bc08161524c565b6000806000806080858703121561529e57600080fd5b84356152a981614b71565b935060208501356152b981614b71565b92506040850135915060608501356001600160401b03811115614fcf57600080fd5b600082601f8301126152ec57600080fd5b813560206152fc614d4d83614cda565b8083825260208201915060208460051b87010193508684111561531e57600080fd5b602086015b8481101561533a5780358352918301918301615323565b509695505050505050565b60008060006060848603121561535a57600080fd5b83356001600160401b0381111561537057600080fd5b61537c868287016152db565b935050602084013591506040840135614f5a81614b71565b600080604083850312156153a757600080fd5b82356153b281614b71565b91506020830135614bc081614b71565b600080600080608085870312156153d857600080fd5b843593506020850135925060408501356153f181614b71565b9396929550929360600135925050565b60008060008060008060a0878903121561541a57600080fd5b86356001600160401b0381111561543057600080fd5b61543c89828a01614e1e565b9097509550506020870135935060408701359250606087013561545e81614b71565b80925050608087013590509295509295509295565b6000806040838503121561548657600080fd5b8235915061549660208401614c73565b90509250929050565b60208082526031908201527f4e656f77697a4552433732313a2063616c6c6572206973206e6f74207468652060408201527037b832b930ba37b91037b91037bbb732b960791b606082015260800190565b600181811c9082168061550457607f821691505b60208210810361552457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611129576000816000526020600020601f850160051c810160208610156155535750805b601f850160051c820191505b818110156120265782815560010161555f565b81516001600160401b0381111561558b5761558b614a59565b61559f8161559984546154f0565b8461552a565b602080601f8311600181146155d457600084156155bc5750858301515b600019600386901b1c1916600185901b178555612026565b600085815260208120601f198616915b82811015615603578886015182559484019460019091019084016155e4565b50858210156156215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b60006001820161565957615659615631565b5060010190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b8082028115828204841417610ee857610ee8615631565b634e487b7160e01b600052601260045260246000fd5b6000826156ea576156ea6156c5565b500490565b60006020828403121561570157600080fd5b5051919050565b81810381811115610ee857610ee8615631565b60006020828403121561572d57600080fd5b8151612e8b8161524c565b80820180821115610ee857610ee8615631565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03868116825285166020820152604081018490526080606082018190526000906157a8908301848661574b565b979650505050505050565b600080858511156157c357600080fd5b838611156157d057600080fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156158055780818660040360031b1b83161692505b505092915050565b8051614c8281614b71565b6000806000806080858703121561582e57600080fd5b8451935060208501519250604085015161584781614b71565b6060959095015193969295505050565b600080600080600060a0868803121561586f57600080fd5b85516001600160401b0381111561588557600080fd5b8601601f8101881361589657600080fd5b805160206158a6614d4d83614cda565b82815260059290921b8301810191818101908b8411156158c557600080fd5b938201935b838510156158e3578451825293820193908201906158ca565b8099505050808901519650505050604086015192506159046060870161580d565b9150608086015190509295509295909350565b6001600160a01b0387811682528681166020830152851660408201526060810184905260a060808201819052600090613b8f908301848661574b565b60208082526022908201527f6f6e5472616e7366657252656365697665643a20696e76616c696420616d6f756040820152611b9d60f21b606082015260800190565b600080600080600060a086880312156159ad57600080fd5b85356001600160401b038111156159c357600080fd5b6159cf888289016152db565b955050602086013593506040860135925060608601356159ee81614b71565b949793965091946080013592915050565b600082615a0e57615a0e6156c5565b500690565b6000808454615a21816154f0565b60018281168015615a395760018114615a4e57615a7d565b60ff1984168752821515830287019450615a7d565b8860005260208060002060005b85811015615a745781548a820152908401908201615a5b565b50505082870194505b505050508351615a91818360208801614bcb565b01949350505050565b634e487b7160e01b600052603260045260246000fd5b82815260406020820152600061223c6040830184614bef565b60008251615adb818460208701614bcb565b9190910192915050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615b6a90830184614bef565b9695505050505050565b600060208284031215615b8657600080fd5b8151612e8b81614b3e56fea26469706673582212202fb497ab354989fe8376313f570296e60952c6e1a03c9c7f953a822b9686986464736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000078a00000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000d255647b9f573916e676db77cd34c9e8bd00528a000000000000000000000000cb9440b0d963c54a6d68aa847517f2ed5311d4ba000000000000000000000000000000000000000000000000000000000000232800000000000000000000000000000000000000000000000000000000000000174561726c792052657469726564204361747320436c7562000000000000000000000000000000000000000000000000000000000000000000000000000000000445524343000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d6648797635587a50723878336355474679623575316e694d666e315268337a336a74715033693842656a6b460000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Early Retired Cats Club
Arg [1] : _symbol (string): ERCC
Arg [2] : _maxTotalSupply (uint256): 1930
Arg [3] : _teamSupply (uint256): 230
Arg [4] : _team (address): 0xe00C795377C1b8E7F726e9C4AadCe8fEC1beEAB0
Arg [5] : _payment (address): 0x0000000000000000000000000000000000000000
Arg [6] : _unrevealedURI (string): ipfs://QmfHyv5XzPr8x3cUGFyb5u1niMfn1Rh3z3jtqP3i8BejkF
Arg [7] : _trustedForwarder (address): 0x0000000000000000000000000000000000000000
Arg [8] : _subscriptionId (uint64): 896
Arg [9] : _vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [10] : _salesInfo (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
20 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [2] : 000000000000000000000000000000000000000000000000000000000000078a
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000e6
Arg [4] : 000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000380
Arg [9] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [10] : 000000000000000000000000d255647b9f573916e676db77cd34c9e8bd00528a
Arg [11] : 000000000000000000000000cb9440b0d963c54a6d68aa847517f2ed5311d4ba
Arg [12] : 0000000000000000000000000000000000000000000000000000000000002328
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [14] : 4561726c792052657469726564204361747320436c7562000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [16] : 4552434300000000000000000000000000000000000000000000000000000000
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000035
Arg [18] : 697066733a2f2f516d6648797635587a50723878336355474679623575316e69
Arg [19] : 4d666e315268337a336a74715033693842656a6b460000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.