ERC-721
Overview
Max Total Supply
1,626 OMFC
Holders
298
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 OMFCLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
AccessPassNFT
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4 <0.8.6; /** * @title NFTs for the AccessPass to Metaframes Maradona Club * @author MetaFrames * @notice This NFT Contract follows the ERC721 Standards and sets one of its properties (tier), on chain. * The three tiers are as follows: GOLD, SILVER, BRONZE. This contract is also connected to Metaframes' TicketNFT * which are used to join Metaframes' Ticket Competition for the World Cup Ticket. * @dev The flow of this contract is as follows: * Deployment: Contract is deployed and configured * ----------------------------------------------- * Additional Configuration * -setWhitelistSigner() * -setPrivateMintingTimestamp() if privateMintingTimestamp is 0 * ----------------------------------------------- * Private Minting: Allows accounts in the mint whitelist to mint * ----------------------------------------------- * Public Minting: Allows all accounts to mint * -setPublicMintingTimestamp() if publicMintingTimestamp is 0 * ----------------------------------------------- * Reveal: Revealing the tiers * -randomizeTiers() * -nftTiers() then builds the final token metadata * ----------------------------------------------- * Airdrop: Minting TicketNFTs to 500 Random Users * -randomizeTickets() * -winners() then builds the 500 random users * NOTE: the actual minting will happen in the TicketNFT contract */ import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "./WhitelistVerifier.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol"; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "./TicketNFT.sol"; import "./interfaces/IAccessPassNFT.sol"; import "./interfaces/ITicketNFT.sol"; contract AccessPassNFT is Ownable, WhitelistVerifier, ERC721Royalty, VRFConsumerBaseV2, IAccessPassNFT { using Counters for Counters.Counter; using Strings for uint256; /** * @dev maxTotalSupply is the amount of NFTs that can be minted */ uint16 public immutable maxTotalSupply; /** * @dev goldenTierSupply is the amount of GOLD NFTs */ uint16 public immutable goldenTierSupply; /** * @dev silverTierSupply is the amount of SILVER NFTs */ uint16 public immutable silverTierSupply; /** * @dev ticketSupply is the amount of TicketNFTs to be airdropped */ uint16 public immutable ticketSupply; /** * @dev Mapping minter address to amount minted */ struct Minted { uint256 publicMinted; uint256 privateMinted; } mapping(address => Minted) private minted; /** * @dev Keeps track of how many NFTs have been minted */ Counters.Counter public tokenIdCounter; /** * @dev privateMintingTimestamp sets when privateMinting is enabled. When this is 0, * it means all minting is disabled */ uint256 public privateMintingTimestamp; /** * @dev publicMintingTimestamp sets when publicMinting is enabled. When this is 0, it means * public minting is disabled. This value must be greater than the privateMintingTimestamp if this is not 0 */ uint256 public publicMintingTimestamp; /** * @dev price specifies how much eth an account pays for a mint. This is in wei */ uint256 public price; /** * @dev maxPublicMintable is the maximum an account can publicMint */ uint16 public maxPublicMintable; /** * @dev flag that tells if the final uri has been set */ bool public tiersRevealed; /** * @dev unrevealedURI is the placeholder token metadata when the reveal has not happened yet */ string unrevealedURI; /** * @dev baseURI is the base of the real token metadata after the reveal */ string baseURI; /** * @dev contractURI is an OpenSea standard. This should point to a metadata that tells who will * receive revenues from OpensSea. See https://docs.opensea.io/docs/contract-level-metadata */ string public contractURI; /** * @dev receives the eth from accounts private and public minting and the royalties from selling the token. * All revenues should be sent to this address */ address payable public treasury; /** * @dev ticketNFT decides the trade freeze when the winners have been selected */ TicketNFT public ticketNFT; /** * @dev The following variables are needed to request a random value from Chainlink * see https://docs.chain.link/docs/vrf-contracts/ */ address public chainlinkCoordinator; // Chainlink coordinator address uint256 public tiersRequestId; // Chainlink request id for tier randomization uint256 public tiersRandomWord; // Random value received from Chainlink VRF uint256 public ticketsRequestId; // Chainlink request id for ticket randomization uint256 public ticketsRandomWord; // Random value received from Chainlink VRF /** * @notice initializes the contract * @param treasury_ is the recipient of eth from private and public minting as well as the recipient for token selling fees * @param vrfCoordinator_ is the address of the VRF Contract for generating random number * @param maxTotalSupply_ is the max number of tokens that can be minted * @param goldenTierSupply_ is the max number of golden tiered tokens * @param silverTierSupply_ is the max number of silver tiered tokens * @param ticketSupply_ is the max number of tickets that will be airdropped * @param privateMintingTimestamp_ is when the private minting will be enabled. NOTE: this could also be set later. 0 is an acceptable value * @param royaltyFee is the fees taken from second-hand selling. This is expressed in _royaltyFee/10_000. * So to do 5% means supplying 500 since 500/10_000 is 5% (see ERC2981 function _setDefaultRoyalty(address receiver, uint96 feeNumerator)) * @param price_ is the price of a public or private mint in wei * @param contractURI_ is an OpenSeas standard and is necessary for getting revenues from OpenSeas * @param unrevealedURI_ is the token metadata placeholder while the reveal has not happened yet. */ constructor( address payable treasury_, address vrfCoordinator_, uint16 maxTotalSupply_, uint16 goldenTierSupply_, uint16 silverTierSupply_, uint16 ticketSupply_, uint256 privateMintingTimestamp_, uint96 royaltyFee, uint256 price_, string memory contractURI_, string memory unrevealedURI_ ) ERC721("Maradona Official Access Pass", "OMFC") WhitelistVerifier() VRFConsumerBaseV2(vrfCoordinator_) { if (treasury_ == address(0)) revert ZeroAddress("treasury"); treasury = treasury_; if (vrfCoordinator_ == address(0)) revert ZeroAddress("vrfCoordinator"); chainlinkCoordinator = vrfCoordinator_; if (maxTotalSupply_ == 0) revert IsZero("maxTotalSupply"); maxTotalSupply = maxTotalSupply_; // The following is to ensure that there will be bronzeTierSupply require( goldenTierSupply_ + silverTierSupply_ < maxTotalSupply_, "Tier Supplies must be less than maxTotalSupply" ); if (goldenTierSupply_ == 0) revert IsZero("goldenTierSupply"); goldenTierSupply = goldenTierSupply_; if (silverTierSupply_ == 0) revert IsZero("silverTierSupply"); silverTierSupply = silverTierSupply_; if (ticketSupply_ > maxTotalSupply_) revert IncorrectValue("ticketSupply"); ticketSupply = ticketSupply_; // not checking for zero on purpose here privateMintingTimestamp = privateMintingTimestamp_; if (royaltyFee == 0) revert IsZero("royaltyFee"); _setDefaultRoyalty(treasury_, royaltyFee); if (price_ == 0) revert IsZero("price"); price = price_; bytes memory bytesUnrevealedURI = bytes(unrevealedURI_); if (bytesUnrevealedURI[bytesUnrevealedURI.length - 1] != bytes("/")[0]) revert IncorrectValue("unrevealedURI"); unrevealedURI = unrevealedURI_; if (bytes(contractURI_).length == 0) revert EmptyString("contractURI"); contractURI = contractURI_; maxPublicMintable = 10; // mint one to deployer so the OpenSeas store front can be edited before private minting starts uint256 tokenId = tokenIdCounter.current(); _safeMint(msg.sender, tokenId); tokenIdCounter.increment(); // classifying this mint as a private mint minted[msg.sender].privateMinted += 1; } /********************** EXTERNAL ********************************/ /** * @inheritdoc IAccessPassNFT */ function privateMint( VerifiedSlot calldata verifiedSlot ) external override payable onlyDuring(ContractStatus.PRIVATE_MINTING) { validateVerifiedSlot(msg.sender, minted[msg.sender].privateMinted, verifiedSlot); internalMint(msg.sender, msg.value, MintingType.PRIVATE_MINT); } /** * @inheritdoc IAccessPassNFT */ function publicMint() external override payable onlyDuring(ContractStatus.PUBLIC_MINTING) { if (minted[msg.sender].publicMinted >= maxPublicMintable) revert ExceedMintingCapacity(minted[msg.sender].publicMinted); internalMint(msg.sender, msg.value, MintingType.PUBLIC_MINT); } /** * @inheritdoc IAccessPassNFT */ function randomizeTiers( uint64 subscriptionId, bytes32 gasLane, uint32 callbackGasLimit ) external override onlyOwner onlyOnOrAfter(ContractStatus.END_MINTING) { /// Only allow randomize if random word has not been set if (tiersRandomWord != 0) revert CanNoLongerCall(); // making sure that the request has enough callbackGasLimit to execute if (callbackGasLimit < 40_000) revert IncorrectValue("callbackGasLimit"); /// Call Chainlink to receive a random word /// Will revert if subscription is not funded. VRFCoordinatorV2Interface coordinator = VRFCoordinatorV2Interface(chainlinkCoordinator); /// Now Chainlink will call us back in a future transaction, see function fulfillRandomWords tiersRequestId = coordinator.requestRandomWords( gasLane, subscriptionId, 3, /// Request confirmations callbackGasLimit, 1 /// request 1 random number ); emit TiersRandomWordRequested(tiersRequestId); } /** * @inheritdoc IAccessPassNFT */ function revealTiers( string memory revealedURI ) external override onlyOwner onlyOnOrAfter(ContractStatus.TIERS_RANDOMIZED) { if (tiersRevealed) revert CallingMoreThanOnce(); bytes memory bytesRevealedURI = bytes(revealedURI); if (bytesRevealedURI[bytesRevealedURI.length - 1] != bytes("/")[0]) revert IncorrectValue("revealedURI"); baseURI = revealedURI; tiersRevealed = true; emit TiersRevealed(); } /** * @inheritdoc IAccessPassNFT */ function randomizeTickets( uint64 subscriptionId, bytes32 gasLane, uint32 callbackGasLimit ) external override onlyOwner onlyOnOrAfter(ContractStatus.END_MINTING) { // Only allow randomize if random word has not been set if (ticketsRandomWord != 0) revert CanNoLongerCall(); // making sure that the request has enough callbackGasLimit to execute if (callbackGasLimit < 40_000) revert IncorrectValue("callbackGasLimit"); /// Call Chainlink to receive a random word /// Will revert if subscription is not funded. VRFCoordinatorV2Interface coordinator = VRFCoordinatorV2Interface(chainlinkCoordinator); ticketsRequestId = coordinator.requestRandomWords( gasLane, subscriptionId, 3, /// Request confirmations callbackGasLimit, 1 /// request 1 random number ); emit TicketsRandomWordRequested(ticketsRequestId); /// Now Chainlink will call us back in a future transaction, see function fulfillRandomWords } /** * @inheritdoc IAccessPassNFT */ function setWhitelistSigner(address whiteListSigner_) external override onlyOwner { _setWhiteListSigner(whiteListSigner_); } /** * @inheritdoc IAccessPassNFT */ function setTicketNFT(TicketNFT ticketNFT_) external override onlyOwner() { bytes4 ticketNFTInterfaceId = type(ITicketNFT).interfaceId; if (!ticketNFT_.supportsInterface(ticketNFTInterfaceId)) revert IncorrectValue("ticketNFT_"); // should not be able to setTicketNFT if ticketNFTs have been airdropped if (address(ticketNFT) != address(0)) { // contractStatus 2 means that the tickets have been airdropped so any status before that should be good if (uint(ticketNFT.contractStatus()) > 1) revert CanNoLongerCall(); } emit TicketNFTSet(ticketNFT, ticketNFT_); ticketNFT = ticketNFT_; } /** * @inheritdoc IAccessPassNFT */ function setTreasury(address payable treasury_) external override onlyOwner() { if (treasury_ == address(0)) revert ZeroAddress("treasury"); emit TreasurySet(treasury, treasury_); treasury = treasury_; } /** * @inheritdoc IAccessPassNFT */ function setRoyaltyFee(uint96 royaltyFee) external override onlyOwner() { _setDefaultRoyalty(treasury, royaltyFee); emit RoyaltyFeesSet(royaltyFee); } /** * @inheritdoc IAccessPassNFT */ function setPrice(uint256 price_) external override onlyOwner { if (price_ == 0) revert IsZero("price"); emit PriceSet(price, price_); price = price_; } /** * @inheritdoc IAccessPassNFT */ function setContractURI(string memory contractURI_) external override onlyOwner() { if (bytes(contractURI_).length == 0) revert EmptyString("contractURI"); emit ContractURISet(contractURI, contractURI_); contractURI = contractURI_; } /** * @inheritdoc IAccessPassNFT */ function setUnrevealedURI(string memory unrevealedURI_) external override onlyOwner { bytes memory bytesUnrevealedURI = bytes(unrevealedURI_); if (bytesUnrevealedURI[bytesUnrevealedURI.length - 1] != bytes("/")[0]) revert IncorrectValue("unrevealedURI"); emit UnrevealedURISet(unrevealedURI, unrevealedURI_); unrevealedURI = unrevealedURI_; } /** * @inheritdoc IAccessPassNFT */ function setPrivateMintingTimestamp( uint256 privateMintingTimestamp_ ) external override onlyOwner onlyBefore(ContractStatus.PRIVATE_MINTING) { if ( privateMintingTimestamp_ >= publicMintingTimestamp && privateMintingTimestamp_ != 0 && publicMintingTimestamp != 0 ) revert IncorrectValue("privateMintingTimestamp"); emit PrivateMintingTimestampSet(privateMintingTimestamp, privateMintingTimestamp_); privateMintingTimestamp = privateMintingTimestamp_; } /** * @inheritdoc IAccessPassNFT */ function setPublicMintingTimestamp( uint256 publicMintingTimestamp_ ) external override onlyOwner onlyBefore(ContractStatus.PUBLIC_MINTING) { if ( publicMintingTimestamp_ < privateMintingTimestamp && publicMintingTimestamp_ != 0 ) revert IncorrectValue("publicMintingTimestamp"); emit PublicMintingTimestampSet(publicMintingTimestamp, publicMintingTimestamp_); publicMintingTimestamp = publicMintingTimestamp_; } /** * @inheritdoc IAccessPassNFT */ function setMaxPublicMintable(uint16 maxPublicMintable_) external override onlyOwner { if (maxPublicMintable_ == 0) revert IsZero("maxPublicMintable"); emit MaxPublicMintableSet(maxPublicMintable, maxPublicMintable_); maxPublicMintable = maxPublicMintable_; } /********************** EXTERNAL VIEW ********************************/ /** * @inheritdoc IAccessPassNFT */ function mintedBy(address minter) external view override returns (uint256) { if(minter == address(0)) revert ZeroAddressQuery(); return minted[minter].privateMinted + minted[minter].publicMinted; } /** * @inheritdoc IAccessPassNFT */ function mintedBy(address minter, MintingType mintingType) external view override returns (uint256) { if(minter == address(0)) revert ZeroAddressQuery(); if (mintingType == MintingType.PRIVATE_MINT) return minted[minter].privateMinted; else return minted[minter].publicMinted; } /** * @inheritdoc IAccessPassNFT */ function nftTier( uint256 tokenId ) external view override onlyOnOrAfter(ContractStatus.TIERS_RANDOMIZED) returns (uint16 tier) { if (!_exists(tokenId)) revert NonExistentToken(); return nftTiers()[tokenId]; } /** * @inheritdoc IAccessPassNFT */ function ticketsRevealed() external view override returns(bool) { return ticketsRandomWord != 0; } /** * @inheritdoc IAccessPassNFT */ function winners() external view override onlyOnOrAfter(ContractStatus.TICKETS_RANDOMIZED) returns (uint16[] memory) { // Setup a pool with random values uint256 randomPoolSize = 100; uint256 batch = 0; uint16[] memory randomPool = randArray(ticketsRandomWord, randomPoolSize, batch++); /// Setup an array with nfts that will be returned uint16[] memory nfts = new uint16[](maxTotalSupply); uint256 counter; uint256 randomId; // Assign 500 winners for(uint256 i = 0; i < ticketSupply; i++) { randomId = randomPool[counter++]; if (counter == randomPoolSize) { randomPool = randArray(ticketsRandomWord, randomPoolSize, batch++); counter = 0; } while(nfts[randomId] != 0) { randomId = randomPool[counter++]; if (counter == randomPoolSize) { randomPool = randArray(ticketsRandomWord, randomPoolSize, batch++); counter = 0; } } nfts[randomId] = 1; // Winner } return nfts; } /********************** PUBLIC ********************************/ /** * @inheritdoc IAccessPassNFT */ function totalSupply() public view override returns (uint256) { return tokenIdCounter.current(); } /** * @inheritdoc IAccessPassNFT */ function contractStatus() public view override returns (ContractStatus) { if (ticketsRandomWord != 0) return ContractStatus.TICKETS_RANDOMIZED; if (tiersRevealed) return ContractStatus.TIERS_REVEALED; if (tiersRandomWord != 0) return ContractStatus.TIERS_RANDOMIZED; if (maxTotalSupply == tokenIdCounter.current()) return ContractStatus.END_MINTING; if ( block.timestamp >= privateMintingTimestamp && privateMintingTimestamp != 0 && ( block.timestamp < publicMintingTimestamp || publicMintingTimestamp == 0 ) ) return ContractStatus.PRIVATE_MINTING; if ( block.timestamp >= publicMintingTimestamp && publicMintingTimestamp != 0 && privateMintingTimestamp != 0 ) return ContractStatus.PUBLIC_MINTING; return ContractStatus.NO_MINTING; } /** * @notice returns the unrevealed uri when the reveal hasn't happened yet and when it has, returns the real uri * @param tokenId should be a minted tokenId owned by an account */ function tokenURI(uint256 tokenId) public view override returns (string memory) { if (!_exists(tokenId)) revert NonExistentToken(); if (!tiersRevealed) return string(abi.encodePacked(unrevealedURI, tokenId.toString(), ".json")); return string(abi.encodePacked(baseURI, tokenId.toString(), ".json")); } /** * @inheritdoc IAccessPassNFT */ function nftTiers() public view override onlyOnOrAfter(ContractStatus.TIERS_RANDOMIZED) returns (uint16[] memory) { /// Setup a pool with random values uint256 randomPoolSize = 500; uint256 batch = 0; uint16[] memory randomPool = randArray(tiersRandomWord, randomPoolSize, batch++); /// Setup an array with nfts that will be returned uint16[] memory nfts = new uint16[](maxTotalSupply); uint256 counter; /// Loop counter to check when we exhaust our random pool and need to fill it again uint256 randomId; /// Random NFT id /// Assign goldenTierSupply golden tier nfts for(uint256 i = 0; i < goldenTierSupply; i++) { randomId = randomPool[counter++]; if (counter == randomPoolSize) { /// If we exhaust the random pool, fill it again randomPool = randArray(tiersRandomWord, randomPoolSize, batch++); counter = 0; } while(nfts[randomId] != 0) { /// Loop while the NFT id already has a tier assigned randomId = randomPool[counter++]; /// If we exhaust the random pool, fill it again if (counter == randomPoolSize) { randomPool = randArray(tiersRandomWord, randomPoolSize, batch++); counter = 0; } } nfts[randomId] = uint16(Tier.GOLD); } // Assign silverTierSupply silver tier nfts for(uint256 i = 0; i < silverTierSupply; i++) { randomId = randomPool[counter++]; if (counter == randomPoolSize) { /// If we exhaust the random pool, fill it again randomPool = randArray(tiersRandomWord, randomPoolSize, batch++); counter = 0; } while(nfts[randomId] != 0) { /// Loop while the NFT id already has a tier assigned randomId = randomPool[counter++]; if (counter == randomPoolSize) { /// If we exhaust the random pool, fill it again randomPool = randArray(tiersRandomWord, randomPoolSize, batch++); counter = 0; } } nfts[randomId] = uint16(Tier.SILVER); } // All remaining nfts are automatically bronze because they are already set to 0 return nfts; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view override(ERC721Royalty, IERC165) returns (bool) { return interfaceId == type(IAccessPassNFT).interfaceId || super.supportsInterface(interfaceId); } /********************** INTERNAL ********************************/ /** * @notice check if the owner has a winning ticket * @inheritdoc ERC721 */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal override { if (address(ticketNFT) != address(0)) { uint256 frozenPeriod = ticketNFT.frozenPeriod(); // not allowing winners to transfer if they only have one AccessPassNFT if ( block.timestamp < frozenPeriod && ticketNFT.isAccountWinner(from) && balanceOf(from) == 1 ) revert TransferringFrozenAccount(from, block.timestamp, frozenPeriod); } } /** * @notice pays treasury the amount * @param account is the account that paid * @param amount is how much the account has paid */ function payTreasury(address account, uint256 amount) internal { (bool success, ) = treasury.call{value: amount}(""); require (success, "Could not pay treasury"); emit TreasuryPaid(account, amount); } /** * @notice internal mint function * @param to is the account receiving the NFT * @param amountPaid is the amount that the account has paid for the mint * @param mintingType could be PRIVATE_MINT or PUBLIC_MINT */ function internalMint( address to, uint256 amountPaid, MintingType mintingType ) internal onlyBefore(ContractStatus.END_MINTING) { if (amountPaid != price) revert IncorrectValue("amountPaid"); uint256 tokenId = tokenIdCounter.current(); payTreasury(to, amountPaid); tokenIdCounter.increment(); if (MintingType.PRIVATE_MINT == mintingType) { minted[to].privateMinted += 1; } else { minted[to].publicMinted += 1; } _safeMint(to, tokenId); } /** * @notice Chainlink calls us with a random value. (See VRFConsumerBaseV2's fulfillRandomWords function) * @dev Note that this happens in a later transaction than the request. * @param requestId is the id of the request from VRF's side * @param randomWords is an array of random numbers generated by VRF */ function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { if (requestId == 0) revert IsZero("requestId"); if (requestId == tiersRequestId) { if (tiersRandomWord != 0) revert CallingMoreThanOnce(); tiersRandomWord = randomWords[0]; /// Set the random value received from Chainlink emit TiersRandomized(tiersRandomWord); } else if (requestId == ticketsRequestId) { if (ticketsRandomWord != 0) revert CallingMoreThanOnce(); ticketsRandomWord = randomWords[0]; /// Set the random value received from Chainlink emit TicketsRandomized(ticketsRandomWord); } } /** * @notice Returns a list of x random numbers, in increments of 16 numbers. * So you may receive x random numbers or up to 15 more. The random numbers are between 0 and 499 * Each batch will be different, you can call multiple times with different batch numbers * This routine is deterministic and will always return the same result if randomWord is the same * @param randomWord can only be tiersRandomWord and ticketsRandomWord * @param max is the max numbers needed in a batch * @param batch represents the batch number */ function randArray(uint256 randomWord, uint256 max, uint256 batch) internal view returns (uint16[] memory) { // First make sure the random chainlinkVRF value is initialized if (randomWord == 0) revert IsZero("randomWord"); uint256 mask = 0xFFFF; // 0xFFFF == [1111111111111111], masking the last 16 bits uint256 mainCounterMax = max / 16; if (max % 16 > 0) { mainCounterMax +=1; } uint256 batchOffset = (batch * mainCounterMax * 16); uint16[] memory randomValues = new uint16[](mainCounterMax * 16); for (uint256 mainCounter = 0; mainCounter < mainCounterMax; mainCounter++) { uint256 randomValue = uint256(keccak256(abi.encode(randomWord, mainCounter + batchOffset))); for (uint256 subCounter = 0; subCounter < 16; subCounter++) { randomValues[mainCounter * 16 + subCounter] = uint16(randomValue & mask) % maxTotalSupply; // Mask 16 bits, value between 0 .. MAX_TOTAL_SUPPLY-1 randomValue = randomValue / 2 ** 16; // Right shift 16 bits into oblivion } } return randomValues; } /********************** MODIFIERS ********************************/ /** * @notice functions like a less than to the supplied status * @param status is a ContractStatus in which the function must happen before in. For example: * setting the privateMintTimestamp should only happen before private minting starts to ensure that no one * messes with the privateMint settings during ContractStatus.PrivateMinting. To do that add this modifier * with the parameter: ContractStatus.PrivateMinting */ modifier onlyBefore(ContractStatus status) { // asserting here because there should be no state before NO_MINTING assert(status != ContractStatus.NO_MINTING); ContractStatus lastStatus = ContractStatus(uint(status) - 1); if (contractStatus() >= status) revert IncorrectContractStatus(contractStatus(), lastStatus); _; } /** * @notice functions like a an equal to the supplied status * @param status is the ContractStatus it must be in */ modifier onlyDuring(ContractStatus status) { if (contractStatus() != status) revert IncorrectContractStatus(contractStatus(), status); _; } /** * @notice functions like a greater than or equal to. The current status must be the same as or happened after the parameter. * @param status that the contract must at least be in. For example: * getting the nftTiers should only happen when TIERS_RANDOMIZED has already happened. so the parameter will be * TIERS_RANDOMIZED, because the function can only work once the status is TIERS_RANDOMIZED or has passed that */ modifier onlyOnOrAfter(ContractStatus status) { if (contractStatus() < status) revert IncorrectContractStatus(contractStatus(), status); _; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 (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 pragma solidity ^0.8.0; /** * @title An abstract contract that checks if the verified slot is valid * @author Oost & Voort, Inc * @notice This contract is to be used in conjunction with the AccessPassNFT contract */ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./interfaces/IVerifiedSlot.sol"; abstract contract WhitelistVerifier is IVerifiedSlot { using ECDSA for bytes32; /** * @dev The following struct follows the EIP712 Standard */ struct EIP712Domain { string name; string version; uint256 chainId; address verifyingContract; } /** * @dev The typehash for EIP712Domain */ bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); /** * @dev The typehash for the message being sent to the contract */ bytes32 constant VERIFIED_SLOT_TYPEHASH = keccak256("VerifiedSlot(address minter,uint256 mintingCapacity)"); /** * @dev The hashed Domain Message */ bytes32 DOMAIN_SEPARATOR; /** * @dev the address of the whiteListSigner which is an EOA that signs a message that confirms who can mint how much */ address public whiteListSigner; /** * @dev emitted when the whitelistSigner has been set * @param oldSigner represents the old signer for the Contract * @param newSigner represents the newly set signer for the Contract */ event WhitelistSignerSet(address oldSigner, address newSigner); /** * @dev reverts with this message when the Zero Address is being used to set the Whitelist Signer */ error WhitelistSignerIsZeroAddress(); /** * @dev reverts with this message when the Caller of the mint is not the same as the one in the VerifiedSLot * @param caller is the account that called for the mint * @param minter is the address specified in the VerifiedSlot */ error CallerIsNotMinter(address caller, address minter); /** * @dev reverts with this message when the message is not correct or if it is not signed by the WhitelistSigner * @param unknownSigner is the signer that signed the message * @param whitelistSigner is the signer who should have signed the message */ error UnknownSigner(address unknownSigner, address whitelistSigner); /** * @dev reverts with this message when the caller is trying to mint more than allowed * @param minted is the amount of tokens the caller has minted already */ error ExceedMintingCapacity(uint256 minted); /** * @notice initializes the contract */ constructor () { DOMAIN_SEPARATOR = hash(EIP712Domain({ name: "AccessPassNFT", version: '1', chainId: block.chainid, verifyingContract: address(this) })); } /** * @notice sets the whitelistSigner * @param whitelistSigner_ is an EOA that signs verified slots */ function _setWhiteListSigner(address whitelistSigner_) internal virtual { if (whitelistSigner_ == address(0)) revert WhitelistSignerIsZeroAddress(); emit WhitelistSignerSet(whiteListSigner, whitelistSigner_); whiteListSigner = whitelistSigner_; } /** * @notice validates verified slot * @param minter is msg.sender * @param minted is the amount the minter has minted * @param verifiedSlot is an object with the following: * minter: address of the minter, * mintingCapacity: amount Metaframes has decided to grant to the minter, * r and s --- The x co-ordinate of r and the s value of the signature * v: The parity of the y co-ordinate of r */ function validateVerifiedSlot( address minter, uint256 minted, VerifiedSlot memory verifiedSlot ) internal view { if (whiteListSigner == address(0)) revert WhitelistSignerIsZeroAddress(); if (verifiedSlot.minter != minter) revert CallerIsNotMinter(minter, verifiedSlot.minter); if(verifiedSlot.mintingCapacity <= minted) revert ExceedMintingCapacity(minted); address wouldBeSigner = getSigner(verifiedSlot); if (wouldBeSigner != whiteListSigner) revert UnknownSigner(wouldBeSigner, whiteListSigner); } /** * @notice hashes the DOMAIN object using keccak256 * @param eip712Domain represents the EIP712 object to be hashed */ function hash(EIP712Domain memory eip712Domain) internal pure returns (bytes32) { return keccak256(abi.encode( EIP712DOMAIN_TYPEHASH, keccak256(bytes(eip712Domain.name)), keccak256(bytes(eip712Domain.version)), eip712Domain.chainId, eip712Domain.verifyingContract )); } /** * @notice hashes the verifiedslot object using keccak256 * @param verifiedSlot is an object with the following: * minter: address of the minter, * mintingCapacity: amount Metaframes has decided to grant to the minter, * r and s --- The x co-ordinate of r and the s value of the signature * v: The parity of the y co-ordinate of r */ function hash(VerifiedSlot memory verifiedSlot) internal pure returns (bytes32) { return keccak256(abi.encode( VERIFIED_SLOT_TYPEHASH, verifiedSlot.minter, verifiedSlot.mintingCapacity )); } /** * @notice returns the signer of a given verifiedSlot to be used to check who signed the message * @param verifiedSlot is an object with the following: * minter: address of the minter, * mintingCapacity: amount Metaframes has decided to grant to the minter, * r and s --- The x co-ordinate of r and the s value of the signature * v: The parity of the y co-ordinate of r */ function getSigner(VerifiedSlot memory verifiedSlot) internal view returns (address) { // Note: we need to use `encodePacked` here instead of `encode`. bytes32 digest = keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, hash(verifiedSlot) )); return ecrecover(digest, verifiedSlot.v, verifiedSlot.r, verifiedSlot.s); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @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); } }
// 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 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; }
// 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 pragma solidity >=0.8.4 <0.8.6; /** * @title NFTs for the TicketCompetition to the World Cup for Metaframes * @author MetaFrames * @notice This is the NFT contract used as basis to determine the winner of the World Cup Ticket. This is also * related to the AccessPassNFT * @dev The flow of the contract is as follows: * Deployment: Contract is deployed and configured * ----------------------------------------------- * Airdrop: Minting TicketNFTs to 500 Random Users * -airdrop() * ----------------------------------------------- * Ticket Competition: Selection of the ticket winner * -setRegistered() means registration was done off-chain * -requestRandomWord() requests the random number from VRF * -ticketWinners() then returns the winner * ----------------------------------------------- * Winners Frozen: When winning tokens are barred from trading their tokens * ----------------------------------------------- * Trading Enabled: When all trading has been enabled again */ import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol"; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "./AccessPassNFT.sol"; import "./interfaces/IAccessPassNFT.sol"; import "./interfaces/ITicketNFT.sol"; contract TicketNFT is Ownable, ERC721Royalty, VRFConsumerBaseV2, ITicketNFT { using Strings for uint256; uint16 public constant NUMBER_OF_WINNERS = 2; /** * @dev maxTotalSupply is the amount of NFTs that can be minted */ uint16 public immutable maxTotalSupply; /** * @dev contractURI is an OpenSea standard. This should point to a metadata that tells who will receive revenues * from OpensSea. See https://docs.opensea.io/docs/contract-level-metadata */ string public contractURI; /** * @dev frozenPeriod is a timestamp for when the ticket winners can start trading again */ uint256 public frozenPeriod; /** * @dev if set to true, that particular nft is a winner */ mapping(uint256 => bool) public isWinner; /** * @dev array of winning ids */ uint256[] public ticketWinners; /** * @dev baseURI is the base of the token metadata used in conjunction with the token id */ string public baseURI; /** * @dev flag that tells if the tickets have been airdropped */ bool public ticketsAirdropped; /** * @dev flag that tells if the registration has been set */ bool public hasSetRegistration; /** * @dev Mapping of token id to if the owner of that token id has not registered off-chain. * For example: * 1. owner of token id 0 has registered, so 0 => false * 2. owner of token id 2 has NOT registered, so 1 => true * This was purposely made as hasNotRegistered so that we only write for values that have not registered. * This is to save gas since there should be more people who have registered than those who have not. * The registration comes from an off-chain database. */ mapping(uint16 => bool) private _hasNotRegistered; /** * @dev the related AccessPassNFT to this contract */ AccessPassNFT public accessPassNFT; /** * @dev The following variables are needed to request a random value from Chainlink. * See https://docs.chain.link/docs/vrf-contracts/ */ address public chainlinkCoordinator; // Chainlink Coordinator address uint256 public requestId; // Chainlink request id for the selection of the ticket winner uint256 public randomWord; // Random value received from Chainlink VRF /** * @notice initializes the contract * @param baseURI_ is the metadata's uri * @param contractURI_ is for OpenSeas compatability * @param royaltyAddress receives royalties fee from selling this token * @param royaltyFee is the fees taken from second-hand selling. This is expressed in _royaltyFee/1000. * So to do 5% means supplying 50 since 50/1000 is 5% (see ERC2981 function _setDefaultRoyalty(address receiver, uint96 feeNumerator)) * @param accessPassNFT_ is the address of the AccessPassNFT related to this token * @param vrfCoordinator_ is the address of the VRF used for getting a random number * @param nftHolder is the temporary holder of the NFTs before the airdrop * @param frozenPeriod_ is a timestamp for when the ticket winners can start trading again */ constructor( string memory baseURI_, string memory contractURI_, address royaltyAddress, uint96 royaltyFee, AccessPassNFT accessPassNFT_, address vrfCoordinator_, address nftHolder, uint256 frozenPeriod_ ) ERC721("Maradona Official World Cup Ticket", "OMWC") VRFConsumerBaseV2(vrfCoordinator_){ // crucial to check if there is a '/' in the end since this can no longer be changed once set // must have a '/' in the end since the token id follows the '/' bytes memory bytesBaseURI = bytes(baseURI_); if (bytesBaseURI[bytesBaseURI.length - 1] != bytes("/")[0]) revert IncorrectValue("baseURI"); baseURI = baseURI_; if (bytes(contractURI_).length == 0) revert EmptyString("contractURI"); contractURI = contractURI_; if(royaltyAddress == address(0)) revert ZeroAddress("royaltyAddress"); // not checking royaltyFee on purpose here _setDefaultRoyalty(royaltyAddress, royaltyFee); uint16 maxTotalSupply_ = accessPassNFT_.ticketSupply(); maxTotalSupply = maxTotalSupply_; bytes4 accessPassNFTInterfaceId = type(IAccessPassNFT).interfaceId; if(!accessPassNFT_.supportsInterface(accessPassNFTInterfaceId)) revert IncorrectValue("accessPassNFT"); accessPassNFT = accessPassNFT_; if(address(vrfCoordinator_) == address(0)) revert ZeroAddress("vrfCoordinator"); chainlinkCoordinator = vrfCoordinator_; if(nftHolder == address(0)) revert ZeroAddress("nftHolder"); // sending nfts to nftHolder which will be the eventual owner of the contract who will do the airdrop for (uint256 i = 0; i < maxTotalSupply_; i++) { _safeMint(nftHolder, i); } // not checking frozenPeriod_ on purpose here because there's a way to change it later frozenPeriod = frozenPeriod_; } /********************** EXTERNAL ********************************/ /** * @inheritdoc ITicketNFT */ function airdrop( uint16[] calldata winners ) external override onlyOwner onlyDuring(ContractStatus.TICKETS_REVEALED) { if (winners.length != maxTotalSupply) revert IncorrectValue("winners"); for (uint256 i = 0; i < winners.length; i++) { safeTransferFrom(msg.sender, accessPassNFT.ownerOf(winners[i]), i); } ticketsAirdropped = true; emit TicketsAirdropped(winners); } /** * @inheritdoc ITicketNFT */ function requestRandomWord( uint64 subscriptionId, bytes32 gasLane, uint32 callbackGasLimit ) external override onlyOwner onlyDuring(ContractStatus.SET_REGISTRATION) { // making sure that the request has enough callbackGasLimit to execute if (callbackGasLimit < 150_000) revert IncorrectValue("callbackGasLimit"); /// Call Chainlink to receive a random word /// Will revert if subscription is not funded. VRFCoordinatorV2Interface coordinator = VRFCoordinatorV2Interface(chainlinkCoordinator); requestId = coordinator.requestRandomWords( gasLane, subscriptionId, 3, /// Request confirmations callbackGasLimit, 1 /// request 1 random number ); /// Now Chainlink will call us back in a future transaction, see function fulfillRandomWords emit RandomWordRequested(requestId); } /** * @inheritdoc ITicketNFT */ function setContractURI(string memory uri) external override onlyOwner() { if (bytes(uri).length == 0) revert EmptyString("contractURI"); emit ContractURISet(contractURI, uri); contractURI = uri; } /** * @inheritdoc ITicketNFT */ function setDefaultRoyalty(address royaltyAddress, uint96 royaltyFee) external override onlyOwner(){ if (address(0) == royaltyAddress) revert ZeroAddress("royaltyAddress"); _setDefaultRoyalty(royaltyAddress, royaltyFee); emit RoyaltiesSet(royaltyAddress, royaltyFee); } /** * @inheritdoc ITicketNFT */ function setRegistered( bool[] calldata hasRegistered_ ) external override onlyOwner onlyDuring(ContractStatus.AIRDROPPED_TICKETS) { // sending an empty array means all accounts have registered if (hasRegistered_.length == 0) { hasSetRegistration = true; } else { if (hasRegistered_.length != maxTotalSupply) revert IncorrectValue("hasRegistered"); uint16 notRegisteredCounter = 0; for (uint16 i = 0; i < hasRegistered_.length; i++) { if (!hasRegistered_[i]) { // only writing for those who have not registered _hasNotRegistered[i] = true; // counting how many accounts have not registred notRegisteredCounter++; } } // ensuring that there are enough registered to have enough winners if (maxTotalSupply - notRegisteredCounter < NUMBER_OF_WINNERS) revert IncorrectValue("notRegisteredCounter"); hasSetRegistration = true; } emit RegistrationSet(hasRegistered_); } /** * @inheritdoc ITicketNFT */ function setFrozenPeriod(uint256 frozenPeriod_) external override onlyOwner() onlyBefore(ContractStatus.WINNERS_FROZEN) { if (frozenPeriod_ < block.timestamp && frozenPeriod_ != 0) revert IncorrectValue("frozenPeriod_"); emit FrozenPeriodSet(frozenPeriod, frozenPeriod_); frozenPeriod = frozenPeriod_; } /********************** PUBLIC VIEW ********************************/ /** * @notice returns a token metadata's uri * @param tokenId is the id of the token being queried */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if(!_exists(tokenId)) revert NonExistentToken(); return string(abi.encodePacked(baseURI, tokenId.toString(), ".json")); } /** * @inheritdoc ITicketNFT */ function hasRegistered( uint16 tokenId ) public view override onlyOnOrAfter(ContractStatus.SET_REGISTRATION) returns (bool) { if(tokenId >= maxTotalSupply) revert NonExistentToken(); return !_hasNotRegistered[tokenId]; } /** * @inheritdoc ITicketNFT */ function isAccountWinner(address account) public view override returns (bool){ for (uint16 i = 0; i < ticketWinners.length; i++) { if (ownerOf(ticketWinners[i]) == account) return true; } return false; } /** * @inheritdoc ITicketNFT */ function contractStatus() public view override returns (ContractStatus) { if(randomWord != 0) { if(block.timestamp < frozenPeriod) return ContractStatus.WINNERS_FROZEN; else return ContractStatus.TRADING_ENABLED; } if(hasSetRegistration) return ContractStatus.SET_REGISTRATION; if(ticketsAirdropped) return ContractStatus.AIRDROPPED_TICKETS; if(accessPassNFT.ticketsRevealed()) return ContractStatus.TICKETS_REVEALED; return ContractStatus.PRE_AIRDROP; } /** * @inheritdoc ITicketNFT */ function totalSupply() public view override returns (uint256) { return maxTotalSupply; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view override(ERC721Royalty, IERC165) returns (bool) { return interfaceId == type(ITicketNFT).interfaceId || super.supportsInterface(interfaceId); } /********************** INTERNAL ********************************/ /** * @notice check if token is frozen before transferring * @inheritdoc ERC721 * @param from is the address that will give the token * @param to is the address that will receive the token * @param tokenId is the id being transferred */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal override { // not allowing winningIds to be transferred when in frozenPeriod if ( block.timestamp < frozenPeriod && isWinner[tokenId] ) revert TransferringFrozenToken(tokenId, block.timestamp, frozenPeriod); } /** * @notice sets the winners */ function setWinners() internal { // Setup a pool with random values uint256 randomPoolSize = 16; uint256 batch = 0; uint16[] memory randomPool = randArray(randomPoolSize, batch++); uint256 counter = 0; uint16 randomId; for (uint16 i = 0; i < NUMBER_OF_WINNERS; i++) { randomId = randomPool[counter++]; if (counter == randomPoolSize) { randomPool = randArray(randomPoolSize, batch++); counter = 0; } // only stays in the loop when the current id has not registered or if the current id already won while(_hasNotRegistered[randomId] || isWinner[randomId]) { randomId = randomPool[counter++]; if (counter == randomPoolSize) { randomPool = randArray(randomPoolSize, batch++); counter = 0; } } ticketWinners.push(randomId); isWinner[randomId] = true; // Using mapping to keep track for if the id was already chosen as a winner } emit TicketWinnersFrozen(frozenPeriod); } /** * @notice Chainlink calls us with a random value. (See VRFConsumerBaseV2's fulfillRandomWords function) * @dev Note that this happens in a later transaction than the request. This approximately costs 139_000 in gas * @param requestId_ is the id of the request from VRF's side * @param randomWords is an array of random numbers generated by VRF */ function fulfillRandomWords( uint256 requestId_, uint256[] memory randomWords ) internal override { if(requestId != requestId_) revert IncorrectValue("requestId"); if(randomWord != 0) revert CallingMoreThanOnce(); randomWord = randomWords[0]; emit TicketWinnersSelected(randomWords[0]); setWinners(); } /** * @notice Returns a list of x random numbers, in increments of 16 numbers. * So you may receive x random numbers or up to 15 more. The random numbers are between 0 and 499 * Each batch will be different, you can call multiple times with different batch numbers * This routine is deterministic and will always return the same result if randomWord is the same * @param max is the max numbers needed in a batch * @param batch represents the batch number */ function randArray( uint256 max, uint256 batch ) internal view returns (uint16[] memory) { uint256 mask = 0xFFFF; // 0xFFFF == [1111111111111111], masking the last 16 bits uint256 mainCounterMax = max / 16; if (max % 16 > 0) { mainCounterMax +=1; } uint256 batchOffset = (batch * mainCounterMax * 16); uint16[] memory randomValues = new uint16[](mainCounterMax * 16); for (uint256 mainCounter = 0; mainCounter < mainCounterMax; mainCounter++) { uint256 randomValue = uint256(keccak256(abi.encode(randomWord, mainCounter + batchOffset))); for (uint256 subCounter = 0; subCounter < 16; subCounter++) { // Mask 16 bits, value between 0 .. maxTotalSupply-1 randomValues[mainCounter * 16 + subCounter] = uint16(randomValue & mask) % maxTotalSupply; // Right shift 16 bits into oblivion randomValue = randomValue / 2 ** 16; } } return randomValues; } /********************** MODIFIER ********************************/ /** * @notice functions like a less than to the supplied status * @param status is a ContractStatus in which the function must happen before in. For example: * setting the frozenPeriod should only happen before the ticketWinners have been selected to ensure that no one * messes with the trading period during ContractStatus.WINNERS_FROZEN. To do that add this modifier * with the parameter: ContractStatus.WINNERS_FROZEN */ modifier onlyBefore(ContractStatus status) { // asserting here because there should be no state before PRE_AIRDROP assert(status != ContractStatus.PRE_AIRDROP); ContractStatus lastStatus = ContractStatus(uint(status) - 1); if (contractStatus() >= status) revert IncorrectContractStatus(contractStatus(), lastStatus); _; } /** * @notice the current status must be equal to the status in the parameter * @param status is the ContractStatus it must be in */ modifier onlyDuring(ContractStatus status) { if (status != contractStatus()) revert IncorrectContractStatus(contractStatus(), status); _; } /** * @notice the current status must be greater than or equal to the status in the parameter * @param status that the contract must at least be in. For example: * getting the nftTiers should only happen when TIERS_RANDOMIZED has already happened. so the parameter will be * TIERS_RANDOMIZED, because the function can only work once the status is TIERS_RANDOMIZED or has passed that */ modifier onlyOnOrAfter(ContractStatus status) { if (contractStatus() < status) revert IncorrectContractStatus(contractStatus(), status); _; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4 <0.8.6; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../TicketNFT.sol"; import "./IVerifiedSlot.sol"; /** * @title Required interface for an AccessPassNFT compliant contract * @author Oost & Voort, Inc */ interface IAccessPassNFT is IERC165, IVerifiedSlot { /** * @dev The following are the stages of the contract in order: * NO_MINTING: Minting is not yet allowed * PRIVATE_MINTING: Only people in the mint whitelist can mint * PUBLIC_MINTING: Everyone can mint * END_MINTING: When everything's been minted already * TIERS_RANDOMIZED: When a random number has been set for the tiers * TIERS_REVEALED: When the final token metadata has been uploaded to IPFS * TICKETS_RANDOMIZED: When a random number has been set for the tickets airdrop */ enum ContractStatus { NO_MINTING, PRIVATE_MINTING, PUBLIC_MINTING, END_MINTING, TIERS_RANDOMIZED, TIERS_REVEALED, TICKETS_RANDOMIZED } /** * @dev Minting types are explained below: * PRIVATE_MINT: minted using the private mint function * PUBLIC_MINT: minted using the public mint function */ enum MintingType {PRIVATE_MINT, PUBLIC_MINT} /** * @dev The on-chain property of the nft that is determined by a random number */ enum Tier {BRONZE, SILVER, GOLD} /** * @dev emitted when the owner has set the private minting timestamp * @param oldTimestamp is for what the timestamp used to be * @param newTimestamp is the new value */ event PrivateMintingTimestampSet(uint256 oldTimestamp, uint256 newTimestamp); /** * @dev emitted when the owner has set the public minting timestamp * @param oldTimestamp is for what the timestamp used to be * @param newTimestamp is the new value */ event PublicMintingTimestampSet(uint256 oldTimestamp, uint256 newTimestamp); /** * @dev emitted when the owner has changed the max number of nfts a public user can mint * @param oldMaxPublicMintable is the old value for the maximum a public account can mint * @param newMaxPublicMintable is the new value for the maximum a public account can mint */ event MaxPublicMintableSet(uint16 oldMaxPublicMintable, uint16 newMaxPublicMintable); /** * @dev emitted when the owner changes the treasury * @param oldTreasury is the old value for the treasury * @param newTreasury is the new value for the treasury */ event TreasurySet(address oldTreasury, address newTreasury); /** * @dev emitted when the owner changes the minting price * @param oldPrice is the price the minting was set as * @param newPrice is the new price minting will cost as */ event PriceSet(uint256 oldPrice, uint256 newPrice); /** * @dev emitted when the owner changes the royalties * @param newRoyalties is the new royalties set by the owner */ event RoyaltyFeesSet(uint96 newRoyalties); /** * @dev emitted when the owner has changed the contract uri * @param oldURI is the uri it was set as before * @param newURI is the uri it is now set in */ event ContractURISet(string oldURI, string newURI); /** * @dev emitted when the owner has changed the unrevealed uri * @param oldURI is the uri it was set as before * @param newURI is the uri it is now set in */ event UnrevealedURISet(string oldURI, string newURI); /** * @dev emitted when the TicketNFT has been set * @param oldTicketNFT is the old TicketNFT it was pointing to * @param newTicketNFT is the TicketNFT it is now pointing to */ event TicketNFTSet(TicketNFT oldTicketNFT, TicketNFT newTicketNFT); /** * @dev emitted when the treasury has been paid in ETH * @param account is the account that paid the treasury * @param amount is how much ETH the account sent to the treasury */ event TreasuryPaid(address indexed account, uint256 amount); /** * @dev the following events must be done in order */ /** * @dev emitted when the owner has requested a random word from VRF to set the tiers of each NFT * @param requestId is the id set by VRF */ event TiersRandomWordRequested(uint256 requestId); /** * @dev emitted when VRF has used fulfillRandomness to set the random number * @param randomWord is the randomWord given back in a callback by VRF */ event TiersRandomized(uint256 randomWord); /** * @dev emitted when the owner has put the final token metadata uri for the nfts */ event TiersRevealed(); /** * @dev emitted when the owner has requested a random word from VRF to set who will be airdropped TicketNFTs * @param requestId is the id set by VRF */ event TicketsRandomWordRequested(uint256 requestId); /** * @dev emitted when VRF has used fulfillRandomness to set the random number * @param randomWord is the randomWord given back in a callback by VRF */ event TicketsRandomized(uint256 randomWord); /** * @dev reverted with this error when the address being supplied is Zero Address * @param addressName is for whom the Zero Address is being set for */ error ZeroAddress(string addressName); /** * @dev reverted with this error when a view function is asking for a Zero Address' information */ error ZeroAddressQuery(); /** * @dev reverted with this error when a view function is being used to look for a nonExistent Token */ error NonExistentToken(); /** * @dev reverted with this error when a function is being called more than once */ error CallingMoreThanOnce(); /** * @dev reverted with this error when a function should no longer be called */ error CanNoLongerCall(); /** * @dev reverted with this error when a variable being supplied is valued 0 * @param variableName is the name of the variable being supplied with 0 */ error IsZero(string variableName); /** * @dev reverted with this error when a variable has an incorrect value * @param variableName is the name of the variable with an incorrect value */ error IncorrectValue(string variableName); /** * @dev reverted with this error when a string being supplied should not be empty * @param stringName is the name of the string being supplied with an empty value */ error EmptyString(string stringName); /** * @dev reverted with this error when a function being called should not be called with the current Contract Status * @param currentStatus is the contract's current status * @param requiredStatus is the status the current must be in for the function to not revert */ error IncorrectContractStatus(ContractStatus currentStatus, ContractStatus requiredStatus); /** * @dev reverted with this error when an account that has won is trying to transfer his or her last AccessPassNFT * during WINNERS_FROZEN in TicketNFT * @param account is the address trying to transfer * @param currentTimestamp is the current block's timestamp * @param requiredTimestamp is the timestamp the block must at least be in */ error TransferringFrozenAccount(address account, uint256 currentTimestamp, uint256 requiredTimestamp); /********************** EXTERNAL ********************************/ /** * @notice private mints for people in the whitelist * @param verifiedSlot is a signed message by the whitelist signer that presents how many the minter can mint */ function privateMint(VerifiedSlot calldata verifiedSlot) external payable; /* * @notice public mints for anyone */ function publicMint() external payable; /** * @notice Randomize the NFT. This requests a random Chainlink value, which causes the tier of each nft id to be known. * @dev See https://docs.chain.link/docs/vrf-contracts/#configurations for Chainlink VRF documentation * @param subscriptionId The chainlink subscription id that pays for the call to Chainlink, needs to be setup with ChainLink beforehand * @param gasLane The maximum gas price you are willing to pay for a Chainlink VRF request in wei * @param callbackGasLimit How much gas to use for the callback request. Approximately 29_000 is used up solely by * fulfillRandomWords */ function randomizeTiers( uint64 subscriptionId, bytes32 gasLane, uint32 callbackGasLimit ) external; /** * @notice sets the base URI for the token metadata * @dev This can only happen once after the generation of the token metadata in unison with the winners function. * @param revealedURI must end in a '/' (slash), because the tokenURI expects it to end in a slash. */ function revealTiers(string memory revealedURI) external; /** * @notice Randomize the tickets. This requests a random Chainlink value, which causes the winners to be known. * @dev See https://docs.chain.link/docs/vrf-contracts/#configurations for Chainlink VRF documentation * @param subscriptionId The chainlink subscription id that pays for the call to Chainlink, needs to be setup with ChainLink beforehand * @param gasLane The maximum gas price you are willing to pay for a Chainlink VRF request in wei * @param callbackGasLimit How much gas to use for the callback request. Approximately 31_000 gas is used up * solely by fulfillRandomWords. */ function randomizeTickets( uint64 subscriptionId, bytes32 gasLane, uint32 callbackGasLimit ) external; /** * @notice sets the whitelist signer * @dev immediately do this after deploying the contract * @param whiteListSigner_ is the signer address for verifying the minting slots */ function setWhitelistSigner(address whiteListSigner_) external; /** * @notice sets the ticketNFT * @dev set this before selecting the TicketWinners in TicketNFT * @param ticketNFT_ is the TicketNFT that selects the ticketWinners */ function setTicketNFT(TicketNFT ticketNFT_) external; /** * @notice sets the recipient of the eth from public and private minting and the royalty fees * @dev setRoyaltyFee right after setting the treasury * @param treasury_ could be an EOA or a gnosis contract that receives eth and royalty fees */ function setTreasury(address payable treasury_) external; /** * @notice sets the royalty fee for the second hand market selling * @param royaltyFee is the fees taken from second-hand selling. This is expressed in a _royaltyFee/10_000. * So to do 5% means supplying 500 since 500/10_000 is 5% (see ERC2981 function _setDefaultRoyalty(address receiver, uint96 feeNumerator)) */ function setRoyaltyFee(uint96 royaltyFee) external; /** * @notice sets the price of minting. the amount is sent to the treasury right after the minting * @param price_ is expressed in wei */ function setPrice(uint256 price_) external; /** * @notice sets the contract uri * @param contractURI_ points to a json file that follows OpenSeas standard (see https://docs.opensea.io/docs/contract-level-metadata) */ function setContractURI(string memory contractURI_) external; /** * @notice sets the unrevealedURI * @param unrevealedURI_ points to a json file with the placeholder image inside */ function setUnrevealedURI(string memory unrevealedURI_) external; /** * @notice sets the private minting timestamp * @param privateMintingTimestamp_ is when private minting is enabled. Setting this to zero disables all minting */ function setPrivateMintingTimestamp(uint256 privateMintingTimestamp_) external; /** * @notice sets the public minting timestamp * @param publicMintingTimestamp_ is when public minting will be enabled. * Setting this to zero disables public minting. * If set, public minting must happen after private minting */ function setPublicMintingTimestamp(uint256 publicMintingTimestamp_) external; /** /* @notice sets how many a minter can public mint /* @param maxPublicMintable_ is how many a public account can mint */ function setMaxPublicMintable(uint16 maxPublicMintable_) external; /********************** EXTERNAL VIEW ********************************/ /** * @notice returns the count an account has minted * @param minter is for the account being queried */ function mintedBy(address minter) external view returns (uint256); /** * @notice returns the count an account has minted per type * @param minter is for the account being queried * @param mintingType is the type of minting expected */ function mintedBy(address minter, MintingType mintingType) external view returns (uint256); /** * @notice Returns the tier for an nft id * @param tokenId is the id of the token being queried */ function nftTier(uint256 tokenId) external view returns (uint16 tier); /** * @notice Returns true if the ticketsRandomWord has been set in the VRF Callback * @dev this is used by TicketNFT as a prerequisite for the airdrop. See TicketNFT for more info. */ function ticketsRevealed() external view returns(bool); /** * @notice Returns an array of all NFT id's, with 500 winners, indicated by 1. The others are indicated by 0. */ function winners() external view returns (uint16[] memory); /** * @notice returns the current supply of the NFT */ function totalSupply() external view returns (uint256); /** * @notice returns the current contract status of the NFT */ function contractStatus() external view returns (ContractStatus); /** * @notice Returns an array with all nft id's and their tier * @dev This function works by filling a pool with random values. When we exhaust the pool, * we refill the pool again with different values. We do it like this because we don't * know in advance how many random values we need. */ function nftTiers() external view returns (uint16[] memory); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4 <0.8.6; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @title Required interface for a TicketNFT compliant contract * @author Oost & Voort, Inc */ interface ITicketNFT is IERC165 { /** * @dev The following are the stages of the contract in order: * PRE_AIRDROP: Before the airdrop has happened * TICKETS_REVEALED: when accessPassNFT has already set who the TicketWinners will be * AIRDROPPED_TICKETS: when the nfts have been airdropped * SET_REGISTRATION: when the _hasNotRegistered have been filled up * WINNERS_FROZEN: When the winners have been frozen from doing transfers * TRADING_ENABLED: When all trading has been enabled again */ enum ContractStatus { PRE_AIRDROP, TICKETS_REVEALED, AIRDROPPED_TICKETS, SET_REGISTRATION, WINNERS_FROZEN, TRADING_ENABLED } /** * @dev emitted when the owner has changed the contract uri * @param oldURI is the uri it was set as before * @param newURI is the uri it is now set in */ event ContractURISet(string oldURI, string newURI); /** * @dev emitted when the owner changes the royalties * @param newRoyaltyAddress is the new royalty address that will receive the royalties. * @param newRoyalties is the new royalties set by the owner */ event RoyaltiesSet(address newRoyaltyAddress, uint96 newRoyalties); /** * @dev emitted when the frozenPeriod has been set * @param oldTimestamp is the old timestamp for when the frozenPeriod was set * @param newTimestamp is the timestamp for when the frozenPeriod will now correspond as */ event FrozenPeriodSet(uint256 oldTimestamp, uint256 newTimestamp); /** * @dev the following events must be done in order */ /** * @dev emitted when the airdrop happens * @param winners is the ids of winners from AccessPassNFT. See AccessPassNFT's winners function for more information. */ event TicketsAirdropped(uint16[] winners); /** * @dev emitted when the registration has been set * @param hasRegistered is an array boolean that represents if the onwer of that index has registered off-chain */ event RegistrationSet(bool[] hasRegistered); /** * @dev emitted when a random number has been requested from VRF * @param requestId is the id sent back by VRF to keep track of the request */ event RandomWordRequested(uint256 requestId); /** * @dev emitted when a ticket winner has been selected * @param randomWord is used to determine the TicketWinner */ event TicketWinnersSelected(uint256 randomWord); /** * @dev emitted when the trading for winners have been frozen * @param frozenTimestamp is until when trading for winning nfts have been frozen for */ event TicketWinnersFrozen(uint256 frozenTimestamp); /** * @dev reverted with this error when the address being supplied is Zero Address * @param addressName is for whom the Zero Address is being set for */ error ZeroAddress(string addressName); /** * @dev reverted with this error when a view function is being used to look for a nonExistent Token */ error NonExistentToken(); /** * @dev reverted with this error when a function is being called more than once */ error CallingMoreThanOnce(); /** * @dev reverted with this error when a variable has an incorrect value * @param variableName is the name of the variable with an incorrect value */ error IncorrectValue(string variableName); /** * @dev reverted with this error when a string being supplied should not be empty * @param stringName is the name of the string being supplied with an empty value */ error EmptyString(string stringName); /** * @dev reverted with this error when a function being called should not be called with the current Contract Status * @param currentStatus is the contract's current status * @param requiredStatus is the status the current must be in for the function to not revert */ error IncorrectContractStatus(ContractStatus currentStatus, ContractStatus requiredStatus); /** * @dev reverted with this error when transferring a winningId during frozenPeriod * @param tokenId is the id being transferred * @param currentTimestamp is the current block's timestamp * @param requiredTimestamp is the timestamp the block must at least be in */ error TransferringFrozenToken(uint256 tokenId, uint256 currentTimestamp, uint256 requiredTimestamp); /** * @notice airdrops to accessPassNFT winners * @param winners are accessPassNFT winners taken off-chain */ function airdrop( uint16[] calldata winners ) external; /** * @notice requests a random word from VRF to be used for selecting a ticket winner * @dev See https://docs.chain.link/docs/vrf-contracts/#configurations for Chainlink VRF documentation * @param subscriptionId The chainlink subscription id that pays for the call to Chainlink, needs to be setup with ChainLink beforehand * @param gasLane The maximum gas price you are willing to pay for a Chainlink VRF request in wei * @param callbackGasLimit How much gas to use for the callback request. Approximately 139_000 gas is used up solely * by fulfillRandomWords. */ function requestRandomWord( uint64 subscriptionId, bytes32 gasLane, uint32 callbackGasLimit ) external; /** * @notice sets the contract uri * @param uri points to a json file that follows OpenSeas standard (see https://docs.opensea.io/docs/contract-level-metadata) */ function setContractURI(string memory uri) external; /** * @notice sets the royalty fee for the second hand market selling * @param royaltyAddress is the recepient of royalty fees from second hand market. * @param royaltyFee is the fees taken from second-hand selling. This is expressed in a _royaltyFee/1000. * So to do 5% means supplying 50 since 50/1000 is 5% (see ERC2981 function _setDefaultRoyalty(address receiver, uint96 feeNumerator)) */ function setDefaultRoyalty(address royaltyAddress, uint96 royaltyFee) external; /** * @notice sets the ids of the people who have not registered * @dev It is important to do this before requesting a random word. To make it cheaper gas-wise, sending an empty * array signifies that all token owners registered off-chain. An explanation of what the array of hasRegistered looks * like will follow: * if the owner of token id 0 has registered in the array it will show as true, * so [true, ...] * if the owner of token id 1 has not registered in the array it will show as false * so [true, false, ...] * and so on.. * @param hasRegistered_ is an array of boolean that tells if the owner of the id has registered off-chain */ function setRegistered(bool[] calldata hasRegistered_) external; /** * @notice sets the frozenPeriod for when trading winning token ids is disabled * @param frozenPeriod_ is a timestamp for when the ticket winners can start trading again */ function setFrozenPeriod(uint256 frozenPeriod_) external; /** * @notice returns if the token id has registered or not * @param tokenId is the id of the token being queried */ function hasRegistered( uint16 tokenId ) external view returns (bool); /** * @notice Returns if the address owns a winning nft * @param account is the queried address */ function isAccountWinner(address account) external view returns (bool); /** * @notice returns the current contract status of the NFT */ function contractStatus() external view returns (ContractStatus); /** * @notice returns the current supply of the NFT */ function totalSupply() external view returns (uint256); }
// 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 (last updated v4.5.0) (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) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ 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. 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 if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } 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 pragma solidity ^0.8.0; interface IVerifiedSlot { struct VerifiedSlot { address minter; uint16 mintingCapacity; uint8 v; bytes32 r; bytes32 s; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.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: balance query for the zero address"); 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: owner query for nonexistent token"); 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) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 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 owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); 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: transfer caller is not 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: transfer caller is not 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) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); 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 a {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 a {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 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 { 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.6.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: * * - `tokenId` must be already minted. * - `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 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 (last updated v4.6.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 be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) 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 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.5.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 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/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.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); }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address payable","name":"treasury_","type":"address"},{"internalType":"address","name":"vrfCoordinator_","type":"address"},{"internalType":"uint16","name":"maxTotalSupply_","type":"uint16"},{"internalType":"uint16","name":"goldenTierSupply_","type":"uint16"},{"internalType":"uint16","name":"silverTierSupply_","type":"uint16"},{"internalType":"uint16","name":"ticketSupply_","type":"uint16"},{"internalType":"uint256","name":"privateMintingTimestamp_","type":"uint256"},{"internalType":"uint96","name":"royaltyFee","type":"uint96"},{"internalType":"uint256","name":"price_","type":"uint256"},{"internalType":"string","name":"contractURI_","type":"string"},{"internalType":"string","name":"unrevealedURI_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"CallerIsNotMinter","type":"error"},{"inputs":[],"name":"CallingMoreThanOnce","type":"error"},{"inputs":[],"name":"CanNoLongerCall","type":"error"},{"inputs":[{"internalType":"string","name":"stringName","type":"string"}],"name":"EmptyString","type":"error"},{"inputs":[{"internalType":"uint256","name":"minted","type":"uint256"}],"name":"ExceedMintingCapacity","type":"error"},{"inputs":[{"internalType":"enum IAccessPassNFT.ContractStatus","name":"currentStatus","type":"uint8"},{"internalType":"enum IAccessPassNFT.ContractStatus","name":"requiredStatus","type":"uint8"}],"name":"IncorrectContractStatus","type":"error"},{"inputs":[{"internalType":"string","name":"variableName","type":"string"}],"name":"IncorrectValue","type":"error"},{"inputs":[{"internalType":"string","name":"variableName","type":"string"}],"name":"IsZero","type":"error"},{"inputs":[],"name":"NonExistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"},{"internalType":"uint256","name":"requiredTimestamp","type":"uint256"}],"name":"TransferringFrozenAccount","type":"error"},{"inputs":[{"internalType":"address","name":"unknownSigner","type":"address"},{"internalType":"address","name":"whitelistSigner","type":"address"}],"name":"UnknownSigner","type":"error"},{"inputs":[],"name":"WhitelistSignerIsZeroAddress","type":"error"},{"inputs":[{"internalType":"string","name":"addressName","type":"string"}],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAddressQuery","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":"string","name":"oldURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"oldMaxPublicMintable","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"newMaxPublicMintable","type":"uint16"}],"name":"MaxPublicMintableSet","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":"uint256","name":"oldPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"}],"name":"PrivateMintingTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"}],"name":"PublicMintingTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"newRoyalties","type":"uint96"}],"name":"RoyaltyFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract TicketNFT","name":"oldTicketNFT","type":"address"},{"indexed":false,"internalType":"contract TicketNFT","name":"newTicketNFT","type":"address"}],"name":"TicketNFTSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"TicketsRandomWordRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"randomWord","type":"uint256"}],"name":"TicketsRandomized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"TiersRandomWordRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"randomWord","type":"uint256"}],"name":"TiersRandomized","type":"event"},{"anonymous":false,"inputs":[],"name":"TiersRevealed","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":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TreasuryPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasurySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"oldURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"UnrevealedURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"WhitelistSignerSet","type":"event"},{"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":[],"name":"chainlinkCoordinator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractStatus","outputs":[{"internalType":"enum IAccessPassNFT.ContractStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"goldenTierSupply","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":"maxPublicMintable","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTotalSupply","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"enum IAccessPassNFT.MintingType","name":"mintingType","type":"uint8"}],"name":"mintedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"mintedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"nftTier","outputs":[{"internalType":"uint16","name":"tier","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftTiers","outputs":[{"internalType":"uint16[]","name":"","type":"uint16[]"}],"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":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"uint16","name":"mintingCapacity","type":"uint16"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IVerifiedSlot.VerifiedSlot","name":"verifiedSlot","type":"tuple"}],"name":"privateMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"privateMintingTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicMintingTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"subscriptionId","type":"uint64"},{"internalType":"bytes32","name":"gasLane","type":"bytes32"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"}],"name":"randomizeTickets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"subscriptionId","type":"uint64"},{"internalType":"bytes32","name":"gasLane","type":"bytes32"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"}],"name":"randomizeTiers","outputs":[],"stateMutability":"nonpayable","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":"string","name":"revealedURI","type":"string"}],"name":"revealTiers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"contractURI_","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"maxPublicMintable_","type":"uint16"}],"name":"setMaxPublicMintable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"privateMintingTimestamp_","type":"uint256"}],"name":"setPrivateMintingTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"publicMintingTimestamp_","type":"uint256"}],"name":"setPublicMintingTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"royaltyFee","type":"uint96"}],"name":"setRoyaltyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract TicketNFT","name":"ticketNFT_","type":"address"}],"name":"setTicketNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"treasury_","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"unrevealedURI_","type":"string"}],"name":"setUnrevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"whiteListSigner_","type":"address"}],"name":"setWhitelistSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"silverTierSupply","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":"ticketNFT","outputs":[{"internalType":"contract TicketNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketSupply","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketsRandomWord","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketsRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketsRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tiersRandomWord","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tiersRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tiersRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenIdCounter","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whiteListSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"winners","outputs":[{"internalType":"uint16[]","name":"","type":"uint16[]"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b506040516200610e3803806200610e833981016040819052620000359162000f14565b896040518060400160405280601d81526020017f4d617261646f6e61204f6666696369616c204163636573732050617373000000815250604051806040016040528060048152602001634f4d464360e01b815250620000a36200009d6200062c60201b60201c565b62000630565b6040805160c081018252600d608082019081526c1058d8d95cdcd4185cdcd39195609a1b60a083015281528151808301835260018152603160f81b6020828101919091528201524691810191909152306060820152620001039062000680565b60015581516200011b90600590602085019062000d97565b5080516200013190600690602084019062000d97565b50505060601b6001600160601b0319166080526001600160a01b038b166200018c5760405163eac0d38960e01b8152602060048201526008602482015267747265617375727960c01b60448201526064015b60405180910390fd5b601480546001600160a01b0319166001600160a01b038d8116919091179091558a16620001ee5760405163eac0d38960e01b815260206004820152600e60248201526d3b393321b7b7b93234b730ba37b960911b604482015260640162000183565b601680546001600160a01b0319166001600160a01b038c1617905561ffff89166200024e57604051630fc3a38f60e41b815260206004820152600e60248201526d6d6178546f74616c537570706c7960901b604482015260640162000183565b6001600160f01b031960f08a901b1660a05261ffff891662000271888a620010dd565b61ffff1610620002db5760405162461bcd60e51b815260206004820152602e60248201527f5469657220537570706c696573206d757374206265206c657373207468616e2060448201526d6d6178546f74616c537570706c7960901b606482015260840162000183565b61ffff88166200032257604051630fc3a38f60e41b815260206004820152601060248201526f676f6c64656e54696572537570706c7960801b604482015260640162000183565b6001600160f01b031960f089901b1660c05261ffff87166200037b57604051630fc3a38f60e41b815260206004820152601060248201526f73696c76657254696572537570706c7960801b604482015260640162000183565b6001600160f01b031960f088901b1660e05261ffff8981169087161115620003d657604051636b6afd1760e11b815260206004820152600c60248201526b7469636b6574537570706c7960a01b604482015260640162000183565b6001600160f01b031960f087901b1661010052600d8590556001600160601b0384166200043457604051630fc3a38f60e41b815260206004820152600a602482015269726f79616c747946656560b01b604482015260640162000183565b620004408b856200071e565b826200047857604051630fc3a38f60e41b8152602060048201526005602482015264707269636560d81b604482015260640162000183565b600f839055604080518082019091526001808252602f60f81b602090920182905282518392918391620004ac919062001121565b81518110620004cb57634e487b7160e01b600052603260045260246000fd5b01602001517fff0000000000000000000000000000000000000000000000000000000000000016146200053257604051636b6afd1760e11b815260206004820152600d60248201526c756e72657665616c656455524960981b604482015260640162000183565b81516200054790601190602085019062000d97565b50825162000587576040516318a996bb60e21b815260206004820152600b60248201526a636f6e747261637455524960a81b604482015260640162000183565b82516200059c90601390602086019062000d97565b5060108054600a61ffff199091161790556000620005c7600c6200081f602090811b62002e8b17901c565b9050620005d5338262000823565b620005ec600c6200084960201b62002e8f1760201c565b336000908152600b6020526040812060019081018054919290916200061390849062001106565b90915550620011d39d5050505050505050505050505050565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82600001518051906020012083602001518051906020012084604001518560600151604051602001620007019594939291909485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b604051602081830303815290604052805190602001209050919050565b6127106001600160601b03821611156200078e5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b606482015260840162000183565b6001600160a01b038216620007e65760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640162000183565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600355565b5490565b620008458282604051806020016040528060008152506200085260201b60201c565b5050565b80546001019055565b6200085e8383620008ca565b6200086d600084848462000a20565b620008c55760405162461bcd60e51b81526020600482015260326024820152600080516020620060ee83398151915260448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606482015260840162000183565b505050565b6001600160a01b038216620009225760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640162000183565b6000818152600760205260409020546001600160a01b031615620009895760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640162000183565b620009976000838362000b89565b6001600160a01b0382166000908152600860205260408120805460019290620009c290849062001106565b909155505060008181526007602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600062000a41846001600160a01b031662000cff60201b62002e981760201c565b1562000b7d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029062000a7b90339089908890889060040162001087565b602060405180830381600087803b15801562000a9657600080fd5b505af192505050801562000ac9575060408051601f3d908101601f1916820190925262000ac69181019062001044565b60015b62000b62573d80801562000afa576040519150601f19603f3d011682016040523d82523d6000602084013e62000aff565b606091505b50805162000b5a5760405162461bcd60e51b81526020600482015260326024820152600080516020620060ee83398151915260448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606482015260840162000183565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905062000b81565b5060015b949350505050565b6015546001600160a01b031615620008c55760155460408051632c77ddfd60e01b815290516000926001600160a01b031691632c77ddfd916004808301926020929190829003018186803b15801562000be157600080fd5b505afa15801562000bf6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c1c91906200106e565b9050804210801562000caa575060155460405163927e603d60e01b81526001600160a01b0386811660048301529091169063927e603d9060240160206040518083038186803b15801562000c6f57600080fd5b505afa15801562000c84573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000caa91906200101b565b801562000cc1575062000cbd8462000d0e565b6001145b1562000cf9576040516365e7520f60e01b81526001600160a01b03851660048201524260248201526044810182905260640162000183565b50505050565b6001600160a01b03163b151590565b60006001600160a01b03821662000d7b5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840162000183565b506001600160a01b031660009081526008602052604090205490565b82805462000da5906200116a565b90600052602060002090601f01602090048101928262000dc9576000855562000e14565b82601f1062000de457805160ff191683800117855562000e14565b8280016001018555821562000e14579182015b8281111562000e1457825182559160200191906001019062000df7565b5062000e2292915062000e26565b5090565b5b8082111562000e22576000815560010162000e27565b80516001600160a01b038116811462000e5557600080fd5b919050565b600082601f83011262000e6b578081fd5b81516001600160401b038082111562000e885762000e88620011bd565b604051601f8301601f19908116603f0116810190828211818310171562000eb35762000eb3620011bd565b8160405283815286602085880101111562000ecc578485fd5b62000edf8460208301602089016200113b565b9695505050505050565b805161ffff8116811462000e5557600080fd5b80516001600160601b038116811462000e5557600080fd5b60008060008060008060008060008060006101608c8e03121562000f36578687fd5b62000f418c62000e3d565b9a5062000f5160208d0162000e3d565b995062000f6160408d0162000ee9565b985062000f7160608d0162000ee9565b975062000f8160808d0162000ee9565b965062000f9160a08d0162000ee9565b955060c08c0151945062000fa860e08d0162000efc565b6101008d01516101208e015191955093506001600160401b0381111562000fcd578283fd5b62000fdb8e828f0162000e5a565b6101408e015190935090506001600160401b0381111562000ffa578182fd5b620010088e828f0162000e5a565b9150509295989b509295989b9093969950565b6000602082840312156200102d578081fd5b815180151581146200103d578182fd5b9392505050565b60006020828403121562001056578081fd5b81516001600160e01b0319811681146200103d578182fd5b60006020828403121562001080578081fd5b5051919050565b600060018060a01b038087168352808616602084015250836040830152608060608301528251806080840152620010c68160a08501602087016200113b565b601f01601f19169190910160a00195945050505050565b600061ffff808316818516808303821115620010fd57620010fd620011a7565b01949350505050565b600082198211156200111c576200111c620011a7565b500190565b600082821015620011365762001136620011a7565b500390565b60005b83811015620011585781810151838201526020016200113e565b8381111562000cf95750506000910152565b600181811c908216806200117f57607f821691505b60208210811415620011a157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160601c60a05160f01c60c05160f01c60e05160f01c6101005160f01c614e8f6200125f6000396000818161065d0152611fb8015260008181610878015261236601526000818161094e015261220301526000818161052901528181611f3b01528181612186015281816127070152613886015260008181610e9c0152610ef70152614e8f6000f3fe6080604052600436106103975760003560e01c8063938e3d7b116101dc578063c6ee20d211610102578063e985e9c5116100a0578063f56153921161006f578063f561539214610ad9578063faf6f4a714610af9578063fe2c7fee14610b0f578063ff9d21f014610b2f57600080fd5b8063e985e9c514610a30578063f0f4426014610a79578063f2fde38b14610a99578063f4f5457214610ab957600080fd5b8063d0bb2189116100dc578063d0bb2189146109c5578063d3381438146109db578063e59af732146109fb578063e8a3d48514610a1b57600080fd5b8063c6ee20d214610970578063c788839b14610992578063c87b56dd146109a557600080fd5b8063ae51dace1161017a578063b882ac9611610149578063b882ac96146108f0578063b88d4fde14610906578063ba11509414610926578063c5b6cc121461093c57600080fd5b8063ae51dace14610866578063b27f8ddc1461089a578063b393391b146108b0578063b4332f32146108d057600080fd5b8063a035b1fe116101b6578063a035b1fe146107f9578063a22cb4651461080f578063a487bcd81461082f578063ad6e30c21461085157600080fd5b8063938e3d7b146107ad57806395d89b41146107cd57806398bdf6f5146107e257600080fd5b806340dd7320116102c15780636966f3a91161025f57806376d5862c1161022e57806376d5862c1461073457806379984efc146107545780638da5cb5b1461076f57806391b7f5ed1461078d57600080fd5b80636966f3a9146106bf5780636ade389b146106df57806370a08231146106ff578063715018a61461071f57600080fd5b80635d62e4681161029b5780635d62e4681461062b5780635d83c2b81461064b57806361d027b31461067f5780636352211e1461069f57600080fd5b806340dd7320146105cb57806342842e0e146105eb578063521331991461060b57600080fd5b806323b872dd1161033957806331faafb41161030857806331faafb41461055e5780633c893ecb1461057e5780633cef28d2146105945780633f3ac92c146105b457600080fd5b806323b872dd146104b057806326092b83146104d05780632a55205a146104d85780632ab4d0521461051757600080fd5b8063095ea7b311610375578063095ea7b31461042b57806318160ddd1461044d5780631d575cf5146104705780631fe543e31461049057600080fd5b806301ffc9a71461039c57806306fdde03146103d1578063081812fc146103f3575b600080fd5b3480156103a857600080fd5b506103bc6103b7366004614756565b610b4f565b60405190151581526020015b60405180910390f35b3480156103dd57600080fd5b506103e6610b93565b6040516103c89190614bd1565b3480156103ff57600080fd5b5061041361040e3660046148a8565b610c25565b6040516001600160a01b0390911681526020016103c8565b34801561043757600080fd5b5061044b61044636600461470f565b610cbf565b005b34801561045957600080fd5b50610462610df1565b6040519081526020016103c8565b34801561047c57600080fd5b5061046261048b3660046146df565b610e01565b34801561049c57600080fd5b5061044b6104ab3660046148d8565b610e91565b3480156104bc57600080fd5b5061044b6104cb3660046145f5565b610f32565b61044b610fb9565b3480156104e457600080fd5b506104f86104f336600461498c565b611080565b604080516001600160a01b0390931683526020830191909152016103c8565b34801561052357600080fd5b5061054b7f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff90911681526020016103c8565b34801561056a57600080fd5b5061044b610579366004614a02565b61113b565b34801561058a57600080fd5b5061046260185481565b3480156105a057600080fd5b506104626105af3660046145a1565b6111dd565b3480156105c057600080fd5b50601a5415156103bc565b3480156105d757600080fd5b5061044b6105e63660046149ad565b611230565b3480156105f757600080fd5b5061044b6106063660046145f5565b611414565b34801561061757600080fd5b5061054b6106263660046148a8565b61142f565b34801561063757600080fd5b5061044b6106463660046147ad565b6114d6565b34801561065757600080fd5b5061054b7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068b57600080fd5b50601454610413906001600160a01b031681565b3480156106ab57600080fd5b506104136106ba3660046148a8565b611693565b3480156106cb57600080fd5b5061044b6106da3660046148a8565b61171e565b3480156106eb57600080fd5b5061044b6106fa3660046145a1565b61188b565b34801561070b57600080fd5b5061046261071a3660046145a1565b611b09565b34801561072b57600080fd5b5061044b611ba3565b34801561074057600080fd5b5061044b61074f36600461488e565b611bf7565b34801561076057600080fd5b5060105461054b9061ffff1681565b34801561077b57600080fd5b506000546001600160a01b0316610413565b34801561079957600080fd5b5061044b6107a83660046148a8565b611ceb565b3480156107b957600080fd5b5061044b6107c83660046147ad565b611dc2565b3480156107d957600080fd5b506103e6611ebf565b3480156107ee57600080fd5b50600c546104629081565b34801561080557600080fd5b50610462600f5481565b34801561081b57600080fd5b5061044b61082a3660046146b2565b611ece565b34801561083b57600080fd5b50610844611ed9565b6040516103c89190614b60565b34801561085d57600080fd5b5061084461212a565b34801561087257600080fd5b5061054b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156108a657600080fd5b50610462600d5481565b3480156108bc57600080fd5b50601554610413906001600160a01b031681565b3480156108dc57600080fd5b5061044b6108eb3660046148a8565b6124c3565b3480156108fc57600080fd5b5061046260195481565b34801561091257600080fd5b5061044b610921366004614635565b61263d565b34801561093257600080fd5b50610462600e5481565b34801561094857600080fd5b5061054b7f000000000000000000000000000000000000000000000000000000000000000081565b34801561097c57600080fd5b506109856126cb565b6040516103c89190614ba8565b61044b6109a03660046147f3565b61279c565b3480156109b157600080fd5b506103e66109c03660046148a8565b61280b565b3480156109d157600080fd5b50610462601a5481565b3480156109e757600080fd5b5061044b6109f63660046145a1565b612890565b348015610a0757600080fd5b50601654610413906001600160a01b031681565b348015610a2757600080fd5b506103e66128e1565b348015610a3c57600080fd5b506103bc610a4b3660046145bd565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b348015610a8557600080fd5b5061044b610a943660046145a1565b61296f565b348015610aa557600080fd5b5061044b610ab43660046145a1565b612a90565b348015610ac557600080fd5b506010546103bc9062010000900460ff1681565b348015610ae557600080fd5b50600254610413906001600160a01b031681565b348015610b0557600080fd5b5061046260175481565b348015610b1b57600080fd5b5061044b610b2a3660046147ad565b612b5d565b348015610b3b57600080fd5b5061044b610b4a3660046149ad565b612cb2565b60006001600160e01b031982167fb75e1f9f000000000000000000000000000000000000000000000000000000001480610b8d5750610b8d82612ea7565b92915050565b606060058054610ba290614d39565b80601f0160208091040260200160405190810160405280929190818152602001828054610bce90614d39565b8015610c1b5780601f10610bf057610100808354040283529160200191610c1b565b820191906000526020600020905b815481529060010190602001808311610bfe57829003601f168201915b5050505050905090565b6000818152600760205260408120546001600160a01b0316610ca35760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600960205260409020546001600160a01b031690565b6000610cca82611693565b9050806001600160a01b0316836001600160a01b03161415610d545760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610c9a565b336001600160a01b0382161480610d705750610d708133610a4b565b610de25760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610c9a565b610dec8383612eb2565b505050565b6000610dfc600c5490565b905090565b60006001600160a01b038316610e2a5760405163331715f760e11b815260040160405180910390fd5b6000826001811115610e4c57634e487b7160e01b600052602160045260246000fd5b1415610e7457506001600160a01b0382166000908152600b6020526040902060010154610b8d565b50506001600160a01b03166000908152600b602052604090205490565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f24576040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610c9a565b610f2e8282612f20565b5050565b610f3c3382613094565b610fae5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610c9a565b610dec83838361318b565b600280610fc46126cb565b6006811115610fe357634e487b7160e01b600052602160045260246000fd5b1461102557610ff06126cb565b816040517ff975326c000000000000000000000000000000000000000000000000000000008152600401610c9a929190614bb6565b601054336000908152600b602052604090205461ffff9091161161107157336000908152600b602052604090819020549051631ebf81cf60e21b81526004810191909152602401610c9a565b61107d33346001613363565b50565b60008281526004602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046bffffffffffffffffffffffff169282019290925282916110ff5750604080518082019091526003546001600160a01b0381168252600160a01b90046bffffffffffffffffffffffff1660208201525b602081015160009061271090611123906bffffffffffffffffffffffff1687614cd7565b61112d9190614cc3565b915196919550909350505050565b6000546001600160a01b031633146111835760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b601454611199906001600160a01b0316826134fc565b6040516bffffffffffffffffffffffff821681527ff4220e27e94f63cac283717e73a4c580428428bc7149f113d01665ea64d6718f9060200160405180910390a150565b60006001600160a01b0382166112065760405163331715f760e11b815260040160405180910390fd5b6001600160a01b0382166000908152600b602052604090208054600190910154610b8d9190614cab565b6000546001600160a01b031633146112785760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6003806112836126cb565b60068111156112a257634e487b7160e01b600052602160045260246000fd5b10156112b057610ff06126cb565b601854156112d1576040516311cfd2ad60e01b815260040160405180910390fd5b619c408263ffffffff16101561132a57604051636b6afd1760e11b815260206004820152601060248201527f63616c6c6261636b4761734c696d6974000000000000000000000000000000006044820152606401610c9a565b6016546040516305d3b1d360e41b81526004810185905267ffffffffffffffff861660248201526003604482015263ffffffff84166064820152600160848201526001600160a01b03909116908190635d3b1d309060a401602060405180830381600087803b15801561139c57600080fd5b505af11580156113b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d491906148c0565b60178190556040519081527f2a88d24fc50b57dbdb005dcfbcaa7b17a93129c4c00f6e1743023f0091cde801906020015b60405180910390a15050505050565b610dec8383836040518060200160405280600081525061263d565b600060048061143c6126cb565b600681111561145b57634e487b7160e01b600052602160045260246000fd5b101561146957610ff06126cb565b6000838152600760205260409020546001600160a01b031661149e57604051634a1850bf60e11b815260040160405180910390fd5b6114a661212a565b83815181106114c557634e487b7160e01b600052603260045260246000fd5b602002602001015191505b50919050565b6000546001600160a01b0316331461151e5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6004806115296126cb565b600681111561154857634e487b7160e01b600052602160045260246000fd5b101561155657610ff06126cb565b60105462010000900460ff16156115805760405163ba4ace8d60e01b815260040160405180910390fd5b604080518082019091526001808252602f60f81b6020909201829052835184929183916115ad9190614cf6565b815181106115cb57634e487b7160e01b600052603260045260246000fd5b01602001517fff00000000000000000000000000000000000000000000000000000000000000161461164057604051636b6afd1760e11b815260206004820152600b60248201527f72657665616c65645552490000000000000000000000000000000000000000006044820152606401610c9a565b82516116539060129060208601906144a2565b506010805462ff00001916620100001790556040517f1e4137ab05aad9af97415bad5605b301d36fbc9eb3f28e0753d4d819c565f87b90600090a1505050565b6000818152600760205260408120546001600160a01b031680610b8d5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610c9a565b6000546001600160a01b031633146117665760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b60026000611775600183614cf6565b600681111561179457634e487b7160e01b600052602160045260246000fd5b90508160068111156117b657634e487b7160e01b600052602160045260246000fd5b6117be6126cb565b60068111156117dd57634e487b7160e01b600052602160045260246000fd5b106117ea57610ff06126cb565b600d54831080156117fa57508215155b1561184857604051636b6afd1760e11b815260206004820152601660248201527f7075626c69634d696e74696e6754696d657374616d70000000000000000000006044820152606401610c9a565b600e5460408051918252602082018590527f0bb04c825da052df0301d5b2b1292d51aa85c2d379b4c4d03f2d998ad2c57a86910160405180910390a15050600e55565b6000546001600160a01b031633146118d35760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6040516301ffc9a760e01b81527f89a32daf0000000000000000000000000000000000000000000000000000000060048201819052906001600160a01b038316906301ffc9a79060240160206040518083038186803b15801561193557600080fd5b505afa158015611949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196d919061473a565b6119ba57604051636b6afd1760e11b815260206004820152600a60248201527f7469636b65744e46545f000000000000000000000000000000000000000000006044820152606401610c9a565b6015546001600160a01b031615611a9f57601554604080517fc6ee20d200000000000000000000000000000000000000000000000000000000815290516001926001600160a01b03169163c6ee20d2916004808301926020929190829003018186803b158015611a2957600080fd5b505afa158015611a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a61919061478e565b6005811115611a8057634e487b7160e01b600052602160045260246000fd5b1115611a9f576040516311cfd2ad60e01b815260040160405180910390fd5b601554604080516001600160a01b03928316815291841660208301527fecb905e703386325d99f190a7cac2df474bcefe4e4d59a55a8c2798047aeba13910160405180910390a150601580546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b038216611b875760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610c9a565b506001600160a01b031660009081526008602052604090205490565b6000546001600160a01b03163314611beb5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b611bf56000613616565b565b6000546001600160a01b03163314611c3f5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b61ffff8116611c9157604051630fc3a38f60e41b815260206004820152601160248201527f6d61785075626c69634d696e7461626c650000000000000000000000000000006044820152606401610c9a565b6010546040805161ffff928316815291831660208301527fb8d7b99ec4233306f8a0b1f89da0eaebba724b9fbe56261e064e9a6bc31e2bbc910160405180910390a16010805461ffff191661ffff92909216919091179055565b6000546001600160a01b03163314611d335760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b80611d8157604051630fc3a38f60e41b815260206004820152600560248201527f70726963650000000000000000000000000000000000000000000000000000006044820152606401610c9a565b600f5460408051918252602082018390527fa0f1665b7b659537b52deec61ea64d134a3bccda74c7f4e79f2246e7a8187a8a910160405180910390a1600f55565b6000546001600160a01b03163314611e0a5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b8051611e72576040517f62a65aec00000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f636f6e74726163745552490000000000000000000000000000000000000000006044820152606401610c9a565b7fd144c5914915e649557dfce6d3199a18bae1ec7c249c1766603a2b76ade11c06601382604051611ea4929190614be4565b60405180910390a18051610f2e9060139060208401906144a2565b606060068054610ba290614d39565b610f2e338383613666565b6060600680611ee66126cb565b6006811115611f0557634e487b7160e01b600052602160045260246000fd5b1015611f1357610ff06126cb565b600060649050600080611f35601a54848480611f2e90614d6e565b9550613735565b905060007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff811115611f8457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611fad578160200160208202803683370190505b50905060008060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff1681101561211c578483611fed81614d6e565b94508151811061200d57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156120435761203c601a5488888061203590614d6e565b9950613735565b9450600092505b83828151811061206357634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff166000146120d557848361208181614d6e565b9450815181106120a157634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156120d0576120c9601a5488888061203590614d6e565b9450600092505b612043565b60018483815181106120f757634e487b7160e01b600052603260045260246000fd5b61ffff909216602092830291909101909101528061211481614d6e565b915050611fb6565b5091965050505050505b5090565b60606004806121376126cb565b600681111561215657634e487b7160e01b600052602160045260246000fd5b101561216457610ff06126cb565b60006101f49050600080612180601854848480611f2e90614d6e565b905060007f000000000000000000000000000000000000000000000000000000000000000061ffff1667ffffffffffffffff8111156121cf57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156121f8578160200160208202803683370190505b50905060008060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff1681101561236057848361223881614d6e565b94508151811061225857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156122875761228060185488888061203590614d6e565b9450600092505b8382815181106122a757634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff166000146123195784836122c581614d6e565b9450815181106122e557634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156123145761230d60185488888061203590614d6e565b9450600092505b612287565b600284838151811061233b57634e487b7160e01b600052603260045260246000fd5b61ffff909216602092830291909101909101528061235881614d6e565b915050612201565b5060005b7f000000000000000000000000000000000000000000000000000000000000000061ffff1681101561211c57848361239b81614d6e565b9450815181106123bb57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156123ea576123e360185488888061203590614d6e565b9450600092505b83828151811061240a57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff1660001461247c57848361242881614d6e565b94508151811061244857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156124775761247060185488888061203590614d6e565b9450600092505b6123ea565b600184838151811061249e57634e487b7160e01b600052603260045260246000fd5b61ffff90921660209283029190910190910152806124bb81614d6e565b915050612364565b6000546001600160a01b0316331461250b5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b600160006125198280614cf6565b600681111561253857634e487b7160e01b600052602160045260246000fd5b905081600681111561255a57634e487b7160e01b600052602160045260246000fd5b6125626126cb565b600681111561258157634e487b7160e01b600052602160045260246000fd5b1061258e57610ff06126cb565b600e54831015801561259f57508215155b80156125ac5750600e5415155b156125fa57604051636b6afd1760e11b815260206004820152601760248201527f707269766174654d696e74696e6754696d657374616d700000000000000000006044820152606401610c9a565b600d5460408051918252602082018590527fb49b0d2203b2bce8f0c1930d69dabfc245275b5ec32dc6f328806e33a4d71581910160405180910390a15050600d55565b6126473383613094565b6126b95760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610c9a565b6126c584848484613939565b50505050565b6000601a546000146126dd5750600690565b60105462010000900460ff16156126f45750600590565b601854156127025750600490565b600c547f000000000000000000000000000000000000000000000000000000000000000061ffff1614156127365750600390565b600d5442101580156127495750600d5415155b80156127605750600e544210806127605750600e54155b1561276b5750600190565b600e54421015801561277e5750600e5415155b801561278b5750600d5415155b156127965750600290565b50600090565b6001806127a76126cb565b60068111156127c657634e487b7160e01b600052602160045260246000fd5b146127d357610ff06126cb565b336000818152600b60205260409020600101546127ff91906127fa36869003860186614804565b6139b7565b610f2e33346000613363565b6000818152600760205260409020546060906001600160a01b031661284357604051634a1850bf60e11b815260040160405180910390fd5b60105462010000900460ff1661288557601161285e83613adc565b60405160200161286f929190614a7c565b6040516020818303038152906040529050919050565b601261285e83613adc565b6000546001600160a01b031633146128d85760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b61107d81613c2a565b601380546128ee90614d39565b80601f016020809104026020016040519081016040528092919081815260200182805461291a90614d39565b80156129675780601f1061293c57610100808354040283529160200191612967565b820191906000526020600020905b81548152906001019060200180831161294a57829003601f168201915b505050505081565b6000546001600160a01b031633146129b75760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6001600160a01b038116612a27576040517feac0d38900000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f74726561737572790000000000000000000000000000000000000000000000006044820152606401610c9a565b601454604080516001600160a01b03928316815291831660208301527f21eb548722a564f6e09f039f7aa858ae94c911910f3823b37af2250eeca4f403910160405180910390a1601480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612ad85760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6001600160a01b038116612b545760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c9a565b61107d81613616565b6000546001600160a01b03163314612ba55760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b604080518082019091526001808252602f60f81b602090920182905282518392918391612bd29190614cf6565b81518110612bf057634e487b7160e01b600052603260045260246000fd5b01602001517fff000000000000000000000000000000000000000000000000000000000000001614612c6557604051636b6afd1760e11b815260206004820152600d60248201527f756e72657665616c6564555249000000000000000000000000000000000000006044820152606401610c9a565b7f8191e07a9f461509729f31da9b0bb812915c3252f697cbf19fc60a700c14e379601183604051612c97929190614be4565b60405180910390a18151610dec9060119060208501906144a2565b6000546001600160a01b03163314612cfa5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b600380612d056126cb565b6006811115612d2457634e487b7160e01b600052602160045260246000fd5b1015612d3257610ff06126cb565b601a5415612d53576040516311cfd2ad60e01b815260040160405180910390fd5b619c408263ffffffff161015612dac57604051636b6afd1760e11b815260206004820152601060248201527f63616c6c6261636b4761734c696d6974000000000000000000000000000000006044820152606401610c9a565b6016546040516305d3b1d360e41b81526004810185905267ffffffffffffffff861660248201526003604482015263ffffffff84166064820152600160848201526001600160a01b03909116908190635d3b1d309060a401602060405180830381600087803b158015612e1e57600080fd5b505af1158015612e32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5691906148c0565b60198190556040519081527f386f7e0e864241c7e92166f1441c88d40259979d0d6fe045ae15c5e0011c7a7290602001611405565b5490565b80546001019055565b6001600160a01b03163b151590565b6000610b8d82613cba565b600081815260096020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612ee782611693565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b81612f6e57604051630fc3a38f60e41b815260206004820152600960248201527f72657175657374496400000000000000000000000000000000000000000000006044820152606401610c9a565b6017548214156130075760185415612f995760405163ba4ace8d60e01b815260040160405180910390fd5b80600081518110612fba57634e487b7160e01b600052603260045260246000fd5b60200260200101516018819055507f260b0d780ce5d3acea4dbce31d432406bb72fea1d4b7e2571b4558445a45c8d6601854604051612ffb91815260200190565b60405180910390a15050565b601954821415610f2e57601a54156130325760405163ba4ace8d60e01b815260040160405180910390fd5b8060008151811061305357634e487b7160e01b600052603260045260246000fd5b6020026020010151601a819055507f1acc627535151d4af646035fc4bc45bb7f1f35139d354287404bd6a074bfaf69601a54604051612ffb91815260200190565b6000818152600760205260408120546001600160a01b031661310d5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610c9a565b600061311883611693565b9050806001600160a01b0316846001600160a01b0316148061315f57506001600160a01b038082166000908152600a602090815260408083209388168352929052205460ff165b806131835750836001600160a01b031661317884610c25565b6001600160a01b0316145b949350505050565b826001600160a01b031661319e82611693565b6001600160a01b03161461321a5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610c9a565b6001600160a01b0382166132955760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610c9a565b6132a0838383613d2c565b6132ab600082612eb2565b6001600160a01b03831660009081526008602052604081208054600192906132d4908490614cf6565b90915550506001600160a01b0382166000908152600860205260408120805460019290613302908490614cab565b909155505060008181526007602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60036000613372600183614cf6565b600681111561339157634e487b7160e01b600052602160045260246000fd5b90508160068111156133b357634e487b7160e01b600052602160045260246000fd5b6133bb6126cb565b60068111156133da57634e487b7160e01b600052602160045260246000fd5b106133e757610ff06126cb565b600f54841461343957604051636b6afd1760e11b815260206004820152600a60248201527f616d6f756e7450616964000000000000000000000000000000000000000000006044820152606401610c9a565b6000613444600c5490565b90506134508686613ed8565b61345e600c80546001019055565b83600181111561347e57634e487b7160e01b600052602160045260246000fd5b6134bb576001600160a01b0386166000908152600b6020526040812060019081018054919290916134b0908490614cab565b909155506134ea9050565b6001600160a01b0386166000908152600b602052604081208054600192906134e4908490614cab565b90915550505b6134f48682613fc3565b505050505050565b6127106bffffffffffffffffffffffff821611156135825760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c2065786365656460448201527f2073616c655072696365000000000000000000000000000000000000000000006064820152608401610c9a565b6001600160a01b0382166135d85760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610c9a565b604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff9091166020909201829052600160a01b90910217600355565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b816001600160a01b0316836001600160a01b031614156136c85760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c9a565b6001600160a01b038381166000818152600a6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b60608361378557604051630fc3a38f60e41b815260206004820152600a60248201527f72616e646f6d576f7264000000000000000000000000000000000000000000006044820152606401610c9a565b61ffff6000613795601086614cc3565b905060006137a4601087614daa565b11156137b8576137b5600182614cab565b90505b60006137c48286614cd7565b6137cf906010614cd7565b905060006137de836010614cd7565b67ffffffffffffffff81111561380457634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561382d578160200160208202803683370190505b50905060005b8381101561392b576000896138488584614cab565b6040805160208101939093528201526060016040516020818303038152906040528051906020012060001c905060005b6010811015613916576138ad7f0000000000000000000000000000000000000000000000000000000000000000838916614d89565b84826138ba866010614cd7565b6138c49190614cab565b815181106138e257634e487b7160e01b600052603260045260246000fd5b61ffff909216602092830291909101909101526139026201000083614cc3565b91508061390e81614d6e565b915050613878565b5050808061392390614d6e565b915050613833565b5093505050505b9392505050565b61394484848461318b565b61395084848484613fdd565b6126c55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610c9a565b6002546001600160a01b03166139e05760405163a75e096760e01b815260040160405180910390fd5b826001600160a01b031681600001516001600160a01b031614613a455780516040517ff1a669ce0000000000000000000000000000000000000000000000000000000081526001600160a01b0380861660048301529091166024820152604401610c9a565b81816020015161ffff1611613a7057604051631ebf81cf60e21b815260048101839052602401610c9a565b6000613a7b82614135565b6002549091506001600160a01b038083169116146126c5576002546040517f6cd82d240000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529091166024820152604401610c9a565b606081613b1c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115613b465780613b3081614d6e565b9150613b3f9050600a83614cc3565b9150613b20565b60008167ffffffffffffffff811115613b6f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613b99576020820181803683370190505b5090505b841561318357613bae600183614cf6565b9150613bbb600a86614daa565b613bc6906030614cab565b60f81b818381518110613be957634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613c23600a86614cc3565b9450613b9d565b6001600160a01b038116613c515760405163a75e096760e01b815260040160405180910390fd5b600254604080516001600160a01b03928316815291831660208301527f9fed3c0e42aa7f73947a13ac6757a3d73c8f820c1c1d45bfdb2a3f9d3f812a07910160405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160e01b031982167f80ac58cd000000000000000000000000000000000000000000000000000000001480613d1d57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610b8d5750610b8d82614211565b6015546001600160a01b031615610dec57601554604080517f2c77ddfd00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691632c77ddfd916004808301926020929190829003018186803b158015613d9b57600080fd5b505afa158015613daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dd391906148c0565b90508042108015613e7557506015546040517f927e603d0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301529091169063927e603d9060240160206040518083038186803b158015613e3d57600080fd5b505afa158015613e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e75919061473a565b8015613e895750613e8584611b09565b6001145b156126c5576040517f65e7520f0000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015242602482015260448101829052606401610c9a565b6014546040516000916001600160a01b03169083908381818185875af1925050503d8060008114613f25576040519150601f19603f3d011682016040523d82523d6000602084013e613f2a565b606091505b5050905080613f7b5760405162461bcd60e51b815260206004820152601660248201527f436f756c64206e6f7420706179207472656173757279000000000000000000006044820152606401610c9a565b826001600160a01b03167fb5668d929317b36d7b61952ab446b7e4dd82c4d9f90788b407c35e90440f567883604051613fb691815260200190565b60405180910390a2505050565b610f2e82826040518060200160405280600081525061425f565b60006001600160a01b0384163b1561412a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614021903390899088908890600401614b24565b602060405180830381600087803b15801561403b57600080fd5b505af192505050801561406b575060408051601f3d908101601f1916820190925261406891810190614772565b60015b614110573d808015614099576040519150601f19603f3d011682016040523d82523d6000602084013e61409e565b606091505b5080516141085760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610c9a565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613183565b506001949350505050565b600080600154614144846142dd565b6040517f1901000000000000000000000000000000000000000000000000000000000000602082015260228101929092526042820152606201604051602081830303815290604052805190602001209050600181846040015185606001518660800151604051600081526020016040526040516141dd949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156141ff573d6000803e3d6000fd5b5050604051601f190151949350505050565b60006001600160e01b031982167f2a55205a000000000000000000000000000000000000000000000000000000001480610b8d57506301ffc9a760e01b6001600160e01b0319831614610b8d565b6142698383614354565b6142766000848484613fdd565b610dec5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610c9a565b8051602080830151604051600093614337937f9016184a70237a58286b5c611a44cf3c4b67b9ec2da552661f6a04c1395282d5939192019283526001600160a01b0391909116602083015261ffff16604082015260600190565b604051602081830303815290604052805190602001209050919050565b6001600160a01b0382166143aa5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c9a565b6000818152600760205260409020546001600160a01b03161561440f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c9a565b61441b60008383613d2c565b6001600160a01b0382166000908152600860205260408120805460019290614444908490614cab565b909155505060008181526007602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b8280546144ae90614d39565b90600052602060002090601f0160209004810192826144d05760008555614516565b82601f106144e957805160ff1916838001178555614516565b82800160010185558215614516579182015b828111156145165782518255916020019190600101906144fb565b506121269291505b80821115612126576000815560010161451e565b600067ffffffffffffffff83111561454c5761454c614dea565b61455f601f8401601f1916602001614c7a565b905082815283838301111561457357600080fd5b828260208301376000602084830101529392505050565b803561ffff8116811461459c57600080fd5b919050565b6000602082840312156145b2578081fd5b813561393281614e00565b600080604083850312156145cf578081fd5b82356145da81614e00565b915060208301356145ea81614e00565b809150509250929050565b600080600060608486031215614609578081fd5b833561461481614e00565b9250602084013561462481614e00565b929592945050506040919091013590565b6000806000806080858703121561464a578182fd5b843561465581614e00565b9350602085013561466581614e00565b925060408501359150606085013567ffffffffffffffff811115614687578182fd5b8501601f81018713614697578182fd5b6146a687823560208401614532565b91505092959194509250565b600080604083850312156146c4578182fd5b82356146cf81614e00565b915060208301356145ea81614e15565b600080604083850312156146f1578182fd5b82356146fc81614e00565b91506020830135600281106145ea578182fd5b60008060408385031215614721578182fd5b823561472c81614e00565b946020939093013593505050565b60006020828403121561474b578081fd5b815161393281614e15565b600060208284031215614767578081fd5b813561393281614e23565b600060208284031215614783578081fd5b815161393281614e23565b60006020828403121561479f578081fd5b815160068110613932578182fd5b6000602082840312156147be578081fd5b813567ffffffffffffffff8111156147d4578182fd5b8201601f810184136147e4578182fd5b61318384823560208401614532565b600060a082840312156114d0578081fd5b600060a08284031215614815578081fd5b60405160a0810181811067ffffffffffffffff8211171561483857614838614dea565b604052823561484681614e00565b81526148546020840161458a565b6020820152604083013560ff8116811461486c578283fd5b6040820152606083810135908201526080928301359281019290925250919050565b60006020828403121561489f578081fd5b6139328261458a565b6000602082840312156148b9578081fd5b5035919050565b6000602082840312156148d1578081fd5b5051919050565b600080604083850312156148ea578182fd5b8235915060208084013567ffffffffffffffff80821115614909578384fd5b818601915086601f83011261491c578384fd5b81358181111561492e5761492e614dea565b8060051b915061493f848301614c7a565b8181528481019084860184860187018b1015614959578788fd5b8795505b8386101561497b57803583526001959095019491860191860161495d565b508096505050505050509250929050565b6000806040838503121561499e578182fd5b50508035926020909101359150565b6000806000606084860312156149c1578081fd5b833567ffffffffffffffff811681146149d8578182fd5b925060208401359150604084013563ffffffff811681146149f7578182fd5b809150509250925092565b600060208284031215614a13578081fd5b81356bffffffffffffffffffffffff81168114613932578182fd5b60008151808452614a46816020860160208601614d0d565b601f01601f19169290920160200192915050565b60078110614a7857634e487b7160e01b600052602160045260246000fd5b9052565b6000808454614a8a81614d39565b60018281168015614aa25760018114614ab357614adf565b60ff19841687528287019450614adf565b8886526020808720875b85811015614ad65781548a820152908401908201614abd565b50505082870194505b505050508351614af3818360208801614d0d565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000009101908152600501949350505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152614b566080830184614a2e565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614b9c57835161ffff1683529284019291840191600101614b7c565b50909695505050505050565b60208101610b8d8284614a5a565b60408101614bc48285614a5a565b6139326020830184614a5a565b6020815260006139326020830184614a2e565b604081526000808454614bf681614d39565b8060408601526060600180841660008114614c185760018114614c2c57614c5a565b60ff19851688840152608088019550614c5a565b8987526020808820885b86811015614c515781548b8201870152908401908201614c36565b8a018501975050505b50505050508281036020840152614c718185614a2e565b95945050505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715614ca357614ca3614dea565b604052919050565b60008219821115614cbe57614cbe614dbe565b500190565b600082614cd257614cd2614dd4565b500490565b6000816000190483118215151615614cf157614cf1614dbe565b500290565b600082821015614d0857614d08614dbe565b500390565b60005b83811015614d28578181015183820152602001614d10565b838111156126c55750506000910152565b600181811c90821680614d4d57607f821691505b602082108114156114d057634e487b7160e01b600052602260045260246000fd5b6000600019821415614d8257614d82614dbe565b5060010190565b600061ffff80841680614d9e57614d9e614dd4565b92169190910692915050565b600082614db957614db9614dd4565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461107d57600080fd5b801515811461107d57600080fd5b6001600160e01b03198116811461107d57600080fdfe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220b3144f75f071b381966b4b44338ff0d329f69549cf83d122078d79f583a3dadc64736f6c634300080400334552433732313a207472616e7366657220746f206e6f6e204552433732315265000000000000000000000000455ad5835b5f732a8c28d0ad79abf7942f586906000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000004e200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000632c403000000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000214e8348c4f0000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000005168747470733a2f2f73332e65752d776573742d322e616d617a6f6e6177732e636f6d2f6d617261646f6e616f6666696369616c2e696f2f61636365737350617373436f6e74726163745552492e6a736f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036697066733a2f2f516d5a346e696a4e546b5933556a3766327a71766d6b5a57386873344e6e42345878514d35474c7277554a4d52522f00000000000000000000
Deployed Bytecode
0x6080604052600436106103975760003560e01c8063938e3d7b116101dc578063c6ee20d211610102578063e985e9c5116100a0578063f56153921161006f578063f561539214610ad9578063faf6f4a714610af9578063fe2c7fee14610b0f578063ff9d21f014610b2f57600080fd5b8063e985e9c514610a30578063f0f4426014610a79578063f2fde38b14610a99578063f4f5457214610ab957600080fd5b8063d0bb2189116100dc578063d0bb2189146109c5578063d3381438146109db578063e59af732146109fb578063e8a3d48514610a1b57600080fd5b8063c6ee20d214610970578063c788839b14610992578063c87b56dd146109a557600080fd5b8063ae51dace1161017a578063b882ac9611610149578063b882ac96146108f0578063b88d4fde14610906578063ba11509414610926578063c5b6cc121461093c57600080fd5b8063ae51dace14610866578063b27f8ddc1461089a578063b393391b146108b0578063b4332f32146108d057600080fd5b8063a035b1fe116101b6578063a035b1fe146107f9578063a22cb4651461080f578063a487bcd81461082f578063ad6e30c21461085157600080fd5b8063938e3d7b146107ad57806395d89b41146107cd57806398bdf6f5146107e257600080fd5b806340dd7320116102c15780636966f3a91161025f57806376d5862c1161022e57806376d5862c1461073457806379984efc146107545780638da5cb5b1461076f57806391b7f5ed1461078d57600080fd5b80636966f3a9146106bf5780636ade389b146106df57806370a08231146106ff578063715018a61461071f57600080fd5b80635d62e4681161029b5780635d62e4681461062b5780635d83c2b81461064b57806361d027b31461067f5780636352211e1461069f57600080fd5b806340dd7320146105cb57806342842e0e146105eb578063521331991461060b57600080fd5b806323b872dd1161033957806331faafb41161030857806331faafb41461055e5780633c893ecb1461057e5780633cef28d2146105945780633f3ac92c146105b457600080fd5b806323b872dd146104b057806326092b83146104d05780632a55205a146104d85780632ab4d0521461051757600080fd5b8063095ea7b311610375578063095ea7b31461042b57806318160ddd1461044d5780631d575cf5146104705780631fe543e31461049057600080fd5b806301ffc9a71461039c57806306fdde03146103d1578063081812fc146103f3575b600080fd5b3480156103a857600080fd5b506103bc6103b7366004614756565b610b4f565b60405190151581526020015b60405180910390f35b3480156103dd57600080fd5b506103e6610b93565b6040516103c89190614bd1565b3480156103ff57600080fd5b5061041361040e3660046148a8565b610c25565b6040516001600160a01b0390911681526020016103c8565b34801561043757600080fd5b5061044b61044636600461470f565b610cbf565b005b34801561045957600080fd5b50610462610df1565b6040519081526020016103c8565b34801561047c57600080fd5b5061046261048b3660046146df565b610e01565b34801561049c57600080fd5b5061044b6104ab3660046148d8565b610e91565b3480156104bc57600080fd5b5061044b6104cb3660046145f5565b610f32565b61044b610fb9565b3480156104e457600080fd5b506104f86104f336600461498c565b611080565b604080516001600160a01b0390931683526020830191909152016103c8565b34801561052357600080fd5b5061054b7f000000000000000000000000000000000000000000000000000000000000138881565b60405161ffff90911681526020016103c8565b34801561056a57600080fd5b5061044b610579366004614a02565b61113b565b34801561058a57600080fd5b5061046260185481565b3480156105a057600080fd5b506104626105af3660046145a1565b6111dd565b3480156105c057600080fd5b50601a5415156103bc565b3480156105d757600080fd5b5061044b6105e63660046149ad565b611230565b3480156105f757600080fd5b5061044b6106063660046145f5565b611414565b34801561061757600080fd5b5061054b6106263660046148a8565b61142f565b34801561063757600080fd5b5061044b6106463660046147ad565b6114d6565b34801561065757600080fd5b5061054b7f00000000000000000000000000000000000000000000000000000000000001f481565b34801561068b57600080fd5b50601454610413906001600160a01b031681565b3480156106ab57600080fd5b506104136106ba3660046148a8565b611693565b3480156106cb57600080fd5b5061044b6106da3660046148a8565b61171e565b3480156106eb57600080fd5b5061044b6106fa3660046145a1565b61188b565b34801561070b57600080fd5b5061046261071a3660046145a1565b611b09565b34801561072b57600080fd5b5061044b611ba3565b34801561074057600080fd5b5061044b61074f36600461488e565b611bf7565b34801561076057600080fd5b5060105461054b9061ffff1681565b34801561077b57600080fd5b506000546001600160a01b0316610413565b34801561079957600080fd5b5061044b6107a83660046148a8565b611ceb565b3480156107b957600080fd5b5061044b6107c83660046147ad565b611dc2565b3480156107d957600080fd5b506103e6611ebf565b3480156107ee57600080fd5b50600c546104629081565b34801561080557600080fd5b50610462600f5481565b34801561081b57600080fd5b5061044b61082a3660046146b2565b611ece565b34801561083b57600080fd5b50610844611ed9565b6040516103c89190614b60565b34801561085d57600080fd5b5061084461212a565b34801561087257600080fd5b5061054b7f00000000000000000000000000000000000000000000000000000000000004e281565b3480156108a657600080fd5b50610462600d5481565b3480156108bc57600080fd5b50601554610413906001600160a01b031681565b3480156108dc57600080fd5b5061044b6108eb3660046148a8565b6124c3565b3480156108fc57600080fd5b5061046260195481565b34801561091257600080fd5b5061044b610921366004614635565b61263d565b34801561093257600080fd5b50610462600e5481565b34801561094857600080fd5b5061054b7f00000000000000000000000000000000000000000000000000000000000002ee81565b34801561097c57600080fd5b506109856126cb565b6040516103c89190614ba8565b61044b6109a03660046147f3565b61279c565b3480156109b157600080fd5b506103e66109c03660046148a8565b61280b565b3480156109d157600080fd5b50610462601a5481565b3480156109e757600080fd5b5061044b6109f63660046145a1565b612890565b348015610a0757600080fd5b50601654610413906001600160a01b031681565b348015610a2757600080fd5b506103e66128e1565b348015610a3c57600080fd5b506103bc610a4b3660046145bd565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b348015610a8557600080fd5b5061044b610a943660046145a1565b61296f565b348015610aa557600080fd5b5061044b610ab43660046145a1565b612a90565b348015610ac557600080fd5b506010546103bc9062010000900460ff1681565b348015610ae557600080fd5b50600254610413906001600160a01b031681565b348015610b0557600080fd5b5061046260175481565b348015610b1b57600080fd5b5061044b610b2a3660046147ad565b612b5d565b348015610b3b57600080fd5b5061044b610b4a3660046149ad565b612cb2565b60006001600160e01b031982167fb75e1f9f000000000000000000000000000000000000000000000000000000001480610b8d5750610b8d82612ea7565b92915050565b606060058054610ba290614d39565b80601f0160208091040260200160405190810160405280929190818152602001828054610bce90614d39565b8015610c1b5780601f10610bf057610100808354040283529160200191610c1b565b820191906000526020600020905b815481529060010190602001808311610bfe57829003601f168201915b5050505050905090565b6000818152600760205260408120546001600160a01b0316610ca35760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600960205260409020546001600160a01b031690565b6000610cca82611693565b9050806001600160a01b0316836001600160a01b03161415610d545760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610c9a565b336001600160a01b0382161480610d705750610d708133610a4b565b610de25760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610c9a565b610dec8383612eb2565b505050565b6000610dfc600c5490565b905090565b60006001600160a01b038316610e2a5760405163331715f760e11b815260040160405180910390fd5b6000826001811115610e4c57634e487b7160e01b600052602160045260246000fd5b1415610e7457506001600160a01b0382166000908152600b6020526040902060010154610b8d565b50506001600160a01b03166000908152600b602052604090205490565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699091614610f24576040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909166024820152604401610c9a565b610f2e8282612f20565b5050565b610f3c3382613094565b610fae5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610c9a565b610dec83838361318b565b600280610fc46126cb565b6006811115610fe357634e487b7160e01b600052602160045260246000fd5b1461102557610ff06126cb565b816040517ff975326c000000000000000000000000000000000000000000000000000000008152600401610c9a929190614bb6565b601054336000908152600b602052604090205461ffff9091161161107157336000908152600b602052604090819020549051631ebf81cf60e21b81526004810191909152602401610c9a565b61107d33346001613363565b50565b60008281526004602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046bffffffffffffffffffffffff169282019290925282916110ff5750604080518082019091526003546001600160a01b0381168252600160a01b90046bffffffffffffffffffffffff1660208201525b602081015160009061271090611123906bffffffffffffffffffffffff1687614cd7565b61112d9190614cc3565b915196919550909350505050565b6000546001600160a01b031633146111835760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b601454611199906001600160a01b0316826134fc565b6040516bffffffffffffffffffffffff821681527ff4220e27e94f63cac283717e73a4c580428428bc7149f113d01665ea64d6718f9060200160405180910390a150565b60006001600160a01b0382166112065760405163331715f760e11b815260040160405180910390fd5b6001600160a01b0382166000908152600b602052604090208054600190910154610b8d9190614cab565b6000546001600160a01b031633146112785760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6003806112836126cb565b60068111156112a257634e487b7160e01b600052602160045260246000fd5b10156112b057610ff06126cb565b601854156112d1576040516311cfd2ad60e01b815260040160405180910390fd5b619c408263ffffffff16101561132a57604051636b6afd1760e11b815260206004820152601060248201527f63616c6c6261636b4761734c696d6974000000000000000000000000000000006044820152606401610c9a565b6016546040516305d3b1d360e41b81526004810185905267ffffffffffffffff861660248201526003604482015263ffffffff84166064820152600160848201526001600160a01b03909116908190635d3b1d309060a401602060405180830381600087803b15801561139c57600080fd5b505af11580156113b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d491906148c0565b60178190556040519081527f2a88d24fc50b57dbdb005dcfbcaa7b17a93129c4c00f6e1743023f0091cde801906020015b60405180910390a15050505050565b610dec8383836040518060200160405280600081525061263d565b600060048061143c6126cb565b600681111561145b57634e487b7160e01b600052602160045260246000fd5b101561146957610ff06126cb565b6000838152600760205260409020546001600160a01b031661149e57604051634a1850bf60e11b815260040160405180910390fd5b6114a661212a565b83815181106114c557634e487b7160e01b600052603260045260246000fd5b602002602001015191505b50919050565b6000546001600160a01b0316331461151e5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6004806115296126cb565b600681111561154857634e487b7160e01b600052602160045260246000fd5b101561155657610ff06126cb565b60105462010000900460ff16156115805760405163ba4ace8d60e01b815260040160405180910390fd5b604080518082019091526001808252602f60f81b6020909201829052835184929183916115ad9190614cf6565b815181106115cb57634e487b7160e01b600052603260045260246000fd5b01602001517fff00000000000000000000000000000000000000000000000000000000000000161461164057604051636b6afd1760e11b815260206004820152600b60248201527f72657665616c65645552490000000000000000000000000000000000000000006044820152606401610c9a565b82516116539060129060208601906144a2565b506010805462ff00001916620100001790556040517f1e4137ab05aad9af97415bad5605b301d36fbc9eb3f28e0753d4d819c565f87b90600090a1505050565b6000818152600760205260408120546001600160a01b031680610b8d5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610c9a565b6000546001600160a01b031633146117665760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b60026000611775600183614cf6565b600681111561179457634e487b7160e01b600052602160045260246000fd5b90508160068111156117b657634e487b7160e01b600052602160045260246000fd5b6117be6126cb565b60068111156117dd57634e487b7160e01b600052602160045260246000fd5b106117ea57610ff06126cb565b600d54831080156117fa57508215155b1561184857604051636b6afd1760e11b815260206004820152601660248201527f7075626c69634d696e74696e6754696d657374616d70000000000000000000006044820152606401610c9a565b600e5460408051918252602082018590527f0bb04c825da052df0301d5b2b1292d51aa85c2d379b4c4d03f2d998ad2c57a86910160405180910390a15050600e55565b6000546001600160a01b031633146118d35760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6040516301ffc9a760e01b81527f89a32daf0000000000000000000000000000000000000000000000000000000060048201819052906001600160a01b038316906301ffc9a79060240160206040518083038186803b15801561193557600080fd5b505afa158015611949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196d919061473a565b6119ba57604051636b6afd1760e11b815260206004820152600a60248201527f7469636b65744e46545f000000000000000000000000000000000000000000006044820152606401610c9a565b6015546001600160a01b031615611a9f57601554604080517fc6ee20d200000000000000000000000000000000000000000000000000000000815290516001926001600160a01b03169163c6ee20d2916004808301926020929190829003018186803b158015611a2957600080fd5b505afa158015611a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a61919061478e565b6005811115611a8057634e487b7160e01b600052602160045260246000fd5b1115611a9f576040516311cfd2ad60e01b815260040160405180910390fd5b601554604080516001600160a01b03928316815291841660208301527fecb905e703386325d99f190a7cac2df474bcefe4e4d59a55a8c2798047aeba13910160405180910390a150601580546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b038216611b875760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610c9a565b506001600160a01b031660009081526008602052604090205490565b6000546001600160a01b03163314611beb5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b611bf56000613616565b565b6000546001600160a01b03163314611c3f5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b61ffff8116611c9157604051630fc3a38f60e41b815260206004820152601160248201527f6d61785075626c69634d696e7461626c650000000000000000000000000000006044820152606401610c9a565b6010546040805161ffff928316815291831660208301527fb8d7b99ec4233306f8a0b1f89da0eaebba724b9fbe56261e064e9a6bc31e2bbc910160405180910390a16010805461ffff191661ffff92909216919091179055565b6000546001600160a01b03163314611d335760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b80611d8157604051630fc3a38f60e41b815260206004820152600560248201527f70726963650000000000000000000000000000000000000000000000000000006044820152606401610c9a565b600f5460408051918252602082018390527fa0f1665b7b659537b52deec61ea64d134a3bccda74c7f4e79f2246e7a8187a8a910160405180910390a1600f55565b6000546001600160a01b03163314611e0a5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b8051611e72576040517f62a65aec00000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f636f6e74726163745552490000000000000000000000000000000000000000006044820152606401610c9a565b7fd144c5914915e649557dfce6d3199a18bae1ec7c249c1766603a2b76ade11c06601382604051611ea4929190614be4565b60405180910390a18051610f2e9060139060208401906144a2565b606060068054610ba290614d39565b610f2e338383613666565b6060600680611ee66126cb565b6006811115611f0557634e487b7160e01b600052602160045260246000fd5b1015611f1357610ff06126cb565b600060649050600080611f35601a54848480611f2e90614d6e565b9550613735565b905060007f000000000000000000000000000000000000000000000000000000000000138861ffff1667ffffffffffffffff811115611f8457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611fad578160200160208202803683370190505b50905060008060005b7f00000000000000000000000000000000000000000000000000000000000001f461ffff1681101561211c578483611fed81614d6e565b94508151811061200d57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156120435761203c601a5488888061203590614d6e565b9950613735565b9450600092505b83828151811061206357634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff166000146120d557848361208181614d6e565b9450815181106120a157634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156120d0576120c9601a5488888061203590614d6e565b9450600092505b612043565b60018483815181106120f757634e487b7160e01b600052603260045260246000fd5b61ffff909216602092830291909101909101528061211481614d6e565b915050611fb6565b5091965050505050505b5090565b60606004806121376126cb565b600681111561215657634e487b7160e01b600052602160045260246000fd5b101561216457610ff06126cb565b60006101f49050600080612180601854848480611f2e90614d6e565b905060007f000000000000000000000000000000000000000000000000000000000000138861ffff1667ffffffffffffffff8111156121cf57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156121f8578160200160208202803683370190505b50905060008060005b7f00000000000000000000000000000000000000000000000000000000000002ee61ffff1681101561236057848361223881614d6e565b94508151811061225857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156122875761228060185488888061203590614d6e565b9450600092505b8382815181106122a757634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff166000146123195784836122c581614d6e565b9450815181106122e557634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156123145761230d60185488888061203590614d6e565b9450600092505b612287565b600284838151811061233b57634e487b7160e01b600052603260045260246000fd5b61ffff909216602092830291909101909101528061235881614d6e565b915050612201565b5060005b7f00000000000000000000000000000000000000000000000000000000000004e261ffff1681101561211c57848361239b81614d6e565b9450815181106123bb57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156123ea576123e360185488888061203590614d6e565b9450600092505b83828151811061240a57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff1660001461247c57848361242881614d6e565b94508151811061244857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff169150868314156124775761247060185488888061203590614d6e565b9450600092505b6123ea565b600184838151811061249e57634e487b7160e01b600052603260045260246000fd5b61ffff90921660209283029190910190910152806124bb81614d6e565b915050612364565b6000546001600160a01b0316331461250b5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b600160006125198280614cf6565b600681111561253857634e487b7160e01b600052602160045260246000fd5b905081600681111561255a57634e487b7160e01b600052602160045260246000fd5b6125626126cb565b600681111561258157634e487b7160e01b600052602160045260246000fd5b1061258e57610ff06126cb565b600e54831015801561259f57508215155b80156125ac5750600e5415155b156125fa57604051636b6afd1760e11b815260206004820152601760248201527f707269766174654d696e74696e6754696d657374616d700000000000000000006044820152606401610c9a565b600d5460408051918252602082018590527fb49b0d2203b2bce8f0c1930d69dabfc245275b5ec32dc6f328806e33a4d71581910160405180910390a15050600d55565b6126473383613094565b6126b95760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610c9a565b6126c584848484613939565b50505050565b6000601a546000146126dd5750600690565b60105462010000900460ff16156126f45750600590565b601854156127025750600490565b600c547f000000000000000000000000000000000000000000000000000000000000138861ffff1614156127365750600390565b600d5442101580156127495750600d5415155b80156127605750600e544210806127605750600e54155b1561276b5750600190565b600e54421015801561277e5750600e5415155b801561278b5750600d5415155b156127965750600290565b50600090565b6001806127a76126cb565b60068111156127c657634e487b7160e01b600052602160045260246000fd5b146127d357610ff06126cb565b336000818152600b60205260409020600101546127ff91906127fa36869003860186614804565b6139b7565b610f2e33346000613363565b6000818152600760205260409020546060906001600160a01b031661284357604051634a1850bf60e11b815260040160405180910390fd5b60105462010000900460ff1661288557601161285e83613adc565b60405160200161286f929190614a7c565b6040516020818303038152906040529050919050565b601261285e83613adc565b6000546001600160a01b031633146128d85760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b61107d81613c2a565b601380546128ee90614d39565b80601f016020809104026020016040519081016040528092919081815260200182805461291a90614d39565b80156129675780601f1061293c57610100808354040283529160200191612967565b820191906000526020600020905b81548152906001019060200180831161294a57829003601f168201915b505050505081565b6000546001600160a01b031633146129b75760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6001600160a01b038116612a27576040517feac0d38900000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f74726561737572790000000000000000000000000000000000000000000000006044820152606401610c9a565b601454604080516001600160a01b03928316815291831660208301527f21eb548722a564f6e09f039f7aa858ae94c911910f3823b37af2250eeca4f403910160405180910390a1601480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612ad85760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b6001600160a01b038116612b545760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c9a565b61107d81613616565b6000546001600160a01b03163314612ba55760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b604080518082019091526001808252602f60f81b602090920182905282518392918391612bd29190614cf6565b81518110612bf057634e487b7160e01b600052603260045260246000fd5b01602001517fff000000000000000000000000000000000000000000000000000000000000001614612c6557604051636b6afd1760e11b815260206004820152600d60248201527f756e72657665616c6564555249000000000000000000000000000000000000006044820152606401610c9a565b7f8191e07a9f461509729f31da9b0bb812915c3252f697cbf19fc60a700c14e379601183604051612c97929190614be4565b60405180910390a18151610dec9060119060208501906144a2565b6000546001600160a01b03163314612cfa5760405162461bcd60e51b81526020600482018190526024820152600080516020614e3a8339815191526044820152606401610c9a565b600380612d056126cb565b6006811115612d2457634e487b7160e01b600052602160045260246000fd5b1015612d3257610ff06126cb565b601a5415612d53576040516311cfd2ad60e01b815260040160405180910390fd5b619c408263ffffffff161015612dac57604051636b6afd1760e11b815260206004820152601060248201527f63616c6c6261636b4761734c696d6974000000000000000000000000000000006044820152606401610c9a565b6016546040516305d3b1d360e41b81526004810185905267ffffffffffffffff861660248201526003604482015263ffffffff84166064820152600160848201526001600160a01b03909116908190635d3b1d309060a401602060405180830381600087803b158015612e1e57600080fd5b505af1158015612e32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5691906148c0565b60198190556040519081527f386f7e0e864241c7e92166f1441c88d40259979d0d6fe045ae15c5e0011c7a7290602001611405565b5490565b80546001019055565b6001600160a01b03163b151590565b6000610b8d82613cba565b600081815260096020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612ee782611693565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b81612f6e57604051630fc3a38f60e41b815260206004820152600960248201527f72657175657374496400000000000000000000000000000000000000000000006044820152606401610c9a565b6017548214156130075760185415612f995760405163ba4ace8d60e01b815260040160405180910390fd5b80600081518110612fba57634e487b7160e01b600052603260045260246000fd5b60200260200101516018819055507f260b0d780ce5d3acea4dbce31d432406bb72fea1d4b7e2571b4558445a45c8d6601854604051612ffb91815260200190565b60405180910390a15050565b601954821415610f2e57601a54156130325760405163ba4ace8d60e01b815260040160405180910390fd5b8060008151811061305357634e487b7160e01b600052603260045260246000fd5b6020026020010151601a819055507f1acc627535151d4af646035fc4bc45bb7f1f35139d354287404bd6a074bfaf69601a54604051612ffb91815260200190565b6000818152600760205260408120546001600160a01b031661310d5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610c9a565b600061311883611693565b9050806001600160a01b0316846001600160a01b0316148061315f57506001600160a01b038082166000908152600a602090815260408083209388168352929052205460ff165b806131835750836001600160a01b031661317884610c25565b6001600160a01b0316145b949350505050565b826001600160a01b031661319e82611693565b6001600160a01b03161461321a5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610c9a565b6001600160a01b0382166132955760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610c9a565b6132a0838383613d2c565b6132ab600082612eb2565b6001600160a01b03831660009081526008602052604081208054600192906132d4908490614cf6565b90915550506001600160a01b0382166000908152600860205260408120805460019290613302908490614cab565b909155505060008181526007602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60036000613372600183614cf6565b600681111561339157634e487b7160e01b600052602160045260246000fd5b90508160068111156133b357634e487b7160e01b600052602160045260246000fd5b6133bb6126cb565b60068111156133da57634e487b7160e01b600052602160045260246000fd5b106133e757610ff06126cb565b600f54841461343957604051636b6afd1760e11b815260206004820152600a60248201527f616d6f756e7450616964000000000000000000000000000000000000000000006044820152606401610c9a565b6000613444600c5490565b90506134508686613ed8565b61345e600c80546001019055565b83600181111561347e57634e487b7160e01b600052602160045260246000fd5b6134bb576001600160a01b0386166000908152600b6020526040812060019081018054919290916134b0908490614cab565b909155506134ea9050565b6001600160a01b0386166000908152600b602052604081208054600192906134e4908490614cab565b90915550505b6134f48682613fc3565b505050505050565b6127106bffffffffffffffffffffffff821611156135825760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c2065786365656460448201527f2073616c655072696365000000000000000000000000000000000000000000006064820152608401610c9a565b6001600160a01b0382166135d85760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610c9a565b604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff9091166020909201829052600160a01b90910217600355565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b816001600160a01b0316836001600160a01b031614156136c85760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c9a565b6001600160a01b038381166000818152600a6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b60608361378557604051630fc3a38f60e41b815260206004820152600a60248201527f72616e646f6d576f7264000000000000000000000000000000000000000000006044820152606401610c9a565b61ffff6000613795601086614cc3565b905060006137a4601087614daa565b11156137b8576137b5600182614cab565b90505b60006137c48286614cd7565b6137cf906010614cd7565b905060006137de836010614cd7565b67ffffffffffffffff81111561380457634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561382d578160200160208202803683370190505b50905060005b8381101561392b576000896138488584614cab565b6040805160208101939093528201526060016040516020818303038152906040528051906020012060001c905060005b6010811015613916576138ad7f0000000000000000000000000000000000000000000000000000000000001388838916614d89565b84826138ba866010614cd7565b6138c49190614cab565b815181106138e257634e487b7160e01b600052603260045260246000fd5b61ffff909216602092830291909101909101526139026201000083614cc3565b91508061390e81614d6e565b915050613878565b5050808061392390614d6e565b915050613833565b5093505050505b9392505050565b61394484848461318b565b61395084848484613fdd565b6126c55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610c9a565b6002546001600160a01b03166139e05760405163a75e096760e01b815260040160405180910390fd5b826001600160a01b031681600001516001600160a01b031614613a455780516040517ff1a669ce0000000000000000000000000000000000000000000000000000000081526001600160a01b0380861660048301529091166024820152604401610c9a565b81816020015161ffff1611613a7057604051631ebf81cf60e21b815260048101839052602401610c9a565b6000613a7b82614135565b6002549091506001600160a01b038083169116146126c5576002546040517f6cd82d240000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529091166024820152604401610c9a565b606081613b1c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115613b465780613b3081614d6e565b9150613b3f9050600a83614cc3565b9150613b20565b60008167ffffffffffffffff811115613b6f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613b99576020820181803683370190505b5090505b841561318357613bae600183614cf6565b9150613bbb600a86614daa565b613bc6906030614cab565b60f81b818381518110613be957634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613c23600a86614cc3565b9450613b9d565b6001600160a01b038116613c515760405163a75e096760e01b815260040160405180910390fd5b600254604080516001600160a01b03928316815291831660208301527f9fed3c0e42aa7f73947a13ac6757a3d73c8f820c1c1d45bfdb2a3f9d3f812a07910160405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160e01b031982167f80ac58cd000000000000000000000000000000000000000000000000000000001480613d1d57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610b8d5750610b8d82614211565b6015546001600160a01b031615610dec57601554604080517f2c77ddfd00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691632c77ddfd916004808301926020929190829003018186803b158015613d9b57600080fd5b505afa158015613daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dd391906148c0565b90508042108015613e7557506015546040517f927e603d0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301529091169063927e603d9060240160206040518083038186803b158015613e3d57600080fd5b505afa158015613e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e75919061473a565b8015613e895750613e8584611b09565b6001145b156126c5576040517f65e7520f0000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015242602482015260448101829052606401610c9a565b6014546040516000916001600160a01b03169083908381818185875af1925050503d8060008114613f25576040519150601f19603f3d011682016040523d82523d6000602084013e613f2a565b606091505b5050905080613f7b5760405162461bcd60e51b815260206004820152601660248201527f436f756c64206e6f7420706179207472656173757279000000000000000000006044820152606401610c9a565b826001600160a01b03167fb5668d929317b36d7b61952ab446b7e4dd82c4d9f90788b407c35e90440f567883604051613fb691815260200190565b60405180910390a2505050565b610f2e82826040518060200160405280600081525061425f565b60006001600160a01b0384163b1561412a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614021903390899088908890600401614b24565b602060405180830381600087803b15801561403b57600080fd5b505af192505050801561406b575060408051601f3d908101601f1916820190925261406891810190614772565b60015b614110573d808015614099576040519150601f19603f3d011682016040523d82523d6000602084013e61409e565b606091505b5080516141085760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610c9a565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613183565b506001949350505050565b600080600154614144846142dd565b6040517f1901000000000000000000000000000000000000000000000000000000000000602082015260228101929092526042820152606201604051602081830303815290604052805190602001209050600181846040015185606001518660800151604051600081526020016040526040516141dd949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156141ff573d6000803e3d6000fd5b5050604051601f190151949350505050565b60006001600160e01b031982167f2a55205a000000000000000000000000000000000000000000000000000000001480610b8d57506301ffc9a760e01b6001600160e01b0319831614610b8d565b6142698383614354565b6142766000848484613fdd565b610dec5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610c9a565b8051602080830151604051600093614337937f9016184a70237a58286b5c611a44cf3c4b67b9ec2da552661f6a04c1395282d5939192019283526001600160a01b0391909116602083015261ffff16604082015260600190565b604051602081830303815290604052805190602001209050919050565b6001600160a01b0382166143aa5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c9a565b6000818152600760205260409020546001600160a01b03161561440f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c9a565b61441b60008383613d2c565b6001600160a01b0382166000908152600860205260408120805460019290614444908490614cab565b909155505060008181526007602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b8280546144ae90614d39565b90600052602060002090601f0160209004810192826144d05760008555614516565b82601f106144e957805160ff1916838001178555614516565b82800160010185558215614516579182015b828111156145165782518255916020019190600101906144fb565b506121269291505b80821115612126576000815560010161451e565b600067ffffffffffffffff83111561454c5761454c614dea565b61455f601f8401601f1916602001614c7a565b905082815283838301111561457357600080fd5b828260208301376000602084830101529392505050565b803561ffff8116811461459c57600080fd5b919050565b6000602082840312156145b2578081fd5b813561393281614e00565b600080604083850312156145cf578081fd5b82356145da81614e00565b915060208301356145ea81614e00565b809150509250929050565b600080600060608486031215614609578081fd5b833561461481614e00565b9250602084013561462481614e00565b929592945050506040919091013590565b6000806000806080858703121561464a578182fd5b843561465581614e00565b9350602085013561466581614e00565b925060408501359150606085013567ffffffffffffffff811115614687578182fd5b8501601f81018713614697578182fd5b6146a687823560208401614532565b91505092959194509250565b600080604083850312156146c4578182fd5b82356146cf81614e00565b915060208301356145ea81614e15565b600080604083850312156146f1578182fd5b82356146fc81614e00565b91506020830135600281106145ea578182fd5b60008060408385031215614721578182fd5b823561472c81614e00565b946020939093013593505050565b60006020828403121561474b578081fd5b815161393281614e15565b600060208284031215614767578081fd5b813561393281614e23565b600060208284031215614783578081fd5b815161393281614e23565b60006020828403121561479f578081fd5b815160068110613932578182fd5b6000602082840312156147be578081fd5b813567ffffffffffffffff8111156147d4578182fd5b8201601f810184136147e4578182fd5b61318384823560208401614532565b600060a082840312156114d0578081fd5b600060a08284031215614815578081fd5b60405160a0810181811067ffffffffffffffff8211171561483857614838614dea565b604052823561484681614e00565b81526148546020840161458a565b6020820152604083013560ff8116811461486c578283fd5b6040820152606083810135908201526080928301359281019290925250919050565b60006020828403121561489f578081fd5b6139328261458a565b6000602082840312156148b9578081fd5b5035919050565b6000602082840312156148d1578081fd5b5051919050565b600080604083850312156148ea578182fd5b8235915060208084013567ffffffffffffffff80821115614909578384fd5b818601915086601f83011261491c578384fd5b81358181111561492e5761492e614dea565b8060051b915061493f848301614c7a565b8181528481019084860184860187018b1015614959578788fd5b8795505b8386101561497b57803583526001959095019491860191860161495d565b508096505050505050509250929050565b6000806040838503121561499e578182fd5b50508035926020909101359150565b6000806000606084860312156149c1578081fd5b833567ffffffffffffffff811681146149d8578182fd5b925060208401359150604084013563ffffffff811681146149f7578182fd5b809150509250925092565b600060208284031215614a13578081fd5b81356bffffffffffffffffffffffff81168114613932578182fd5b60008151808452614a46816020860160208601614d0d565b601f01601f19169290920160200192915050565b60078110614a7857634e487b7160e01b600052602160045260246000fd5b9052565b6000808454614a8a81614d39565b60018281168015614aa25760018114614ab357614adf565b60ff19841687528287019450614adf565b8886526020808720875b85811015614ad65781548a820152908401908201614abd565b50505082870194505b505050508351614af3818360208801614d0d565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000009101908152600501949350505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152614b566080830184614a2e565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614b9c57835161ffff1683529284019291840191600101614b7c565b50909695505050505050565b60208101610b8d8284614a5a565b60408101614bc48285614a5a565b6139326020830184614a5a565b6020815260006139326020830184614a2e565b604081526000808454614bf681614d39565b8060408601526060600180841660008114614c185760018114614c2c57614c5a565b60ff19851688840152608088019550614c5a565b8987526020808820885b86811015614c515781548b8201870152908401908201614c36565b8a018501975050505b50505050508281036020840152614c718185614a2e565b95945050505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715614ca357614ca3614dea565b604052919050565b60008219821115614cbe57614cbe614dbe565b500190565b600082614cd257614cd2614dd4565b500490565b6000816000190483118215151615614cf157614cf1614dbe565b500290565b600082821015614d0857614d08614dbe565b500390565b60005b83811015614d28578181015183820152602001614d10565b838111156126c55750506000910152565b600181811c90821680614d4d57607f821691505b602082108114156114d057634e487b7160e01b600052602260045260246000fd5b6000600019821415614d8257614d82614dbe565b5060010190565b600061ffff80841680614d9e57614d9e614dd4565b92169190910692915050565b600082614db957614db9614dd4565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461107d57600080fd5b801515811461107d57600080fd5b6001600160e01b03198116811461107d57600080fdfe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220b3144f75f071b381966b4b44338ff0d329f69549cf83d122078d79f583a3dadc64736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000455ad5835b5f732a8c28d0ad79abf7942f586906000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000004e200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000632c403000000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000214e8348c4f0000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000005168747470733a2f2f73332e65752d776573742d322e616d617a6f6e6177732e636f6d2f6d617261646f6e616f6666696369616c2e696f2f61636365737350617373436f6e74726163745552492e6a736f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036697066733a2f2f516d5a346e696a4e546b5933556a3766327a71766d6b5a57386873344e6e42345878514d35474c7277554a4d52522f00000000000000000000
-----Decoded View---------------
Arg [0] : treasury_ (address): 0x455AD5835B5f732A8C28d0ad79abF7942f586906
Arg [1] : vrfCoordinator_ (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [2] : maxTotalSupply_ (uint16): 5000
Arg [3] : goldenTierSupply_ (uint16): 750
Arg [4] : silverTierSupply_ (uint16): 1250
Arg [5] : ticketSupply_ (uint16): 500
Arg [6] : privateMintingTimestamp_ (uint256): 1663844400
Arg [7] : royaltyFee (uint96): 850
Arg [8] : price_ (uint256): 150000000000000000
Arg [9] : contractURI_ (string): https://s3.eu-west-2.amazonaws.com/maradonaofficial.io/accessPassContractURI.json
Arg [10] : unrevealedURI_ (string): ipfs://QmZ4nijNTkY3Uj7f2zqvmkZW8hs4NnB4XxQM5GLrwUJMRR/
-----Encoded View---------------
18 Constructor Arguments found :
Arg [0] : 000000000000000000000000455ad5835b5f732a8c28d0ad79abf7942f586906
Arg [1] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [2] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [3] : 00000000000000000000000000000000000000000000000000000000000002ee
Arg [4] : 00000000000000000000000000000000000000000000000000000000000004e2
Arg [5] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [6] : 00000000000000000000000000000000000000000000000000000000632c4030
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000352
Arg [8] : 0000000000000000000000000000000000000000000000000214e8348c4f0000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [10] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000051
Arg [12] : 68747470733a2f2f73332e65752d776573742d322e616d617a6f6e6177732e63
Arg [13] : 6f6d2f6d617261646f6e616f6666696369616c2e696f2f616363657373506173
Arg [14] : 73436f6e74726163745552492e6a736f6e000000000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000036
Arg [16] : 697066733a2f2f516d5a346e696a4e546b5933556a3766327a71766d6b5a5738
Arg [17] : 6873344e6e42345878514d35474c7277554a4d52522f00000000000000000000
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.