Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x61020060 | 16585034 | 612 days ago | IN | 0 ETH | 0.24614206 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
KitsERC721Drop
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** ██╗ ██╗██╗████████╗███████╗ ██║ ██╔╝██║╚══██╔══╝██╔════╝ █████╔╝ ██║ ██║ ███████╗ ██╔═██╗ ██║ ██║ ╚════██║ ██║ ██╗██║ ██║ ███████║ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ Forked from Zora Drop by [email protected] */ import {ERC721AUpgradeable} from "erc721a-upgradeable/contracts/ERC721AUpgradeable.sol"; import {IERC721AUpgradeable} from "erc721a-upgradeable/contracts/IERC721AUpgradeable.sol"; import {IERC2981Upgradeable, IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol"; import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import {MerkleProofUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {IKitsFeeManager} from "../interfaces/IKitsFeeManager.sol"; import {IMetadataRenderer} from "../interfaces/IMetadataRenderer.sol"; import {IOperatorFilterRegistry} from "../interfaces/IOperatorFilterRegistry.sol"; import {IKitsERC721Drop} from "../interfaces/IKitsERC721Drop.sol"; import {IOwnable} from "../interfaces/IOwnable.sol"; import {IFactoryUpgradeGate} from "../interfaces/IFactoryUpgradeGate.sol"; import {OwnableSkeleton} from "./utils/OwnableSkeleton.sol"; import {FundsReceiver} from "./utils/FundsReceiver.sol"; import {Version} from "./utils/Version.sol"; import {ERC721DropStorageV1} from "./storage/ERC721DropStorageV1.sol"; /** * @notice Kits NFT Base contract for Drops and Editions. Forked from Zora's ERC721Drop contract by [email protected]. * * Ownership of tokens in this contract entitles the owner to commercial use rights of sounds as specified in the * following Terms: * ar://Pxi9M882YT8P68p6e2Lzl_McvgbdzfO5brVRgZlLaEc. * * Terms are also available at: * https://h4ml2m6pgzqt6d7lzj5hwyxts7zrzpqg3xg7holowviydgklnbdq.arweave.net/Pxi9M882YT8P68p6e2Lzl_McvgbdzfO5brVRgZlLaEc * * @author [email protected], [email protected] * */ contract KitsERC721Drop is ERC721AUpgradeable, UUPSUpgradeable, IERC2981Upgradeable, ReentrancyGuardUpgradeable, AccessControlUpgradeable, IKitsERC721Drop, OwnableSkeleton, FundsReceiver, Version(9001), ERC721DropStorageV1 { /// @dev This is the max mint batch size for the optimized ERC721A mint contract uint256 internal immutable MAX_MINT_BATCH_SIZE = 8; /// @dev This is the magic number that means this is an open edition. formerly type(uint64).max uint64 internal immutable OPEN_EDITION_VOLUME_MAGIC_NUMBER = 99999999; /// @dev Gas limit to send funds uint256 internal immutable FUNDS_SEND_GAS_LIMIT = 210_000; /// @notice Access control roles bytes32 public immutable MINTER_ROLE = keccak256("MINTER"); bytes32 public immutable SALES_MANAGER_ROLE = keccak256("SALES_MANAGER"); /// @dev KITS V3 transfer helper address for auto-approval address internal immutable kitsERC721TransferHelper; /// @dev Factory upgrade gate IFactoryUpgradeGate internal immutable factoryUpgradeGate; /// @dev Kits Fee Manager address IKitsFeeManager public immutable kitsFeeManager; /// @notice Max royalty BPS uint16 constant MAX_ROYALTY_BPS = 50_00; address immutable marketFilterDAOAddress; IOperatorFilterRegistry immutable operatorFilterRegistry = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); /// @notice Only allow for users with admin access modifier onlyAdmin() { if (!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { revert Access_OnlyAdmin(); } _; } /// @notice Only a given role has access or admin /// @param role role to check for alongside the admin role modifier onlyRoleOrAdmin(bytes32 role) { if ( !hasRole(DEFAULT_ADMIN_ROLE, _msgSender()) && !hasRole(role, _msgSender()) ) { revert Access_MissingRoleOrAdmin(role); } _; } /// @notice Allows user to mint tokens at a quantity modifier canMintPublicSaleTokens(uint256 quantity) { if (quantity + (_totalMinted()) > config.totalEditionSize) { revert Mint_SoldOut(); } _; } /// @notice Allows user to mint presale tokens at a quantity modifier canMintPresaleTokens(uint256 quantity) { if (quantity + presaleMints > config.presaleEditionSize) { revert Mint_Presale_SoldOut(); } _; } modifier senderHoldsAllowlistToken() { uint balance = IERC721AUpgradeable(salesConfig.allowlistContractAddress) .balanceOf(_msgSender()); if (balance < 1) { revert Presale_UserNotAllowlist(); } _; } function _presaleActive() internal view returns (bool) { return salesConfig.presaleStart <= block.timestamp && salesConfig.presaleEnd > block.timestamp; } function _publicSaleActive() internal view returns (bool) { return salesConfig.publicSaleStart <= block.timestamp && salesConfig.publicSaleEnd > block.timestamp; } /// @notice Presale active modifier onlyPresaleActive() { if (!_presaleActive()) { revert Presale_Inactive(); } _; } /// @notice Public sale active modifier onlyPublicSaleActive() { if (!_publicSaleActive()) { revert Sale_Inactive(); } _; } /// @notice Getter for last minted token ID (gets next token id and subtracts 1) function _lastMintedTokenId() internal view returns (uint256) { return _currentIndex - 1; } /// @notice Start token ID for minting (1-100 vs 0-99) function _startTokenId() internal pure override returns (uint256) { return 1; } /// @notice Global constructor – these variables will not change with further proxy deploys /// @dev Marked as an initializer to prevent storage being used of base implementation. Can only be init'd by a proxy. /// @param _kitsFeeManager Kits Fee Manager /// @param _kitsERC721TransferHelper Transfer helper constructor( IKitsFeeManager _kitsFeeManager, address _kitsERC721TransferHelper, IFactoryUpgradeGate _factoryUpgradeGate, address _marketFilterDAOAddress ) initializer { kitsFeeManager = _kitsFeeManager; kitsERC721TransferHelper = _kitsERC721TransferHelper; factoryUpgradeGate = _factoryUpgradeGate; marketFilterDAOAddress = _marketFilterDAOAddress; } /// @dev Create a new drop contract /// @param _contractName Contract name /// @param _contractSymbol Contract symbol /// @param _initialOwner User that owns and can mint the edition, gets royalty and sales payouts and can update the base url if needed. /// @param _fundsRecipient Wallet/user that receives funds from sale /// @param _totalEditionSize Number of editions that can be minted during public and presale. If OPEN_EDITION_VOLUME_MAGIC_NUMBER, unlimited editions can be minted as an open edition. /// @param _presaleEditionSize Number of editions that can be minted during presale. If OPEN_EDITION_VOLUME_MAGIC_NUMBER, unlimited editions can be minted during presale. /// @param _royaltyBPS BPS of the royalty set on the contract. Can be 0 for no royalty. /// @param _salesConfig New sales config to set upon init /// @param _metadataRenderer Renderer contract to use /// @param _baseURI HTTP URI, up to but not including, the contract address. eg: https://arpeggi.io/api/v2/kits-metadata function initialize( string memory _contractName, string memory _contractSymbol, address _initialOwner, address payable _fundsRecipient, uint64 _totalEditionSize, uint64 _presaleEditionSize, uint16 _royaltyBPS, SalesConfiguration memory _salesConfig, IMetadataRenderer _metadataRenderer, string memory _baseURI ) public initializer { // Setup ERC721A __ERC721A_init(_contractName, _contractSymbol); // Setup access control __AccessControl_init(); // Setup re-entracy guard __ReentrancyGuard_init(); // Setup the owner role _setupRole(DEFAULT_ADMIN_ROLE, _initialOwner); // Set ownership to original sender of contract call _setOwner(_initialOwner); if (config.royaltyBPS > MAX_ROYALTY_BPS) { revert Setup_RoyaltyPercentageTooHigh(MAX_ROYALTY_BPS); } // Update salesConfig salesConfig = _salesConfig; // Setup config variables config.totalEditionSize = _totalEditionSize; config.presaleEditionSize = _presaleEditionSize; config.metadataRenderer = _metadataRenderer; config.royaltyBPS = _royaltyBPS; config.fundsRecipient = _fundsRecipient; baseURI = _baseURI; } /// @dev Getter for admin role associated with the contract to handle metadata /// @return boolean if address is admin function isAdmin(address user) external view returns (bool) { return hasRole(DEFAULT_ADMIN_ROLE, user); } /// @dev Update the baseURI used by tokenURI function setBaseUri(string calldata baseUri_) public onlyAdmin { baseURI = baseUri_; emit UpdateBaseUri(msg.sender, baseUri_); } /// @notice Connects this contract to the factory upgrade gate /// @param newImplementation proposed new upgrade implementation /// @dev Only can be called by admin function _authorizeUpgrade( address newImplementation ) internal override onlyAdmin { if ( !factoryUpgradeGate.isValidUpgradePath({ _newImpl: newImplementation, _currentImpl: _getImplementation() }) ) { revert Admin_InvalidUpgradeAddress(newImplementation); } } function getRarityTierId(uint256 tokenId) internal returns (uint256) { // iterate over the tiers to see if we have any open AvailableTiers[NUMBER_OF_RARITY_CONFIGS] memory tiersWithAvailability; uint256 numTiersWithAvailability = 0; for (uint i = 0; i < NUMBER_OF_RARITY_CONFIGS; i++) { uint tierMintsRemaining = rarityConfigs[i].tierVolume - rarityConfigs[i].volumeMinted; if (tierMintsRemaining > 0) { tiersWithAvailability[numTiersWithAvailability].rarityId = i; tiersWithAvailability[numTiersWithAvailability] .tierMintsRemaining = tierMintsRemaining; numTiersWithAvailability++; } } uint256 totalMintsRemaining = config.totalEditionSize - _totalMinted() + 1; uint256 random = uint256( keccak256(abi.encode(currentRandom, tokenId, block.timestamp)) ); uint256 roll = random % TARGET_RARITY_MOD; uint currentLowerBound = 0; for (uint i = 0; i < numTiersWithAvailability; i++) { // get percentage chance of minting at this tier uint chanceOutOfTargetMod = ((tiersWithAvailability[i] .tierMintsRemaining * TARGET_RARITY_MOD) / (totalMintsRemaining)); if ( roll >= currentLowerBound && roll < (currentLowerBound + chanceOutOfTargetMod) ) { return tiersWithAvailability[i].rarityId; } currentLowerBound += chanceOutOfTargetMod; } } // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | burn() | // | ------------------> // | | // | |----. // | | | burn token // | |<---' // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @param tokenId Token ID to burn /// @notice User burn function for token id function burn(uint256 tokenId) public { _burn(tokenId, true); } /// @dev Get royalty information for token /// @param _salePrice Sale price for the token function royaltyInfo( uint256, uint256 _salePrice ) external view override returns (address receiver, uint256 royaltyAmount) { if (config.fundsRecipient == address(0)) { return (config.fundsRecipient, 0); } return ( config.fundsRecipient, (_salePrice * config.royaltyBPS) / 10_000 ); } /// @notice Sale details /// @return IKitsERC721Drop.SaleDetails sale information details function saleDetails() external view returns (IKitsERC721Drop.SaleDetails memory) { return IKitsERC721Drop.SaleDetails({ publicSaleActive: _publicSaleActive(), presaleActive: _presaleActive(), publicSalePrice: salesConfig.publicSalePrice, publicSaleStart: salesConfig.publicSaleStart, publicSaleEnd: salesConfig.publicSaleEnd, presaleStart: salesConfig.presaleStart, presaleEnd: salesConfig.presaleEnd, presaleMerkleRoot: salesConfig.presaleMerkleRoot, totalMinted: _totalMinted(), totalPreSaleMinted: presaleMints, maxSupply: config.totalEditionSize, maxSalePurchasePerAddress: salesConfig.maxSalePurchasePerAddress }); } /// @dev Number of NFTs the user has minted per address /// @param minter to get counts for function mintedPerAddress( address minter ) external view override returns (IKitsERC721Drop.AddressMintDetails memory) { return IKitsERC721Drop.AddressMintDetails({ presaleMints: presaleMintsByAddress[minter], publicMints: _numberMinted(minter) - presaleMintsByAddress[minter], totalMints: _numberMinted(minter) }); } /// @dev Setup auto-approval for Kits v3 access to sell NFT /// Still requires approval for module /// @param nftOwner owner of the nft /// @param operator operator wishing to transfer/burn/etc the NFTs function isApprovedForAll( address nftOwner, address operator ) public view override(ERC721AUpgradeable) returns (bool) { if (operator == kitsERC721TransferHelper) { return true; } return super.isApprovedForAll(nftOwner, operator); } /** *** ---------------------------------- *** *** *** *** PUBLIC MINTING FUNCTIONS *** *** *** *** ---------------------------------- *** ***/ // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | purchase() | // | ----------------------------> // | | // | | // ___________________________________________________________ // ! ALT / drop has no tokens left for caller to mint? ! // !_____/ | | ! // ! | revert Mint_SoldOut() | ! // ! | <---------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // ___________________________________________________________ // ! ALT / public sale isn't active? | ! // !_____/ | | ! // ! | revert Sale_Inactive() | ! // ! | <---------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // ___________________________________________________________ // ! ALT / inadequate funds sent? | ! // !_____/ | | ! // ! | revert Purchase_WrongPrice()| ! // ! | <---------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | mint tokens // | |<---' // | | // | |----. // | | | emit IKitsERC721Drop.Sale() // | |<---' // | | // | return first minted token ID| // | <---------------------------- // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /** @dev This allows the user to purchase a edition edition at the given price in the contract. */ function purchase( uint256 quantity ) external payable nonReentrant canMintPublicSaleTokens(quantity) onlyPublicSaleActive returns (uint256) { uint256 salePrice = salesConfig.publicSalePrice; if (msg.value != salePrice * quantity) { revert Purchase_WrongPrice(salePrice * quantity); } // If max purchase per address == 0 there is no limit. // Any other number, the per address mint limit is that. if ( salesConfig.maxSalePurchasePerAddress != 0 && _numberMinted(_msgSender()) + quantity - presaleMintsByAddress[_msgSender()] > salesConfig.maxSalePurchasePerAddress ) { revert Purchase_TooManyForAddress(); } _mintNFTs(_msgSender(), quantity); uint256 firstMintedTokenId = _lastMintedTokenId() - quantity; postMintRarityUpdate(firstMintedTokenId, _lastMintedTokenId()); emit IKitsERC721Drop.Sale({ to: _msgSender(), quantity: quantity, pricePerToken: salePrice, firstPurchasedTokenId: firstMintedTokenId }); return firstMintedTokenId; } /// @notice Function to mint NFTs /// @dev (important: Does not enforce max supply limit, enforce that limit earlier) /// @dev This batches in size of 8 as per recommended by ERC721A creators /// @param to address to mint NFTs to /// @param quantity number of NFTs to mint function _mintNFTs(address to, uint256 quantity) internal { do { uint256 toMint = quantity > MAX_MINT_BATCH_SIZE ? MAX_MINT_BATCH_SIZE : quantity; _mint({to: to, quantity: toMint}); quantity -= toMint; } while (quantity > 0); } function setRandom(uint256 newRandom) external onlyAdmin { currentRandom = newRandom; } function postMintRarityUpdate( uint256 firstMintedTokenId, uint256 lastMintedTokenId ) internal { for ( uint i = firstMintedTokenId + 1; i < _lastMintedTokenId() + 1; i++ ) { uint256 rarityTierId = getRarityTierId(i); rarityConfigs[rarityTierId].volumeMinted++; rarityMapping[i] = rarityTierId; } } /** * Get the presale edition size only if the presale is active * If the presale has expired, then return 0. * * This is used to determine rarity on token mint. */ function getContextualPresaleEditionSize() internal view returns (uint256) { if (_presaleActive()) { return config.presaleEditionSize; } // if the presale is not active, set the presale volume to 0 for calulating rarity return 0; } // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | purchasePresale() | // | ----------------------------------> // | | // | | // _________________________________________________________________ // ! ALT / drop has no tokens left for caller to mint? ! // !_____/ | | ! // ! | revert Mint_SoldOut() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / presale sale isn't active? | ! // !_____/ | | ! // ! | revert Presale_Inactive() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / merkle proof unapproved for caller? | ! // !_____/ | | ! // ! | revert Presale_MerkleNotApproved()| ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / inadequate funds sent? | ! // !_____/ | | ! // ! | revert Purchase_WrongPrice() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | mint tokens // | |<---' // | | // | |----. // | | | emit IKitsERC721Drop.Sale() // | |<---' // | | // | return first minted token ID | // | <---------------------------------- // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @notice Merkle-tree based presale purchase function /// @param quantity quantity to purchase /// @param maxQuantity max quantity that can be purchased via merkle proof # /// @param pricePerToken price that each token is purchased at /// @param merkleProof proof for presale mint function purchasePresale( uint256 quantity, uint256 maxQuantity, uint256 pricePerToken, bytes32[] calldata merkleProof ) external payable nonReentrant canMintPresaleTokens(quantity) onlyPresaleActive returns (uint256) { if ( !MerkleProofUpgradeable.verify( merkleProof, salesConfig.presaleMerkleRoot, keccak256( // address, uint256, uint256 abi.encode(_msgSender(), maxQuantity, pricePerToken) ) ) ) { revert Presale_MerkleNotApproved(); } if (msg.value != pricePerToken * quantity) { revert Purchase_WrongPrice(pricePerToken * quantity); } presaleMintsByAddress[_msgSender()] += quantity; if (presaleMintsByAddress[_msgSender()] > maxQuantity) { revert Presale_TooManyForAddress(); } // canMintPresaleTokens modifier checks that we can // mint `quantity` and remain under `config.presaleEditionSize` unchecked { presaleMints += quantity; } _mintNFTs(_msgSender(), quantity); uint256 firstMintedTokenId = _lastMintedTokenId() - quantity; postMintRarityUpdate(firstMintedTokenId, _lastMintedTokenId()); emit IKitsERC721Drop.Sale({ to: _msgSender(), quantity: quantity, pricePerToken: pricePerToken, firstPurchasedTokenId: firstMintedTokenId }); return firstMintedTokenId; } // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | purchaseAllowlist() | // | ----------------------------------> // | | // | | // _________________________________________________________________ // ! ALT / drop has no tokens left for caller to mint? ! // !_____/ | | ! // ! | revert Mint_SoldOut() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / presale sale isn't active? | ! // !_____/ | | ! // ! | revert Presale_Inactive() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / caller does not own allowlist token? | ! // !_____/ | | ! // ! | revert Presale_UserNotAllowlist() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / inadequate funds sent? | ! // !_____/ | | ! // ! | revert Purchase_WrongPrice() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | mint tokens // | |<---' // | | // | |----. // | | | emit IKitsERC721Drop.Sale() // | |<---' // | | // | return first minted token ID | // | <---------------------------------- // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @notice External contract token holder-based presale purchase function /// @param quantity quantity to purchase function purchaseAllowlist( uint256 quantity ) external payable nonReentrant canMintPresaleTokens(quantity) onlyPresaleActive senderHoldsAllowlistToken returns (uint256) { uint256 salePrice = salesConfig.allowlistSalePrice; if (msg.value != salePrice * quantity) { revert Purchase_WrongPrice(salePrice); } // If max purchase per address == 0 there is no limit. // Any other number, the per address mint limit is that. if ( salesConfig.maxSalePurchasePerAddress != 0 && _numberMinted(_msgSender()) + quantity - presaleMintsByAddress[_msgSender()] > salesConfig.maxSalePurchasePerAddress ) { revert Purchase_TooManyForAddress(); } // canMintPresaleTokens modifier checks that we can // mint `quantity` and remain under `config.presaleEditionSize` unchecked { presaleMints += quantity; } _mintNFTs(_msgSender(), quantity); uint256 firstMintedTokenId = _lastMintedTokenId() - quantity; postMintRarityUpdate(firstMintedTokenId, _lastMintedTokenId()); emit IKitsERC721Drop.Sale({ to: _msgSender(), quantity: quantity, pricePerToken: salePrice, firstPurchasedTokenId: firstMintedTokenId }); return firstMintedTokenId; } /** *** ---------------------------------- *** *** *** *** ADMIN OPERATOR FILTERING *** *** *** *** ---------------------------------- *** ***/ /// @notice Proxy to update market filter settings in the main registry contracts /// @notice Requires admin permissions /// @param args Calldata args to pass to the registry function updateMarketFilterSettings( bytes calldata args ) external onlyAdmin returns (bytes memory) { (bool success, bytes memory ret) = address(operatorFilterRegistry).call( args ); if (!success) { revert RemoteOperatorFilterRegistryCallFailed(); } return ret; } /// @notice Manage subscription to the DAO for marketplace filtering based off royalty payouts. /// @param enable Enable filtering to non-royalty payout marketplaces function manageMarketFilterDAOSubscription(bool enable) external onlyAdmin { address self = address(this); if (marketFilterDAOAddress == address(0x0)) { revert MarketFilterDAOAddressNotSupportedForChain(); } if (!operatorFilterRegistry.isRegistered(self) && enable) { operatorFilterRegistry.registerAndSubscribe( self, marketFilterDAOAddress ); } else if (enable) { operatorFilterRegistry.subscribe(self, marketFilterDAOAddress); } else { operatorFilterRegistry.unsubscribe(self, false); operatorFilterRegistry.unregister(self); } } /// @notice Configure rarities for this edition /// @param _rarityConfigs to set for the edition function updateRarities( IKitsERC721Drop.RarityConfiguration[NUMBER_OF_RARITY_CONFIGS] memory _rarityConfigs ) external onlyAdmin { for (uint i = 0; i < _rarityConfigs.length; i++) { rarityConfigs[i] = _rarityConfigs[i]; } emit UpdatedRarities(msg.sender, _rarityConfigs); } /// @notice Hook to filter operators (no-op if no filters are registered) /// @dev Part of ERC721A token hooks /// @param from Transfer from user /// @param to Transfer to user /// @param startTokenId Token ID to start with /// @param quantity Quantity of token being transferred function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual override { if ( from != msg.sender && address(operatorFilterRegistry).code.length > 0 ) { if ( !operatorFilterRegistry.isOperatorAllowed( address(this), msg.sender ) ) { revert OperatorNotAllowed(msg.sender); } } } /** *** ---------------------------------- *** *** *** *** ADMIN MINTING FUNCTIONS *** *** *** *** ---------------------------------- *** ***/ // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | adminMint() | // | ----------------------------------> // | | // | | // _________________________________________________________________ // ! ALT / caller is not admin or minter role? | ! // !_____/ | | ! // ! | revert Access_MissingRoleOrAdmin()| ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / drop has no tokens left for caller to mint? ! // !_____/ | | ! // ! | revert Mint_SoldOut() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | mint tokens // | |<---' // | | // | return last minted token ID | // | <---------------------------------- // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @notice Mint admin /// @param recipient recipient to mint to /// @param quantity quantity to mint function adminMint( address recipient, uint256 quantity ) external onlyRoleOrAdmin(MINTER_ROLE) canMintPublicSaleTokens(quantity) returns (uint256) { _mintNFTs(recipient, quantity); return _lastMintedTokenId(); } // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | adminMintAirdrop() | // | ----------------------------------> // | | // | | // _________________________________________________________________ // ! ALT / caller is not admin or minter role? | ! // !_____/ | | ! // ! | revert Access_MissingRoleOrAdmin()| ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // _________________________________________________________________ // ! ALT / drop has no tokens left for recipients to mint? ! // !_____/ | | ! // ! | revert Mint_SoldOut() | ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | | // | _____________________________________ // | ! LOOP / for all recipients ! // | !______/ | ! // | ! |----. ! // | ! | | mint tokens ! // | ! |<---' ! // | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | return last minted token ID | // | <---------------------------------- // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @dev This mints multiple editions to the given list of addresses. /// @param recipients list of addresses to send the newly minted editions to function adminMintAirdrop( address[] calldata recipients ) external override onlyRoleOrAdmin(MINTER_ROLE) canMintPublicSaleTokens(recipients.length) returns (uint256) { uint256 atId = _currentIndex; uint256 startAt = atId; unchecked { for ( uint256 endAt = atId + recipients.length; atId < endAt; atId++ ) { _mintNFTs(recipients[atId - startAt], 1); } } return _lastMintedTokenId(); } /** *** ---------------------------------- *** *** *** *** ADMIN CONFIGURATION FUNCTIONS *** *** *** *** ---------------------------------- *** ***/ // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | setOwner() | // | -------------------------> // | | // | | // ________________________________________________________ // ! ALT / caller is not admin? | ! // !_____/ | | ! // ! | revert Access_OnlyAdmin()| ! // ! | <------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | set owner // | |<---' // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @dev Set new owner for royalties / opensea /// @param newOwner new owner to set function setOwner(address newOwner) public onlyAdmin { _setOwner(newOwner); } /// @notice Set a new metadata renderer /// @param newRenderer new renderer address to use /// @param setupRenderer data to setup new renderer with function setMetadataRenderer( IMetadataRenderer newRenderer, bytes memory setupRenderer ) external onlyAdmin { config.metadataRenderer = newRenderer; if (setupRenderer.length > 0) { newRenderer.initializeWithData(setupRenderer); } emit UpdatedMetadataRenderer({ sender: _msgSender(), renderer: newRenderer }); } // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | setSalesConfiguration() | // | ----------------------------------> // | | // | | // _________________________________________________________________ // ! ALT / caller is not admin? | ! // !_____/ | | ! // ! | revert Access_MissingRoleOrAdmin()| ! // ! | <---------------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | set funds recipient // | |<---' // | | // | |----. // | | | emit FundsRecipientChanged() // | |<---' // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @dev This sets the sales configuration // / @param publicSalePrice New public sale price function setSaleConfiguration( uint104 publicSalePrice, uint32 maxSalePurchasePerAddress, uint64 publicSaleStart, uint64 publicSaleEnd, uint64 presaleStart, uint64 presaleEnd, uint104 allowlistSalePrice, address allowlistContractAddress, bytes32 presaleMerkleRoot ) external onlyRoleOrAdmin(SALES_MANAGER_ROLE) { // SalesConfiguration storage newConfig = SalesConfiguration({ // publicSaleStart: publicSaleStart, // publicSaleEnd: publicSaleEnd, // presaleStart: presaleStart, // presaleEnd: presaleEnd, // publicSalePrice: publicSalePrice, // maxSalePurchasePerAddress: maxSalePurchasePerAddress, // presaleMerkleRoot: presaleMerkleRoot // }); salesConfig.publicSalePrice = publicSalePrice; salesConfig.maxSalePurchasePerAddress = maxSalePurchasePerAddress; salesConfig.publicSaleStart = publicSaleStart; salesConfig.publicSaleEnd = publicSaleEnd; salesConfig.presaleStart = presaleStart; salesConfig.presaleEnd = presaleEnd; salesConfig.presaleMerkleRoot = presaleMerkleRoot; salesConfig.allowlistSalePrice = allowlistSalePrice; salesConfig.allowlistContractAddress = allowlistContractAddress; emit SalesConfigChanged(_msgSender()); } // ,-. // `-' // /|\ // | ,----------. // / \ |KitsERC721Drop| // Caller `----+-----' // | setOwner() | // | -------------------------> // | | // | | // ________________________________________________________ // ! ALT / caller is not admin or SALES_MANAGER_ROLE? ! // !_____/ | | ! // ! | revert Access_OnlyAdmin()| ! // ! | <------------------------- ! // !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | // | |----. // | | | set sales configuration // | |<---' // | | // | |----. // | | | emit SalesConfigChanged() // | |<---' // Caller ,----+-----. // ,-. |KitsERC721Drop| // `-' `----------' // /|\ // | // / \ /// @notice Set a different funds recipient /// @param newRecipientAddress new funds recipient address function setFundsRecipient( address payable newRecipientAddress ) external onlyRoleOrAdmin(SALES_MANAGER_ROLE) { // TODO(iain): funds recipient cannot be 0? config.fundsRecipient = newRecipientAddress; emit FundsRecipientChanged(newRecipientAddress, _msgSender()); } // ,-. ,-. ,-. // `-' `-' `-' // /|\ /|\ /|\ // | | | ,----------. // / \ / \ / \ |KitsERC721Drop| // Caller FeeRecipient FundsRecipient `----+-----' // | | withdraw() | | // | -------------------------------------------------------------------------> // | | | | // | | | | // | | | | // | | | | // | | | | // | | | ____________________________________________________________ // | | | ! ALT / send unsuccesful? ! // | | | !_____/ | ! // | | | ! |----. ! // | | | ! | | revert Withdraw_FundsSendFailure() ! // | | | ! |<---' ! // | | | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | | !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | | | // | | | send remaining funds amount| // | | | <--------------------------- // | | | | // | | | | // | | | ____________________________________________________________ // | | | ! ALT / send unsuccesful? ! // | | | !_____/ | ! // | | | ! |----. ! // | | | ! | | revert Withdraw_FundsSendFailure() ! // | | | ! |<---' ! // | | | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // | | | !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! // Caller FeeRecipient FundsRecipient ,----+-----. // ,-. ,-. ,-. |KitsERC721Drop| // `-' `-' `-' `----------' // /|\ /|\ /|\ // | | | // / \ / \ / \ /// @notice This withdraws ETH from the contract to the contract owner. Anyone can call this. function withdraw() external nonReentrant { // Get fee amount uint256 funds = address(this).balance; // Payout recipient (bool successFunds, ) = config.fundsRecipient.call{ value: funds, gas: FUNDS_SEND_GAS_LIMIT }(""); if (!successFunds) { revert Withdraw_FundsSendFailure(); } // Emit event for indexing emit FundsWithdrawn( _msgSender(), config.fundsRecipient, funds, address(0x0), // formerly feeRecipient. we are not collecting a fee 0 // formerly kitsFee. we are not collecting a fee ); } /** *** ---------------------------------- *** *** *** *** GENERAL GETTER FUNCTIONS *** *** *** *** ---------------------------------- *** ***/ /// @notice Simple override for owner interface. /// @return user owner address function owner() public view override(OwnableSkeleton, IKitsERC721Drop) returns (address) { return super.owner(); } /// @notice Contract URI Getter, proxies to metadataRenderer /// @return Contract URI function contractURI() external view returns (string memory) { return config.metadataRenderer.contractURI(); } /// @notice Getter for metadataRenderer contract function metadataRenderer() external view returns (IMetadataRenderer) { return IMetadataRenderer(config.metadataRenderer); } /// @notice Token URI Getter, proxies to metadataRenderer /// @param tokenId id of token to get URI for /// @return Token URI function tokenURI( uint256 tokenId ) public view override returns (string memory) { if (!_exists(tokenId)) { revert IERC721AUpgradeable.URIQueryForNonexistentToken(); } return string.concat( baseURI, "/", Strings.toHexString(uint256(uint160(address(this))), 20), "/", Strings.toString(tokenId) ); } /// @notice ERC165 supports interface /// @param interfaceId interface id to check if supported function supportsInterface( bytes4 interfaceId ) public view override( IERC165Upgradeable, ERC721AUpgradeable, AccessControlUpgradeable ) returns (bool) { return super.supportsInterface(interfaceId) || type(IOwnable).interfaceId == interfaceId || type(IERC2981Upgradeable).interfaceId == interfaceId || type(IKitsERC721Drop).interfaceId == interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IKitsERC721Drop} from "../../interfaces/IKitsERC721Drop.sol"; contract ERC721DropStorageV1 { /// @notice Required number of rarity configs when calling updateRarities uint8 constant NUMBER_OF_RARITY_CONFIGS = 10; uint16 constant TARGET_RARITY_MOD = 10000; /// @notice Configuration for NFT minting contract storage IKitsERC721Drop.Configuration public config; /// @notice Sales configuration IKitsERC721Drop.SalesConfiguration public salesConfig; /// @dev Number of total presale mints. Includes merkle root mints plus allowlist mints uint256 public presaleMints; /// @dev Mapping for presale mint counts by address mapping(address => uint256) public presaleMintsByAddress; /// @dev Rarity configurations. /// @notice uint256 serves as the ID used by rarityMapping mapping(uint256 => IKitsERC721Drop.RarityConfiguration) public rarityConfigs; /// @dev mapping of TokenID => rarity id /// @notice gets set on token mint mapping(uint256 => uint256) public rarityMapping; /// @dev get rarity mapping function getRarityMapping(uint256 tokenId) external view returns (uint256) { return rarityMapping[tokenId]; } function getRarityConfig( uint256 rarityId ) external view returns (IKitsERC721Drop.RarityConfiguration memory) { return rarityConfigs[rarityId]; } /// @dev stores current random value uint256 currentRandom; /// @dev HTTP URI, up to but not including, the contract address. eg: https://arpeggi.io/api/v2/kits-metadata string baseURI; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @notice This allows this contract to receive native currency funds from other contracts * Uses event logging for UI reasons. */ contract FundsReceiver { event FundsReceived(address indexed source, uint256 amount); receive() external payable { emit FundsReceived(msg.sender, msg.value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IOwnable} from "../../interfaces/IOwnable.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. * * This ownership interface matches OZ's ownable interface. */ contract OwnableSkeleton is IOwnable { address private _owner; /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } function _setOwner(address newAddress) internal { emit OwnershipTransferred(_owner, newAddress); _owner = newAddress; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; contract Version { uint32 private immutable __version; /// @notice The version of the contract /// @return The version ID of this contract implementation function contractVersion() external view returns (uint32) { return __version; } constructor(uint32 version) { __version = version; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; interface IFactoryUpgradeGate { function isValidUpgradePath( address _newImpl, address _currentImpl ) external returns (bool); function registerNewUpgradePath( address _newImpl, address[] calldata _supportedPrevImpls ) external; function unregisterUpgradePath( address _newImpl, address _prevImpl ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IMetadataRenderer} from "./IMetadataRenderer.sol"; /** ██╗ ██╗██╗████████╗███████╗ ██║ ██╔╝██║╚══██╔══╝██╔════╝ █████╔╝ ██║ ██║ ███████╗ ██╔═██╗ ██║ ██║ ╚════██║ ██║ ██╗██║ ██║ ███████║ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ Forked from Zora Drop by [email protected] */ /// @notice Interface for KITS Drops contract interface IKitsERC721Drop { // Access errors /// @notice Only admin can access this function error Access_OnlyAdmin(); /// @notice Missing the given role or admin access error Access_MissingRoleOrAdmin(bytes32 role); /// @notice Withdraw is not allowed by this user error Access_WithdrawNotAllowed(); /// @notice Cannot withdraw funds due to ETH send failure. error Withdraw_FundsSendFailure(); /// @notice Thrown when the operator for the contract is not allowed /// @dev Used when strict enforcement of marketplaces for creator royalties is desired. error OperatorNotAllowed(address operator); /// @notice Thrown when there is no active market filter DAO address supported for the current chain /// @dev Used for enabling and disabling filter for the given chain. error MarketFilterDAOAddressNotSupportedForChain(); /// @notice Used when the operator filter registry external call fails /// @dev Used for bubbling error up to clients. error RemoteOperatorFilterRegistryCallFailed(); // Sale/Purchase errors /// @notice Sale is inactive error Sale_Inactive(); /// @notice Presale is inactive error Presale_Inactive(); /// @notice Presale merkle root is invalid error Presale_MerkleNotApproved(); /// @notice User does not own a token on the presale contract error Presale_UserNotAllowlist(); /// @notice Wrong price for purchase error Purchase_WrongPrice(uint256 correctPrice); /// @notice NFT sold out, public sale error Mint_SoldOut(); /// @notice NFT sold out, pre sale error Mint_Presale_SoldOut(); /// @notice Too many purchase for address error Purchase_TooManyForAddress(); /// @notice Too many presale for address error Presale_TooManyForAddress(); // Admin errors /// @notice Royalty percentage too high error Setup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS); /// @notice Invalid admin upgrade address error Admin_InvalidUpgradeAddress(address proposedAddress); /// @notice Unable to finalize an edition not marked as open (size set to uint64_max_value) error Admin_UnableToFinalizeNotOpenEdition(); /// @notice Event emitted for each sale /// @param to address sale was made to /// @param quantity quantity of the minted nfts /// @param pricePerToken price for each token /// @param firstPurchasedTokenId first purchased token ID (to get range add to quantity for max) event Sale( address indexed to, uint256 indexed quantity, uint256 indexed pricePerToken, uint256 firstPurchasedTokenId ); /// @notice Sales configuration has been changed /// @dev To access new sales configuration, use getter function. /// @param changedBy Changed by user event SalesConfigChanged(address indexed changedBy); /// @notice Event emitted when the funds recipient is changed /// @param newAddress new address for the funds recipient /// @param changedBy address that the recipient is changed by event FundsRecipientChanged( address indexed newAddress, address indexed changedBy ); /// @notice Event emitted when the funds are withdrawn from the minting contract /// @param withdrawnBy address that issued the withdraw /// @param withdrawnTo address that the funds were withdrawn to /// @param amount amount that was withdrawn /// @param feeRecipient user getting withdraw fee (if any) /// @param feeAmount amount of the fee getting sent (if any) event FundsWithdrawn( address indexed withdrawnBy, address indexed withdrawnTo, uint256 amount, address feeRecipient, uint256 feeAmount ); /// @notice Event emitted when an open mint is finalized and further minting is closed forever on the contract. /// @param sender address sending close mint /// @param numberOfMints number of mints the contract is finalized at event OpenMintFinalized(address indexed sender, uint256 numberOfMints); /// @notice Event emitted when metadata renderer is updated. /// @param sender address of the updater /// @param renderer new metadata renderer address event UpdatedMetadataRenderer(address sender, IMetadataRenderer renderer); /// @notice Event emitted when rarities are updated. /// @param sender address updating rarities /// @param rarityConfigs new rarity configs used event UpdatedRarities( address indexed sender, RarityConfiguration[10] rarityConfigs ); event UpdateBaseUri(address indexed sender, string baseURI); struct AvailableTiers { uint256 rarityId; uint256 tierMintsRemaining; } /// @notice General configuration for NFT Minting and bookkeeping struct Configuration { /// @dev Metadata renderer (uint160) IMetadataRenderer metadataRenderer; /// @dev Total size of edition that can be minted (including public and presale) (uint160+64 = 224) uint64 totalEditionSize; /// @dev Royalty amount in bps (uint224+16 = 240) uint16 royaltyBPS; /// @dev Funds recipient for sale (new slot, uint160) address payable fundsRecipient; /// @dev Total size of edition available during presale uint64 presaleEditionSize; } /// @notice General configuration for rarity tiers struct RarityConfiguration { /// @dev Total number of tokens that belong to this tier uint256 tierVolume; /// @dev Name of the tier string name; /// @dev URI of the cover image for this tier string coverImageURI; /// @dev The description for this rarity. Used as the description of the token. string rarityDescription; /// @dev The number of tokens that have been minted at this rarity uint256 volumeMinted; } /// @notice Sales states and configuration /// @dev Uses 3 storage slots struct SalesConfiguration { /// @dev Public sale price (max ether value > 1000 ether with this value) uint104 publicSalePrice; /// @notice Purchase mint limit per address (if set to 0 === unlimited mints) /// @dev Max purchase number per txn (90+32 = 122) uint32 maxSalePurchasePerAddress; /// @dev uint64 type allows for dates into 292 billion years /// @notice Public sale start timestamp (136+64 = 186) uint64 publicSaleStart; /// @notice Public sale end timestamp (186+64 = 250) uint64 publicSaleEnd; /// @notice Presale start timestamp /// @dev new storage slot uint64 presaleStart; /// @notice Presale end timestamp uint64 presaleEnd; /// @notice Allowlist sale price. Different from presale price uint104 allowlistSalePrice; /// @notice Allowlist contract address address allowlistContractAddress; /// @notice Presale merkle root bytes32 presaleMerkleRoot; } /// @notice Return value for sales details to use with front-ends struct SaleDetails { // Synthesized status variables for sale and presale bool publicSaleActive; bool presaleActive; // Price for public sale uint256 publicSalePrice; // Timed sale actions for public sale uint64 publicSaleStart; uint64 publicSaleEnd; // Timed sale actions for presale uint64 presaleStart; uint64 presaleEnd; // Merkle root (includes address, quantity, and price data for each entry) bytes32 presaleMerkleRoot; // Limit public sale to a specific number of mints per wallet uint256 maxSalePurchasePerAddress; // Information about the rest of the supply // Total that have been minted uint256 totalMinted; // Total presale that have been minted uint256 totalPreSaleMinted; // The total supply available uint256 maxSupply; } /// @notice Return type of specific mint counts and details per address struct AddressMintDetails { /// Number of total mints from the given address uint256 totalMints; /// Number of presale mints from the given address uint256 presaleMints; /// Number of public mints from the given address uint256 publicMints; } /// @notice External purchase function (payable in eth) /// @param quantity to purchase /// @return first minted token ID function purchase(uint256 quantity) external payable returns (uint256); /// @notice External purchase presale function (takes a merkle proof and matches to root) (payable in eth) /// @param quantity to purchase /// @param maxQuantity can purchase (verified by merkle root) /// @param pricePerToken price per token allowed (verified by merkle root) /// @param merkleProof input for merkle proof leaf verified by merkle root /// @return first minted token ID function purchasePresale( uint256 quantity, uint256 maxQuantity, uint256 pricePerToken, bytes32[] memory merkleProof ) external payable returns (uint256); /// @notice Function to return the global sales details for the given drop function saleDetails() external view returns (SaleDetails memory); /// @notice Function to get rarity mapping id for a given token id // /// @notice Function to return the specific sales details for a given address /// @param minter address for minter to return mint information for function mintedPerAddress( address minter ) external view returns (AddressMintDetails memory); /// @notice This is the opensea/public owner setting that can be set by the contract admin function owner() external view returns (address); /// @notice Update the metadata renderer /// @param newRenderer new address for renderer /// @param setupRenderer data to call to bootstrap data for the new renderer (optional) function setMetadataRenderer( IMetadataRenderer newRenderer, bytes memory setupRenderer ) external; /// @notice This is an admin mint function to mint a quantity to a specific address /// @param to address to mint to /// @param quantity quantity to mint /// @return the id of the first minted NFT function adminMint(address to, uint256 quantity) external returns (uint256); /// @notice This is an admin mint function to mint a single nft each to a list of addresses /// @param to list of addresses to mint an NFT each to /// @return the id of the first minted NFT function adminMintAirdrop(address[] memory to) external returns (uint256); /// @dev Getter for admin role associated with the contract to handle metadata /// @return boolean if address is admin function isAdmin(address user) external view returns (bool); /// @notice This sets the _baseURI variable on the contract /// @param baseUri HTTP URI, up to but not including, the contract address. eg: https://arpeggi.io/api/v2/kits-metadata function setBaseUri(string memory baseUri) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; interface IKitsFeeManager { function getKITSWithdrawFeesBPS( address sender ) external returns (address payable, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; interface IMetadataRenderer { function tokenURI(uint256) external view returns (string memory); function contractURI() external view returns (string memory); function initializeWithData(bytes memory initData) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; interface IOperatorFilterRegistry { function isOperatorAllowed( address registrant, address operator ) external view returns (bool); function register(address registrant) external; function registerAndSubscribe( address registrant, address subscription ) external; function registerAndCopyEntries( address registrant, address registrantToCopy ) external; function updateOperator( address registrant, address operator, bool filtered ) external; function updateOperators( address registrant, address[] calldata operators, bool filtered ) external; function updateCodeHash( address registrant, bytes32 codehash, bool filtered ) external; function updateCodeHashes( address registrant, bytes32[] calldata codeHashes, bool filtered ) external; function subscribe( address registrant, address registrantToSubscribe ) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers( address registrant ) external returns (address[] memory); function subscriberAt( address registrant, uint256 index ) external returns (address); function copyEntriesOf( address registrant, address registrantToCopy ) external; function isOperatorFiltered( address registrant, address operator ) external returns (bool); function isCodeHashOfFiltered( address registrant, address operatorWithCode ) external returns (bool); function isCodeHashFiltered( address registrant, bytes32 codeHash ) external returns (bool); function filteredOperators( address addr ) external returns (address[] memory); function filteredCodeHashes( address addr ) external returns (bytes32[] memory); function filteredOperatorAt( address registrant, uint256 index ) external returns (address); function filteredCodeHashAt( address registrant, uint256 index ) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); function unregister(address registrant) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @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. * * This ownership interface matches OZ's ownable interface. * */ interface IOwnable { error ONLY_OWNER(); error ONLY_PENDING_OWNER(); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); event OwnerPending( address indexed previousOwner, address indexed potentialNewOwner ); event OwnerCanceled( address indexed previousOwner, address indexed potentialNewOwner ); /** * @dev Returns the address of the current owner. */ function owner() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControlUpgradeable.sol"; import "../utils/ContextUpgradeable.sol"; import "../utils/StringsUpgradeable.sol"; import "../utils/introspection/ERC165Upgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable { function __AccessControl_init() internal onlyInitializing { } function __AccessControl_init_unchained() internal onlyInitializing { } struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", StringsUpgradeable.toHexString(account), " is missing role ", StringsUpgradeable.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165Upgradeable.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 IERC2981Upgradeable is IERC165Upgradeable { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// 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 IERC721ReceiverUpgradeable { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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 v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721Upgradeable.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721MetadataUpgradeable is IERC721Upgradeable { /** * @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.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = MathUpgradeable.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProofUpgradeable { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// 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 IERC165Upgradeable { /** * @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.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v3.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import "./IERC721AUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension. Built to optimize for lower gas during batch mints. * * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..). * * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721AUpgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721AUpgradeable { using AddressUpgradeable for address; using StringsUpgradeable for uint256; // The tokenId of the next token to be minted. uint256 internal _currentIndex; // The number of tokens burned. uint256 internal _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. See _ownershipOf implementation for details. mapping(uint256 => TokenOwnership) internal _ownerships; // Mapping owner address to address data mapping(address => AddressData) private _addressData; // 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; function __ERC721A_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC721A_init_unchained(name_, symbol_); } function __ERC721A_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); } /** * To change the starting tokenId, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens. */ function totalSupply() public view override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than _currentIndex - _startTokenId() times unchecked { return _currentIndex - _burnCounter - _startTokenId(); } } /** * Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view returns (uint256) { // Counter underflow is impossible as _currentIndex does not decrement, // and it is initialized to _startTokenId() unchecked { return _currentIndex - _startTokenId(); } } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC721Upgradeable).interfaceId || interfaceId == type(IERC721MetadataUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view override returns (uint256) { if (owner == address(0)) revert BalanceQueryForZeroAddress(); return uint256(_addressData[owner].balance); } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return uint256(_addressData[owner].numberMinted); } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return uint256(_addressData[owner].numberBurned); } /** * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return _addressData[owner].aux; } /** * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal { _addressData[owner].aux = aux; } /** * Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around in the collection over time. */ function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { TokenOwnership memory ownership = _ownerships[curr]; if (!ownership.burned) { if (ownership.addr != address(0)) { return ownership; } // Invariant: // There will always be an ownership that has an address and is not burned // before an ownership that does not have an address and is not burned. // Hence, curr will not underflow. while (true) { curr--; ownership = _ownerships[curr]; if (ownership.addr != address(0)) { return ownership; } } } } } revert OwnerQueryForNonexistentToken(); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view override returns (address) { return _ownershipOf(tokenId).addr; } /** * @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) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); 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 overriden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public override { address owner = ERC721AUpgradeable.ownerOf(tokenId); if (to == owner) revert ApprovalToCurrentOwner(); if (_msgSender() != owner) if(!isApprovedForAll(owner, _msgSender())) { revert ApprovalCallerNotOwnerNorApproved(); } _approve(to, tokenId, owner); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view override returns (address) { if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken(); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { if (operator == _msgSender()) revert ApproveToCaller(); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_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 { _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 { _transfer(from, to, tokenId); if (to.isContract()) if(!_checkContractOnERC721Received(from, to, tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** * @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`), */ function _exists(uint256 tokenId) internal view returns (bool) { return _startTokenId() <= tokenId && tokenId < _currentIndex && !_ownerships[tokenId].burned; } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal { _safeMint(to, quantity, ''); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * Emits a {Transfer} event. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { _addressData[to].balance += uint64(quantity); _addressData[to].numberMinted += uint64(quantity); _ownerships[startTokenId].addr = to; _ownerships[startTokenId].startTimestamp = uint64(block.timestamp); uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + quantity; if (to.isContract()) { do { emit Transfer(address(0), to, updatedIndex); if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (updatedIndex < end); // Reentrancy protection if (_currentIndex != startTokenId) revert(); } else { do { emit Transfer(address(0), to, updatedIndex++); } while (updatedIndex < end); } _currentIndex = updatedIndex; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event. */ function _mint(address to, uint256 quantity) internal { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { _addressData[to].balance += uint64(quantity); _addressData[to].numberMinted += uint64(quantity); _ownerships[startTokenId].addr = to; _ownerships[startTokenId].startTimestamp = uint64(block.timestamp); uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + quantity; do { emit Transfer(address(0), to, updatedIndex++); } while (updatedIndex < end); _currentIndex = updatedIndex; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Transfers `tokenId` from `from` to `to`. * * 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 ) private { TokenOwnership memory prevOwnership = _ownershipOf(tokenId); if (prevOwnership.addr != from) revert TransferFromIncorrectOwner(); bool isApprovedOrOwner = (_msgSender() == from || isApprovedForAll(from, _msgSender()) || getApproved(tokenId) == _msgSender()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); if (to == address(0)) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner _approve(address(0), tokenId, from); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256. unchecked { _addressData[from].balance -= 1; _addressData[to].balance += 1; TokenOwnership storage currSlot = _ownerships[tokenId]; currSlot.addr = to; currSlot.startTimestamp = uint64(block.timestamp); // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it. // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls. uint256 nextTokenId = tokenId + 1; TokenOwnership storage nextSlot = _ownerships[nextTokenId]; if (nextSlot.addr == address(0)) { // This will suffice for checking _exists(nextTokenId), // as a burned slot cannot contain the zero address. if (nextTokenId != _currentIndex) { nextSlot.addr = from; nextSlot.startTimestamp = prevOwnership.startTimestamp; } } } emit Transfer(from, to, tokenId); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { TokenOwnership memory prevOwnership = _ownershipOf(tokenId); address from = prevOwnership.addr; if (approvalCheck) { bool isApprovedOrOwner = (_msgSender() == from || isApprovedForAll(from, _msgSender()) || getApproved(tokenId) == _msgSender()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner _approve(address(0), tokenId, from); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256. unchecked { AddressData storage addressData = _addressData[from]; addressData.balance -= 1; addressData.numberBurned += 1; // Keep track of who burned the token, and the timestamp of burning. TokenOwnership storage currSlot = _ownerships[tokenId]; currSlot.addr = from; currSlot.startTimestamp = uint64(block.timestamp); currSlot.burned = true; // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it. // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls. uint256 nextTokenId = tokenId + 1; TokenOwnership storage nextSlot = _ownerships[nextTokenId]; if (nextSlot.addr == address(0)) { // This will suffice for checking _exists(nextTokenId), // as a burned slot cannot contain the zero address. if (nextTokenId != _currentIndex) { nextSlot.addr = from; nextSlot.startTimestamp = prevOwnership.startTimestamp; } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { _burnCounter++; } } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve( address to, uint256 tokenId, address owner ) private { _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target 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 _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721ReceiverUpgradeable(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert TransferToNonERC721ReceiverImplementer(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } /** * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting. * And also called before burning one token. * * startTokenId - the first token id to be transferred * quantity - the amount to be transferred * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes * minting. * And also called after one token has been burned. * * startTokenId - the first token id to be transferred * quantity - the amount to be transferred * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[42] private __gap; }
// SPDX-License-Identifier: MIT // ERC721A Contracts v3.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol"; /** * @dev Interface of an ERC721A compliant contract. */ interface IERC721AUpgradeable is IERC721Upgradeable, IERC721MetadataUpgradeable { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * The caller cannot approve to their own address. */ error ApproveToCaller(); /** * The caller cannot approve to the current owner. */ error ApprovalToCurrentOwner(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); // Compiler will pack this into a single 256bit word. struct TokenOwnership { // The address of the owner. address addr; // Keeps track of the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; } // Compiler will pack this into a single 256bit word. struct AddressData { // Realistically, 2**64-1 is more than enough. uint64 balance; // Keeps track of mint count with minimal overhead for tokenomics. uint64 numberMinted; // Keeps track of burn count with minimal overhead for tokenomics. uint64 numberBurned; // For miscellaneous variable(s) pertaining to the address // (e.g. number of whitelist mint slots used). // If there are multiple variables, please pack them into a uint64. uint64 aux; } /** * @dev Returns the total amount of tokens stored by the contract. * * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens. */ function totalSupply() external view returns (uint256); }
{ "remappings": [ "@openzeppelin/=node_modules/@openzeppelin/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc721a-upgradeable/=node_modules/erc721a-upgradeable/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "operator-filter-registry/=node_modules/operator-filter-registry/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IKitsFeeManager","name":"_kitsFeeManager","type":"address"},{"internalType":"address","name":"_kitsERC721TransferHelper","type":"address"},{"internalType":"contract IFactoryUpgradeGate","name":"_factoryUpgradeGate","type":"address"},{"internalType":"address","name":"_marketFilterDAOAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"Access_MissingRoleOrAdmin","type":"error"},{"inputs":[],"name":"Access_OnlyAdmin","type":"error"},{"inputs":[],"name":"Access_WithdrawNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"proposedAddress","type":"address"}],"name":"Admin_InvalidUpgradeAddress","type":"error"},{"inputs":[],"name":"Admin_UnableToFinalizeNotOpenEdition","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MarketFilterDAOAddressNotSupportedForChain","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"Mint_Presale_SoldOut","type":"error"},{"inputs":[],"name":"Mint_SoldOut","type":"error"},{"inputs":[],"name":"ONLY_OWNER","type":"error"},{"inputs":[],"name":"ONLY_PENDING_OWNER","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"Presale_Inactive","type":"error"},{"inputs":[],"name":"Presale_MerkleNotApproved","type":"error"},{"inputs":[],"name":"Presale_TooManyForAddress","type":"error"},{"inputs":[],"name":"Presale_UserNotAllowlist","type":"error"},{"inputs":[],"name":"Purchase_TooManyForAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"correctPrice","type":"uint256"}],"name":"Purchase_WrongPrice","type":"error"},{"inputs":[],"name":"RemoteOperatorFilterRegistryCallFailed","type":"error"},{"inputs":[],"name":"Sale_Inactive","type":"error"},{"inputs":[{"internalType":"uint16","name":"maxRoyaltyBPS","type":"uint16"}],"name":"Setup_RoyaltyPercentageTooHigh","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"Withdraw_FundsSendFailure","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAddress","type":"address"},{"indexed":true,"internalType":"address","name":"changedBy","type":"address"}],"name":"FundsRecipientChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawnBy","type":"address"},{"indexed":true,"internalType":"address","name":"withdrawnTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"feeRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"numberOfMints","type":"uint256"}],"name":"OpenMintFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"potentialNewOwner","type":"address"}],"name":"OwnerCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"potentialNewOwner","type":"address"}],"name":"OwnerPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"firstPurchasedTokenId","type":"uint256"}],"name":"Sale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"changedBy","type":"address"}],"name":"SalesConfigChanged","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":"sender","type":"address"},{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"UpdateBaseUri","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"contract IMetadataRenderer","name":"renderer","type":"address"}],"name":"UpdatedMetadataRenderer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"uint256","name":"tierVolume","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"coverImageURI","type":"string"},{"internalType":"string","name":"rarityDescription","type":"string"},{"internalType":"uint256","name":"volumeMinted","type":"uint256"}],"indexed":false,"internalType":"struct IKitsERC721Drop.RarityConfiguration[10]","name":"rarityConfigs","type":"tuple[10]"}],"name":"UpdatedRarities","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALES_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"}],"name":"adminMintAirdrop","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"contract IMetadataRenderer","name":"metadataRenderer","type":"address"},{"internalType":"uint64","name":"totalEditionSize","type":"uint64"},{"internalType":"uint16","name":"royaltyBPS","type":"uint16"},{"internalType":"address payable","name":"fundsRecipient","type":"address"},{"internalType":"uint64","name":"presaleEditionSize","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractVersion","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rarityId","type":"uint256"}],"name":"getRarityConfig","outputs":[{"components":[{"internalType":"uint256","name":"tierVolume","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"coverImageURI","type":"string"},{"internalType":"string","name":"rarityDescription","type":"string"},{"internalType":"uint256","name":"volumeMinted","type":"uint256"}],"internalType":"struct IKitsERC721Drop.RarityConfiguration","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getRarityMapping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_contractName","type":"string"},{"internalType":"string","name":"_contractSymbol","type":"string"},{"internalType":"address","name":"_initialOwner","type":"address"},{"internalType":"address payable","name":"_fundsRecipient","type":"address"},{"internalType":"uint64","name":"_totalEditionSize","type":"uint64"},{"internalType":"uint64","name":"_presaleEditionSize","type":"uint64"},{"internalType":"uint16","name":"_royaltyBPS","type":"uint16"},{"components":[{"internalType":"uint104","name":"publicSalePrice","type":"uint104"},{"internalType":"uint32","name":"maxSalePurchasePerAddress","type":"uint32"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"uint104","name":"allowlistSalePrice","type":"uint104"},{"internalType":"address","name":"allowlistContractAddress","type":"address"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"}],"internalType":"struct IKitsERC721Drop.SalesConfiguration","name":"_salesConfig","type":"tuple"},{"internalType":"contract IMetadataRenderer","name":"_metadataRenderer","type":"address"},{"internalType":"string","name":"_baseURI","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftOwner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kitsFeeManager","outputs":[{"internalType":"contract IKitsFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"manageMarketFilterDAOSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"metadataRenderer","outputs":[{"internalType":"contract IMetadataRenderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"mintedPerAddress","outputs":[{"components":[{"internalType":"uint256","name":"totalMints","type":"uint256"},{"internalType":"uint256","name":"presaleMints","type":"uint256"},{"internalType":"uint256","name":"publicMints","type":"uint256"}],"internalType":"struct IKitsERC721Drop.AddressMintDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"presaleMintsByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"purchaseAllowlist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"purchasePresale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rarityConfigs","outputs":[{"internalType":"uint256","name":"tierVolume","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"coverImageURI","type":"string"},{"internalType":"string","name":"rarityDescription","type":"string"},{"internalType":"uint256","name":"volumeMinted","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rarityMapping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleDetails","outputs":[{"components":[{"internalType":"bool","name":"publicSaleActive","type":"bool"},{"internalType":"bool","name":"presaleActive","type":"bool"},{"internalType":"uint256","name":"publicSalePrice","type":"uint256"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"},{"internalType":"uint256","name":"maxSalePurchasePerAddress","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"},{"internalType":"uint256","name":"totalPreSaleMinted","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"}],"internalType":"struct IKitsERC721Drop.SaleDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"salesConfig","outputs":[{"internalType":"uint104","name":"publicSalePrice","type":"uint104"},{"internalType":"uint32","name":"maxSalePurchasePerAddress","type":"uint32"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"uint104","name":"allowlistSalePrice","type":"uint104"},{"internalType":"address","name":"allowlistContractAddress","type":"address"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseUri_","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newRecipientAddress","type":"address"}],"name":"setFundsRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMetadataRenderer","name":"newRenderer","type":"address"},{"internalType":"bytes","name":"setupRenderer","type":"bytes"}],"name":"setMetadataRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRandom","type":"uint256"}],"name":"setRandom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint104","name":"publicSalePrice","type":"uint104"},{"internalType":"uint32","name":"maxSalePurchasePerAddress","type":"uint32"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"uint104","name":"allowlistSalePrice","type":"uint104"},{"internalType":"address","name":"allowlistContractAddress","type":"address"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"}],"name":"setSaleConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"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":"bytes","name":"args","type":"bytes"}],"name":"updateMarketFilterSettings","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"tierVolume","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"coverImageURI","type":"string"},{"internalType":"string","name":"rarityDescription","type":"string"},{"internalType":"uint256","name":"volumeMinted","type":"uint256"}],"internalType":"struct IKitsERC721Drop.RarityConfiguration[10]","name":"_rarityConfigs","type":"tuple[10]"}],"name":"updateRarities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61020060405230608052600860c0526305f5e0ff60e05262033450610100527ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc9610120527f5ebbf78043a2215b522b1366a193ec74dd1f54e441e841a87b9653246a9c49a6610140526daaeb6d7670e522a718067333cd4e6101e0523480156200008857600080fd5b5060405162005f9a38038062005f9a833981016040819052620000ab916200022b565b61232960a052600054610100900460ff1615808015620000d25750600054600160ff909116105b80620001025750620000ef306200020360201b620030841760201c565b15801562000102575060005460ff166001145b6200016a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156200018e576000805461ff0019166101001790555b6001600160a01b038086166101a052848116610160528381166101805282166101c0528015620001f8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505062000293565b6001600160a01b03163b151590565b6001600160a01b03811681146200022857600080fd5b50565b600080600080608085870312156200024257600080fd5b84516200024f8162000212565b6020860151909450620002628162000212565b6040860151909350620002758162000212565b6060860151909250620002888162000212565b939692955090935050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051615bfa620003a06000396000818161203f01528181612102015281816121b0015281816122050152818161227e015281816127130152818161403f015261408a015260008181611fdb015281816120da0152612188015260006109d00152600061376401526000612e69015260008181610c7501528181610fe60152612b2e015260008181610c0e015281816125d80152612d3601526000611a3a01526000505060008181613456015261348301526000610abb01526000818161186b015281816118ab01528181611d6f01528181611daf0152611e270152615bfa6000f3fe60806040526004361061038f5760003560e01c80636352211e116101dc578063a22cb46511610102578063d547741f116100a0578063e58306f91161006f578063e58306f914610cb7578063e8a3d48514610cd7578063e985e9c514610cec578063efef39a114610d0c57600080fd5b8063d547741f14610c30578063db0b680d14610c50578063e26bd34314610c63578063e38deb1414610c9757600080fd5b8063bb20d857116100dc578063bb20d85714610b7a578063c87b56dd14610b9a578063d445b97814610bba578063d539139314610bfc57600080fd5b8063a22cb46514610b1a578063b88d4fde14610b3a578063b8ae5a2c14610b5a57600080fd5b80638da5cb5b1161017a5780639d4744b7116101495780639d4744b714610a73578063a0a8e46014610aa4578063a0bcfc7f14610ae5578063a217fddf14610b0557600080fd5b80638da5cb5b14610a0957806391d1485414610a1e57806395d89b4114610a3e5780639bdb89e514610a5357600080fd5b8063729e7cf6116101b6578063729e7cf61461091057806379502c55146109305780637eb55231146109be578063877568cb146109f257600080fd5b80636352211e146108b157806370319970146108d157806370a08231146108f057600080fd5b80632a55205a116102c15780633ccfd60b1161025f5780634b25fbe31161022e5780634b25fbe31461082d5780634f1ef2861461085b57806352d1902d1461086e57806361fea7681461088357600080fd5b80633ccfd60b146107ab57806342842e0e146107c057806342966c68146107e057806347e959151461080057600080fd5b80633474a4a61161029b5780633474a4a61461072957806336568abe1461074b5780633659cfe61461076b5780633bcdcc871461078b57600080fd5b80632a55205a146106aa5780632c6d68a3146106e95780632f2ff15d1461070957600080fd5b806315c6a6001161032e57806323b872dd1161030857806323b872dd14610626578063248a9ca31461064657806324d7806c1461067757806325024a2b1461069757600080fd5b806315c6a600146104e157806318160ddd1461051d5780631d2c0b381461053a57600080fd5b8063081812fc1161036a578063081812fc14610449578063095ea7b31461048157806310a7eb5d146104a157806313af4035146104c157600080fd5b806279fe04146103d057806301ffc9a7146103f257806306fdde031461042757600080fd5b366103cb5760405134815233907f8e47b87b0ef542cdfa1659c551d88bad38aa7f452d2bbb349ab7530dfec8be8f9060200160405180910390a2005b600080fd5b3480156103dc57600080fd5b506103f06103eb366004614b2a565b610d1f565b005b3480156103fe57600080fd5b5061041261040d366004614c6b565b610e26565b60405190151581526020015b60405180910390f35b34801561043357600080fd5b5061043c610e88565b60405161041e9190614cd8565b34801561045557600080fd5b50610469610464366004614ceb565b610f1a565b6040516001600160a01b03909116815260200161041e565b34801561048d57600080fd5b506103f061049c366004614d24565b610f5e565b3480156104ad57600080fd5b506103f06104bc366004614d50565b610fe4565b3480156104cd57600080fd5b506103f06104dc366004614d50565b611099565b3480156104ed57600080fd5b5061050f6104fc366004614ceb565b61016a6020526000908152604090205481565b60405190815260200161041e565b34801561052957600080fd5b50606654606554036000190161050f565b34801561054657600080fd5b5061016254610163546101645461016554610166546105b8946001600160681b0380821695600160681b830463ffffffff1695600160881b9093046001600160401b039081169581831695600160401b8404831695600160801b90940490921693909216916001600160a01b03169089565b604080516001600160681b039a8b16815263ffffffff9990991660208a01526001600160401b039788169089015294861660608801529285166080870152931660a08501529190931660c08301526001600160a01b031660e08201526101008101919091526101200161041e565b34801561063257600080fd5b506103f0610641366004614d6d565b6110cd565b34801561065257600080fd5b5061050f610661366004614ceb565b600090815261012d602052604090206001015490565b34801561068357600080fd5b50610412610692366004614d50565b6110d8565b61050f6106a5366004614df2565b6110e4565b3480156106b657600080fd5b506106ca6106c5366004614e52565b611311565b604080516001600160a01b03909316835260208301919091520161041e565b3480156106f557600080fd5b506103f0610704366004614f79565b611380565b34801561071557600080fd5b506103f0610724366004615078565b61168e565b34801561073557600080fd5b5061073e6116b4565b60405161041e91906150a8565b34801561075757600080fd5b506103f0610766366004615078565b6117e3565b34801561077757600080fd5b506103f0610786366004614d50565b611861565b34801561079757600080fd5b506103f06107a636600461517a565b611926565b3480156107b757600080fd5b506103f0611a18565b3480156107cc57600080fd5b506103f06107db366004614d6d565b611b1d565b3480156107ec57600080fd5b506103f06107fb366004614ceb565b611b38565b34801561080c57600080fd5b5061082061081b366004614ceb565b611b43565b60405161041e9190615232565b34801561083957600080fd5b5061050f610848366004614ceb565b600090815261016a602052604090205490565b6103f061086936600461517a565b611d65565b34801561087a57600080fd5b5061050f611e1a565b34801561088f57600080fd5b5061050f61089e366004614d50565b6101686020526000908152604090205481565b3480156108bd57600080fd5b506104696108cc366004614ceb565b611ecd565b3480156108dd57600080fd5b50610160546001600160a01b0316610469565b3480156108fc57600080fd5b5061050f61090b366004614d50565b611edf565b34801561091c57600080fd5b506103f061092b366004614ceb565b611f2d565b34801561093c57600080fd5b50610160546101615461097d916001600160a01b03808216926001600160401b03600160a01b80850482169461ffff600160e01b9091041693831692041685565b604080516001600160a01b0396871681526001600160401b03958616602082015261ffff90941690840152931660608201529116608082015260a00161041e565b3480156109ca57600080fd5b506104697f000000000000000000000000000000000000000000000000000000000000000081565b3480156109fe57600080fd5b5061050f6101675481565b348015610a1557600080fd5b50610469611f5b565b348015610a2a57600080fd5b50610412610a39366004615078565b611f75565b348015610a4a57600080fd5b5061043c611fa1565b348015610a5f57600080fd5b506103f0610a6e366004615253565b611fb0565b348015610a7f57600080fd5b50610a93610a8e366004614ceb565b6122af565b60405161041e959493929190615270565b348015610ab057600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161041e565b348015610af157600080fd5b506103f0610b00366004615303565b612477565b348015610b1157600080fd5b5061050f600081565b348015610b2657600080fd5b506103f0610b35366004615344565b6124f5565b348015610b4657600080fd5b506103f0610b55366004615372565b61258a565b348015610b6657600080fd5b5061050f610b753660046153dd565b6125d4565b348015610b8657600080fd5b5061043c610b95366004615303565b6126e4565b348015610ba657600080fd5b5061043c610bb5366004614ceb565b6127b8565b348015610bc657600080fd5b50610bda610bd5366004614d50565b61281f565b604080518251815260208084015190820152918101519082015260600161041e565b348015610c0857600080fd5b5061050f7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c3c57600080fd5b506103f0610c4b366004615078565b6128a0565b61050f610c5e366004614ceb565b6128c6565b348015610c6f57600080fd5b5061050f7f000000000000000000000000000000000000000000000000000000000000000081565b348015610ca357600080fd5b506103f0610cb2366004615412565b612b2c565b348015610cc357600080fd5b5061050f610cd2366004614d24565b612d32565b348015610ce357600080fd5b5061043c612df2565b348015610cf857600080fd5b50610412610d073660046154b7565b612e65565b61050f610d1a366004614ceb565b612ed9565b610d2a600033611f75565b610d47576040516302bd6bd160e01b815260040160405180910390fd5b60005b600a811015610de1578181600a8110610d6557610d656154e5565b60209081029190910151600083815261016983526040902081518155918101519091906001820190610d97908261557b565b5060408201516002820190610dac908261557b565b5060608201516003820190610dc1908261557b565b506080919091015160049091015580610dd981615650565b915050610d4a565b50336001600160a01b03167f1433261f918df6b640d17001d8490f5841fef00a243201b2f05120ec893ab1de82604051610e1b9190615669565b60405180910390a250565b6000610e3182613093565b80610e4c5750638da5cb5b60e01b6001600160e01b03198316145b80610e67575063152a902d60e11b6001600160e01b03198316145b80610e8257506322f924a760e11b6001600160e01b03198316145b92915050565b606060678054610e97906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec3906154fb565b8015610f105780601f10610ee557610100808354040283529160200191610f10565b820191906000526020600020905b815481529060010190602001808311610ef357829003601f168201915b5050505050905090565b6000610f25826130b8565b610f42576040516333d1c03960e21b815260040160405180910390fd5b506000908152606b60205260409020546001600160a01b031690565b6000610f6982611ecd565b9050806001600160a01b0316836001600160a01b031603610f9d5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b03821614610fd457610fb78133612e65565b610fd4576040516367d9dca160e11b815260040160405180910390fd5b610fdf8383836130f1565b505050565b7f0000000000000000000000000000000000000000000000000000000000000000611010600033611f75565b15801561102457506110228133611f75565b155b1561104a576040516333ba055f60e21b8152600481018290526024015b60405180910390fd5b61016180546001600160a01b0319166001600160a01b0384169081179091556040513391907f70a7ea5c664ab9c21baf3da59bb2f1e1ca33557b08a0031fab4f17076744995190600090a35050565b6110a4600033611f75565b6110c1576040516302bd6bd160e01b815260040160405180910390fd5b6110ca8161314d565b50565b610fdf8383836131ab565b6000610e828183611f75565b60006110ee6133a6565b61016154610167548791600160a01b90046001600160401b03169061111390836156b7565b11156111325760405163a84bbf1760e01b815260040160405180910390fd5b61113a6133ff565b61115757604051634af69e0d60e11b815260040160405180910390fd5b6111d284848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050610166549150339050604080516001600160a01b03909216602083015281018a9052606081018990526080016040516020818303038152906040528051906020012061343c565b6111ef576040516342db872960e11b815260040160405180910390fd5b6111f987866156ca565b34146112255761120987866156ca565b60405163350e0bcf60e11b815260040161104191815260200190565b3360009081526101686020526040812080548992906112459084906156b7565b9091555050336000908152610168602052604090205486101561127b5760405163a7b32bb160e01b815260040160405180910390fd5b61016780548801905561128e3388613452565b6000876112996134c8565b6112a391906156e1565b90506112b6816112b16134c8565b6134d9565b8588336001600160a01b03167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a90846040516112f391815260200190565b60405180910390a4915050611308600160fb55565b95945050505050565b6101615460009081906001600160a01b031661133d575050610161546001600160a01b03166000611379565b61016154610160546001600160a01b03909116906127109061136a90600160e01b900461ffff16866156ca565b611374919061570a565b915091505b9250929050565b600054610100900460ff16158080156113a05750600054600160ff909116105b806113ba5750303b1580156113ba575060005460ff166001145b61141d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611041565b6000805460ff191660011790558015611440576000805461ff0019166101001790555b61144a8b8b61355d565b61145261358e565b61145a6135b5565b61146560008a6135e4565b61146e8961314d565b61016054611388600160e01b90910461ffff1611156114a45760405163334074c160e11b81526113886004820152602401611041565b83516101628054602087015160408801516001600160681b0394851670ffffffffffffffffffffffffffffffffff1990931692909217600160681b63ffffffff909216919091021767ffffffffffffffff60881b1916600160881b6001600160401b03928316021790915560608601516101638054608089015160a08a01519385166001600160801b031990921691909117600160401b918516919091021767ffffffffffffffff60801b1916600160801b9284169290920291909117905560c086015161016480546cffffffffffffffffffffffffff1916919093161790915560e085015161016580546001600160a01b03199081166001600160a01b039384161790915561010087015161016655610160805461016180548986166001600160f01b0319909316600160a01b8f891681027fffff0000ffffffffffffffff0000000000000000000000000000000000000000169190911793909317600160e01b61ffff8e1602179093556001600160e01b0319909216948b160290911692909217908a1617905561016c61163a838261557b565b508015611681576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b600082815261012d60205260409020600101546116aa816135ee565b610fdf83836135f8565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915260405180610180016040528061172961367f565b151581526020016117386133ff565b15158152610162546001600160681b03811660208301526001600160401b03600160881b820481166040840152610163548082166060850152600160401b810482166080850152600160801b90041660a08301526101665460c083015263ffffffff600160681b9091041660e0820152610100016117b96065546000190190565b815261016754602082015261016054600160a01b90046001600160401b0316604090910152919050565b6001600160a01b03811633146118535760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401611041565b61185d82826136b6565b5050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036118a95760405162461bcd60e51b81526004016110419061571e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166118db61371e565b6001600160a01b0316146119015760405162461bcd60e51b81526004016110419061576a565b61190a8161373a565b604080516000808252602082019092526110ca91839190613833565b611931600033611f75565b61194e576040516302bd6bd160e01b815260040160405180910390fd5b61016080546001600160a01b0319166001600160a01b0384161790558051156119d0576040516342b53ffd60e11b81526001600160a01b0383169063856a7ffa9061199d908490600401614cd8565b600060405180830381600087803b1580156119b757600080fd5b505af11580156119cb573d6000803e3d6000fd5b505050505b7f046c5d913c35948c3e0e44c3599eb14bf33b73f141fa8bb282b300414998b86833604080516001600160a01b03928316815291851660208301520160405180910390a15050565b611a206133a6565b6101615460405147916000916001600160a01b03909116907f000000000000000000000000000000000000000000000000000000000000000090849084818181858888f193505050503d8060008114611a95576040519150601f19603f3d011682016040523d82523d6000602084013e611a9a565b606091505b5050905080611abc576040516339debd5b60e01b815260040160405180910390fd5b61016154604080518481526000602082018190528183015290516001600160a01b039092169133917f8a95554e4c9dcaaf33f247387f2ee77390780487d3365e3a804788791a1df500919081900360600190a35050611b1b600160fb55565b565b610fdf8383836040518060200160405280600081525061258a565b6110ca81600161399e565b611b756040518060a0016040528060008152602001606081526020016060815260200160608152602001600081525090565b61016960008381526020019081526020016000206040518060a001604052908160008201548152602001600182018054611bae906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054611bda906154fb565b8015611c275780601f10611bfc57610100808354040283529160200191611c27565b820191906000526020600020905b815481529060010190602001808311611c0a57829003601f168201915b50505050508152602001600282018054611c40906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6c906154fb565b8015611cb95780601f10611c8e57610100808354040283529160200191611cb9565b820191906000526020600020905b815481529060010190602001808311611c9c57829003601f168201915b50505050508152602001600382018054611cd2906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054611cfe906154fb565b8015611d4b5780601f10611d2057610100808354040283529160200191611d4b565b820191906000526020600020905b815481529060010190602001808311611d2e57829003601f168201915b505050505081526020016004820154815250509050919050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611dad5760405162461bcd60e51b81526004016110419061571e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ddf61371e565b6001600160a01b031614611e055760405162461bcd60e51b81526004016110419061576a565b611e0e8261373a565b61185d82826001613833565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611eba5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401611041565b50600080516020615b7e83398151915290565b6000611ed882613b72565b5192915050565b60006001600160a01b038216611f08576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152606a60205260409020546001600160401b031690565b611f38600033611f75565b611f55576040516302bd6bd160e01b815260040160405180910390fd5b61016b55565b6000611f7061015f546001600160a01b031690565b905090565b600091825261012d602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060688054610e97906154fb565b611fbb600033611f75565b611fd8576040516302bd6bd160e01b815260040160405180910390fd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661202057604051635acc4a8760e11b815260040160405180910390fd5b60405163c3c5a54760e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c3c5a547906024016020604051808303816000875af1158015612088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ac91906157b6565b1580156120b65750815b1561216357604051633e9f1edf60e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000811660248301527f00000000000000000000000000000000000000000000000000000000000000001690637d3e3dbe906044015b600060405180830381600087803b15801561214757600080fd5b505af115801561215b573d6000803e3d6000fd5b505050505050565b81156121df57604051632cc5350560e21b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063b314d4149060440161212d565b60405163034a0dc160e41b81526001600160a01b038281166004830152600060248301527f000000000000000000000000000000000000000000000000000000000000000016906334a0dc1090604401600060405180830381600087803b15801561224957600080fd5b505af115801561225d573d6000803e3d6000fd5b5050604051631761612360e11b81526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169250632ec2c246915060240161212d565b61016960205260009081526040902080546001820180549192916122d2906154fb565b80601f01602080910402602001604051908101604052809291908181526020018280546122fe906154fb565b801561234b5780601f106123205761010080835404028352916020019161234b565b820191906000526020600020905b81548152906001019060200180831161232e57829003601f168201915b505050505090806002018054612360906154fb565b80601f016020809104026020016040519081016040528092919081815260200182805461238c906154fb565b80156123d95780601f106123ae576101008083540402835291602001916123d9565b820191906000526020600020905b8154815290600101906020018083116123bc57829003601f168201915b5050505050908060030180546123ee906154fb565b80601f016020809104026020016040519081016040528092919081815260200182805461241a906154fb565b80156124675780601f1061243c57610100808354040283529160200191612467565b820191906000526020600020905b81548152906001019060200180831161244a57829003601f168201915b5050505050908060040154905085565b612482600033611f75565b61249f576040516302bd6bd160e01b815260040160405180910390fd5b61016c6124ad8284836157d3565b50336001600160a01b03167f981198a74a260b9813b2dc38651c0af99e9533d4f4e1dfe42fdd05cf997cd24c83836040516124e9929190615892565b60405180910390a25050565b336001600160a01b0383160361251e5760405163b06307db60e01b815260040160405180910390fd5b336000818152606c602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6125958484846131ab565b6001600160a01b0383163b156125ce576125b184848484613c94565b6125ce576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b60007f00000000000000000000000000000000000000000000000000000000000000006126018233611f75565b15801561261557506126138133611f75565b155b15612636576040516333ba055f60e21b815260048101829052602401611041565b610160548390600160a01b90046001600160401b03166126596065546000190190565b61266390836156b7565b111561268257604051630717c51360e41b815260040160405180910390fd5b606554808581015b808310156126d0576126c588888486038181106126a9576126a96154e5565b90506020020160208101906126be9190614d50565b6001613452565b60019092019161268a565b506126d96134c8565b979650505050505050565b60606126f1600033611f75565b61270e576040516302bd6bd160e01b815260040160405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316858560405161274b9291906158c1565b6000604051808303816000865af19150503d8060008114612788576040519150601f19603f3d011682016040523d82523d6000602084013e61278d565b606091505b5091509150816127b05760405163097ce21560e21b815260040160405180910390fd5b949350505050565b60606127c3826130b8565b6127e057604051630a14c4b560e41b815260040160405180910390fd5b61016c6127ee306014613d7f565b6127f784613f1a565b604051602001612809939291906158ed565b6040516020818303038152906040529050919050565b61284360405180606001604052806000815260200160008152602001600081525090565b604051806060016040528061285784613fac565b81526001600160a01b0384166000818152610168602081815260408084205482870181905294909352529091019061288e85613fac565b61289891906156e1565b905292915050565b600082815261012d60205260409020600101546128bc816135ee565b610fdf83836136b6565b60006128d06133a6565b61016154610167548391600160a01b90046001600160401b0316906128f590836156b7565b11156129145760405163a84bbf1760e01b815260040160405180910390fd5b61291c6133ff565b61293957604051634af69e0d60e11b815260040160405180910390fd5b610165546000906001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b791906159a0565b905060018110156129db57604051631126b58b60e21b815260040160405180910390fd5b610164546001600160681b03166129f285826156ca565b3414612a145760405163350e0bcf60e11b815260048101829052602401611041565b61016254600160681b900463ffffffff1615801590612a7f575061016254600160681b900463ffffffff166101686000336001600160a01b0316815260208101919091526040016000205486612a6933613fac565b612a7391906156b7565b612a7d91906156e1565b115b15612a9d57604051630882ba5360e21b815260040160405180910390fd5b610167805486019055612ab03386613452565b600085612abb6134c8565b612ac591906156e1565b9050612ad3816112b16134c8565b8186336001600160a01b03167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a9084604051612b1091815260200190565b60405180910390a49350505050612b27600160fb55565b919050565b7f0000000000000000000000000000000000000000000000000000000000000000612b58600033611f75565b158015612b6c5750612b6a8133611f75565b155b15612b8d576040516333ba055f60e21b815260048101829052602401611041565b8961016260000160006101000a8154816001600160681b0302191690836001600160681b0316021790555088610162600001600d6101000a81548163ffffffff021916908363ffffffff1602179055508761016260000160116101000a8154816001600160401b0302191690836001600160401b031602179055508661016260010160006101000a8154816001600160401b0302191690836001600160401b031602179055508561016260010160086101000a8154816001600160401b0302191690836001600160401b031602179055508461016260010160106101000a8154816001600160401b0302191690836001600160401b0316021790555081610162600401819055508361016260020160006101000a8154816001600160681b0302191690836001600160681b031602179055508261016260030160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550612cf13390565b6001600160a01b03167fc1ff5e4744ac8dd2b8027a10e3723b165975297501c71c4e7dcb8796d96375db60405160405180910390a250505050505050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612d5f8233611f75565b158015612d735750612d718133611f75565b155b15612d94576040516333ba055f60e21b815260048101829052602401611041565b610160548390600160a01b90046001600160401b0316612db76065546000190190565b612dc190836156b7565b1115612de057604051630717c51360e41b815260040160405180910390fd5b612dea8585613452565b6113086134c8565b610160546040805163e8a3d48560e01b815290516060926001600160a01b03169163e8a3d4859160048083019260009291908290030181865afa158015612e3d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f7091908101906159b9565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612ea857506001610e82565b6001600160a01b038084166000908152606c602090815260408083209386168352929052205460ff165b9392505050565b6000612ee36133a6565b610160548290600160a01b90046001600160401b0316612f066065546000190190565b612f1090836156b7565b1115612f2f57604051630717c51360e41b815260040160405180910390fd5b612f3761367f565b612f545760405163f12dcc7f60e01b815260040160405180910390fd5b610162546001600160681b0316612f6b84826156ca565b3414612f7b5761120984826156ca565b61016254600160681b900463ffffffff1615801590612fe6575061016254600160681b900463ffffffff166101686000336001600160a01b0316815260208101919091526040016000205485612fd033613fac565b612fda91906156b7565b612fe491906156e1565b115b1561300457604051630882ba5360e21b815260040160405180910390fd5b61300e3385613452565b6000846130196134c8565b61302391906156e1565b9050613031816112b16134c8565b8185336001600160a01b03167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a908460405161306e91815260200190565b60405180910390a492505050612b27600160fb55565b6001600160a01b03163b151590565b60006001600160e01b03198216637965db0b60e01b1480610e825750610e8282613fd7565b6000816001111580156130cc575060655482105b8015610e82575050600090815260696020526040902054600160e01b900460ff161590565b6000828152606b602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b61015f546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a361015f80546001600160a01b0319166001600160a01b0392909216919091179055565b60006131b682613b72565b9050836001600160a01b031681600001516001600160a01b0316146131ed5760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b038616148061320b575061320b8533612e65565b8061322657503361321b84610f1a565b6001600160a01b0316145b90508061324657604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03841661326d57604051633a954ecd60e21b815260040160405180910390fd5b61327a8585856001614027565b613286600084876130f1565b6001600160a01b038581166000908152606a60209081526040808320805467ffffffffffffffff198082166001600160401b0392831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652606990945282852080546001600160e01b031916909417600160a01b4290921691909102178355870180845292208054919390911661335a57606554821461335a57805460208601516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038a16171781555b50505082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b5050505050565b600260fb54036133f85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611041565b600260fb55565b6101635460009042600160401b9091046001600160401b031611801590611f705750506101635442600160801b9091046001600160401b03161190565b600082613449858461411c565b14949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000821161348157816134a3565b7f00000000000000000000000000000000000000000000000000000000000000005b90506134af8382614169565b6134b981836156e1565b91505060008111613452575050565b60006001606554611f7091906156e1565b60006134e68360016156b7565b90505b6134f16134c8565b6134fc9060016156b7565b811015610fdf57600061350e8261429a565b60008181526101696020526040812060040180549293509061352f83615650565b9091555050600082815261016a60205260409020558061354e81615650565b9150506134e9565b600160fb55565b600054610100900460ff166135845760405162461bcd60e51b815260040161104190615a26565b61185d828261446b565b600054610100900460ff16611b1b5760405162461bcd60e51b815260040161104190615a26565b600054610100900460ff166135dc5760405162461bcd60e51b815260040161104190615a26565b611b1b6144b5565b61185d82826135f8565b6110ca81336144dc565b6136028282611f75565b61185d57600082815261012d602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561363b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6101625460009042600160881b9091046001600160401b031611801590611f7057505061016354426001600160401b039091161190565b6136c08282611f75565b1561185d57600082815261012d602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600080516020615b7e833981519152546001600160a01b031690565b613745600033611f75565b613762576040516302bd6bd160e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663739958338261379a61371e565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af11580156137e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380b91906157b6565b6110ca57604051633bcafdf560e21b81526001600160a01b0382166004820152602401611041565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561386657610fdf83614535565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156138c0575060408051601f3d908101601f191682019092526138bd918101906159a0565b60015b6139235760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401611041565b600080516020615b7e83398151915281146139925760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401611041565b50610fdf8383836145d1565b60006139a983613b72565b80519091508215613a0f576000336001600160a01b03831614806139d257506139d28233612e65565b806139ed5750336139e286610f1a565b6001600160a01b0316145b905080613a0d57604051632ce44b5f60e11b815260040160405180910390fd5b505b613a1d816000866001614027565b613a29600085836130f1565b6001600160a01b038082166000818152606a602090815260408083208054600160801b6000196001600160401b0380841691909101811667ffffffffffffffff198416811783900482166001908101831690930277ffffffffffffffff0000000000000000ffffffffffffffff19909416179290921783558b86526069909452828520805460ff60e01b1942909316600160a01b026001600160e01b03199091169097179690961716600160e01b178555918901808452922080549194909116613b27576065548214613b2757805460208701516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038716171781555b5050604051869250600091506001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a450506066805460010190555050565b60408051606081018252600080825260208201819052918101919091528180600111613c7b57606554811015613c7b57600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff16151591810182905290613c795780516001600160a01b031615613c10579392505050565b5060001901600081815260696020908152604091829020825160608101845290546001600160a01b038116808352600160a01b82046001600160401b031693830193909352600160e01b900460ff1615159281019290925215613c74579392505050565b613c10565b505b604051636f96cda160e11b815260040160405180910390fd5b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290613cc9903390899088908890600401615a71565b6020604051808303816000875af1925050508015613d04575060408051601f3d908101601f19168201909252613d0191810190615aa4565b60015b613d62573d808015613d32576040519150601f19603f3d011682016040523d82523d6000602084013e613d37565b606091505b508051600003613d5a576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b60606000613d8e8360026156ca565b613d999060026156b7565b6001600160401b03811115613db057613db06149f9565b6040519080825280601f01601f191660200182016040528015613dda576020820181803683370190505b509050600360fc1b81600081518110613df557613df56154e5565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613e2457613e246154e5565b60200101906001600160f81b031916908160001a9053506000613e488460026156ca565b613e539060016156b7565b90505b6001811115613ecb576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613e8757613e876154e5565b1a60f81b828281518110613e9d57613e9d6154e5565b60200101906001600160f81b031916908160001a90535060049490941c93613ec481615ac1565b9050613e56565b508315612ed25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401611041565b60606000613f27836145f6565b60010190506000816001600160401b03811115613f4657613f466149f9565b6040519080825280601f01601f191660200182016040528015613f70576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084613f7a57509392505050565b6001600160a01b03166000908152606a6020526040902054600160401b90046001600160401b031690565b60006001600160e01b031982166380ac58cd60e01b148061400857506001600160e01b03198216635b5e139f60e01b145b80610e8257506301ffc9a760e01b6001600160e01b0319831614610e82565b6001600160a01b038416331480159061406a575060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b115b156125ce57604051633185c44d60e21b81523060048201523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c617113490604401602060405180830381865afa1580156140d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140fd91906157b6565b6125ce57604051633b79c77360e21b8152336004820152602401611041565b600081815b84518110156141615761414d82868381518110614140576141406154e5565b60200260200101516146ce565b91508061415981615650565b915050614121565b509392505050565b6065546001600160a01b03831661419257604051622e076360e81b815260040160405180910390fd5b816000036141b35760405163b562e8dd60e01b815260040160405180910390fd5b6141c06000848385614027565b6001600160a01b0383166000818152606a6020908152604080832080546001600160801b031981166001600160401b038083168a018116918217600160401b67ffffffffffffffff1990941690921783900481168a01811690920217909155858452606990925290912080546001600160e01b031916909217600160a01b4290921691909102179055808083015b6040516001830192906001600160a01b038716906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a480821061424e5750606555505050565b60006142a46149bf565b6000805b600a81101561433257600081815261016960205260408120600481015490546142d191906156e1565b9050801561431f57818484600a81106142ec576142ec6154e5565b602002015152808484600a8110614305576143056154e5565b6020908102919091015101528261431b81615650565b9350505b508061432a81615650565b9150506142a8565b5060006143426065546000190190565b610160546143609190600160a01b90046001600160401b03166156e1565b61436b9060016156b7565b61016b54604080516020810192909252810187905242606082015290915060009060800160408051601f198184030181529190528051602090910120905060006143b761271083615ad8565b90506000805b8581101561445f576000856127108984600a81106143dd576143dd6154e5565b6020020151602001516143f091906156ca565b6143fa919061570a565b9050828410158015614414575061441181846156b7565b84105b1561443f578782600a811061442b5761442b6154e5565b6020020151519a9950505050505050505050565b61444981846156b7565b925050808061445790615650565b9150506143bd565b50505050505050919050565b600054610100900460ff166144925760405162461bcd60e51b815260040161104190615a26565b606761449e838261557b565b5060686144ab828261557b565b5060016065555050565b600054610100900460ff166135565760405162461bcd60e51b815260040161104190615a26565b6144e68282611f75565b61185d576144f3816146fd565b6144fe83602061470f565b60405160200161450f929190615aec565b60408051601f198184030181529082905262461bcd60e51b825261104191600401614cd8565b6001600160a01b0381163b6145a25760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401611041565b600080516020615b7e83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6145da8361485b565b6000825111806145e75750805b15610fdf576125ce838361489b565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106146355772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310614661576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061467f57662386f26fc10000830492506010015b6305f5e1008310614697576305f5e100830492506008015b61271083106146ab57612710830492506004015b606483106146bd576064830492506002015b600a8310610e825760010192915050565b60008183106146ea576000828152602084905260409020612ed2565b6000838152602083905260409020612ed2565b6060610e826001600160a01b03831660145b6060600061471e8360026156ca565b6147299060026156b7565b6001600160401b03811115614740576147406149f9565b6040519080825280601f01601f19166020018201604052801561476a576020820181803683370190505b509050600360fc1b81600081518110614785576147856154e5565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106147b4576147b46154e5565b60200101906001600160f81b031916908160001a90535060006147d88460026156ca565b6147e39060016156b7565b90505b6001811115613ecb576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614817576148176154e5565b1a60f81b82828151811061482d5761482d6154e5565b60200101906001600160f81b031916908160001a90535060049490941c9361485481615ac1565b90506147e6565b61486481614535565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6149035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401611041565b600080846001600160a01b03168460405161491e9190615b61565b600060405180830381855af49150503d8060008114614959576040519150601f19603f3d011682016040523d82523d6000602084013e61495e565b606091505b50915091506113088282604051806060016040528060278152602001615b9e6027913960608315614990575081612ed2565b612ed283838151156149a55781518083602001fd5b8060405162461bcd60e51b81526004016110419190614cd8565b604051806101400160405280600a905b60408051808201909152600080825260208201528152602001906001900390816149cf5790505090565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b0381118282101715614a3257614a326149f9565b60405290565b60405160a081016001600160401b0381118282101715614a3257614a326149f9565b60405161012081016001600160401b0381118282101715614a3257614a326149f9565b604051601f8201601f191681016001600160401b0381118282101715614aa557614aa56149f9565b604052919050565b60006001600160401b03821115614ac657614ac66149f9565b50601f01601f191660200190565b600082601f830112614ae557600080fd5b8135614af8614af382614aad565b614a7d565b818152846020838601011115614b0d57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215614b3d57600080fd5b82356001600160401b0380821115614b5457600080fd5b818501915085601f830112614b6857600080fd5b614b70614a0f565b80610140840188811115614b8357600080fd5b845b81811015614c4757803585811115614b9d5760008081fd5b860160a0818c031215614bb05760008081fd5b614bb8614a38565b813581528882013587811115614bce5760008081fd5b614bda8d828501614ad4565b8a8301525060408083013588811115614bf35760008081fd5b614bff8e828601614ad4565b82840152505060608083013588811115614c195760008081fd5b614c258e828601614ad4565b9183019190915250608091820135918101919091528452928601928601614b85565b509098975050505050505050565b6001600160e01b0319811681146110ca57600080fd5b600060208284031215614c7d57600080fd5b8135612ed281614c55565b60005b83811015614ca3578181015183820152602001614c8b565b50506000910152565b60008151808452614cc4816020860160208601614c88565b601f01601f19169290920160200192915050565b602081526000612ed26020830184614cac565b600060208284031215614cfd57600080fd5b5035919050565b6001600160a01b03811681146110ca57600080fd5b8035612b2781614d04565b60008060408385031215614d3757600080fd5b8235614d4281614d04565b946020939093013593505050565b600060208284031215614d6257600080fd5b8135612ed281614d04565b600080600060608486031215614d8257600080fd5b8335614d8d81614d04565b92506020840135614d9d81614d04565b929592945050506040919091013590565b60008083601f840112614dc057600080fd5b5081356001600160401b03811115614dd757600080fd5b6020830191508360208260051b850101111561137957600080fd5b600080600080600060808688031215614e0a57600080fd5b85359450602086013593506040860135925060608601356001600160401b03811115614e3557600080fd5b614e4188828901614dae565b969995985093965092949392505050565b60008060408385031215614e6557600080fd5b50508035926020909101359150565b80356001600160401b0381168114612b2757600080fd5b803561ffff81168114612b2757600080fd5b80356001600160681b0381168114612b2757600080fd5b803563ffffffff81168114612b2757600080fd5b60006101208284031215614edb57600080fd5b614ee3614a5a565b9050614eee82614e9d565b8152614efc60208301614eb4565b6020820152614f0d60408301614e74565b6040820152614f1e60608301614e74565b6060820152614f2f60808301614e74565b6080820152614f4060a08301614e74565b60a0820152614f5160c08301614e9d565b60c0820152614f6260e08301614d19565b60e082015261010080830135818301525092915050565b6000806000806000806000806000806102408b8d031215614f9957600080fd5b8a356001600160401b0380821115614fb057600080fd5b614fbc8e838f01614ad4565b9b5060208d0135915080821115614fd257600080fd5b614fde8e838f01614ad4565b9a50614fec60408e01614d19565b9950614ffa60608e01614d19565b985061500860808e01614e74565b975061501660a08e01614e74565b965061502460c08e01614e8b565b95506150338e60e08f01614ec8565b94506150426102008e01614d19565b93506102208d013591508082111561505957600080fd5b506150668d828e01614ad4565b9150509295989b9194979a5092959850565b6000806040838503121561508b57600080fd5b82359150602083013561509d81614d04565b809150509250929050565b815115158152610180810160208301516150c6602084018215159052565b506040830151604083015260608301516150eb60608401826001600160401b03169052565b50608083015161510660808401826001600160401b03169052565b5060a083015161512160a08401826001600160401b03169052565b5060c083015161513c60c08401826001600160401b03169052565b5060e0838101519083015261010080840151908301526101208084015190830152610140808401519083015261016092830151929091019190915290565b6000806040838503121561518d57600080fd5b823561519881614d04565b915060208301356001600160401b038111156151b357600080fd5b6151bf85828601614ad4565b9150509250929050565b805182526000602082015160a060208501526151e860a0850182614cac565b9050604083015184820360408601526152018282614cac565b9150506060830151848203606086015261521b8282614cac565b915050608083015160808501528091505092915050565b602081526000612ed260208301846151c9565b80151581146110ca57600080fd5b60006020828403121561526557600080fd5b8135612ed281615245565b85815260a06020820152600061528960a0830187614cac565b828103604084015261529b8187614cac565b905082810360608401526152af8186614cac565b9150508260808301529695505050505050565b60008083601f8401126152d457600080fd5b5081356001600160401b038111156152eb57600080fd5b60208301915083602082850101111561137957600080fd5b6000806020838503121561531657600080fd5b82356001600160401b0381111561532c57600080fd5b615338858286016152c2565b90969095509350505050565b6000806040838503121561535757600080fd5b823561536281614d04565b9150602083013561509d81615245565b6000806000806080858703121561538857600080fd5b843561539381614d04565b935060208501356153a381614d04565b92506040850135915060608501356001600160401b038111156153c557600080fd5b6153d187828801614ad4565b91505092959194509250565b600080602083850312156153f057600080fd5b82356001600160401b0381111561540657600080fd5b61533885828601614dae565b60008060008060008060008060006101208a8c03121561543157600080fd5b61543a8a614e9d565b985061544860208b01614eb4565b975061545660408b01614e74565b965061546460608b01614e74565b955061547260808b01614e74565b945061548060a08b01614e74565b935061548e60c08b01614e9d565b925060e08a013561549e81614d04565b809250506101008a013590509295985092959850929598565b600080604083850312156154ca57600080fd5b82356154d581614d04565b9150602083013561509d81614d04565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061550f57607f821691505b60208210810361552f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610fdf57600081815260208120601f850160051c8101602086101561555c5750805b601f850160051c820191505b8181101561215b57828155600101615568565b81516001600160401b03811115615594576155946149f9565b6155a8816155a284546154fb565b84615535565b602080601f8311600181146155dd57600084156155c55750858301515b600019600386901b1c1916600185901b17855561215b565b600085815260208120601f198616915b8281101561560c578886015182559484019460019091019084016155ed565b508582101561562a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b6000600182016156625761566261563a565b5060010190565b6020808252600090610160830183820185845b600a8110156156ab57601f198785030183526156998483516151c9565b9350918401919084019060010161567c565b50919695505050505050565b80820180821115610e8257610e8261563a565b8082028115828204841417610e8257610e8261563a565b81810381811115610e8257610e8261563a565b634e487b7160e01b600052601260045260246000fd5b600082615719576157196156f4565b500490565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6000602082840312156157c857600080fd5b8151612ed281615245565b6001600160401b038311156157ea576157ea6149f9565b6157fe836157f883546154fb565b83615535565b6000601f841160018114615832576000851561581a5750838201355b600019600387901b1c1916600186901b17835561339f565b600083815260209020601f19861690835b828110156158635786850135825560209485019460019092019101615843565b50868210156158805760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b8183823760009101908152919050565b600081516158e3818560208601614c88565b9290920192915050565b60008085546158fb816154fb565b60018281168015615913576001811461592857615957565b60ff1984168752821515830287019450615957565b8960005260208060002060005b8581101561594e5781548a820152908401908201615935565b50505082870194505b50602f60f81b8452875192506159738382860160208b01614c88565b92820192615986818501602f60f81b9052565b50505061599660028201856158d1565b9695505050505050565b6000602082840312156159b257600080fd5b5051919050565b6000602082840312156159cb57600080fd5b81516001600160401b038111156159e157600080fd5b8201601f810184136159f257600080fd5b8051615a00614af382614aad565b818152856020838501011115615a1557600080fd5b611308826020830160208601614c88565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061599690830184614cac565b600060208284031215615ab657600080fd5b8151612ed281614c55565b600081615ad057615ad061563a565b506000190190565b600082615ae757615ae76156f4565b500690565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351615b24816017850160208801614c88565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351615b55816028840160208801614c88565b01602801949350505050565b60008251615b73818460208701614c88565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e9f4dcef31ffcb069ec495fd81deef4c23dc3039cdde5f436f233de16334563a64736f6c63430008110033000000000000000000000000602d6235286efe1dd69f4151b8b8dab7bbd5e2620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f150d6ce744c1325c53fb183f5d2006811399c6c0000000000000000000000006e0b98ed1b874439c55b7459a67a73d54f907d7e
Deployed Bytecode
0x60806040526004361061038f5760003560e01c80636352211e116101dc578063a22cb46511610102578063d547741f116100a0578063e58306f91161006f578063e58306f914610cb7578063e8a3d48514610cd7578063e985e9c514610cec578063efef39a114610d0c57600080fd5b8063d547741f14610c30578063db0b680d14610c50578063e26bd34314610c63578063e38deb1414610c9757600080fd5b8063bb20d857116100dc578063bb20d85714610b7a578063c87b56dd14610b9a578063d445b97814610bba578063d539139314610bfc57600080fd5b8063a22cb46514610b1a578063b88d4fde14610b3a578063b8ae5a2c14610b5a57600080fd5b80638da5cb5b1161017a5780639d4744b7116101495780639d4744b714610a73578063a0a8e46014610aa4578063a0bcfc7f14610ae5578063a217fddf14610b0557600080fd5b80638da5cb5b14610a0957806391d1485414610a1e57806395d89b4114610a3e5780639bdb89e514610a5357600080fd5b8063729e7cf6116101b6578063729e7cf61461091057806379502c55146109305780637eb55231146109be578063877568cb146109f257600080fd5b80636352211e146108b157806370319970146108d157806370a08231146108f057600080fd5b80632a55205a116102c15780633ccfd60b1161025f5780634b25fbe31161022e5780634b25fbe31461082d5780634f1ef2861461085b57806352d1902d1461086e57806361fea7681461088357600080fd5b80633ccfd60b146107ab57806342842e0e146107c057806342966c68146107e057806347e959151461080057600080fd5b80633474a4a61161029b5780633474a4a61461072957806336568abe1461074b5780633659cfe61461076b5780633bcdcc871461078b57600080fd5b80632a55205a146106aa5780632c6d68a3146106e95780632f2ff15d1461070957600080fd5b806315c6a6001161032e57806323b872dd1161030857806323b872dd14610626578063248a9ca31461064657806324d7806c1461067757806325024a2b1461069757600080fd5b806315c6a600146104e157806318160ddd1461051d5780631d2c0b381461053a57600080fd5b8063081812fc1161036a578063081812fc14610449578063095ea7b31461048157806310a7eb5d146104a157806313af4035146104c157600080fd5b806279fe04146103d057806301ffc9a7146103f257806306fdde031461042757600080fd5b366103cb5760405134815233907f8e47b87b0ef542cdfa1659c551d88bad38aa7f452d2bbb349ab7530dfec8be8f9060200160405180910390a2005b600080fd5b3480156103dc57600080fd5b506103f06103eb366004614b2a565b610d1f565b005b3480156103fe57600080fd5b5061041261040d366004614c6b565b610e26565b60405190151581526020015b60405180910390f35b34801561043357600080fd5b5061043c610e88565b60405161041e9190614cd8565b34801561045557600080fd5b50610469610464366004614ceb565b610f1a565b6040516001600160a01b03909116815260200161041e565b34801561048d57600080fd5b506103f061049c366004614d24565b610f5e565b3480156104ad57600080fd5b506103f06104bc366004614d50565b610fe4565b3480156104cd57600080fd5b506103f06104dc366004614d50565b611099565b3480156104ed57600080fd5b5061050f6104fc366004614ceb565b61016a6020526000908152604090205481565b60405190815260200161041e565b34801561052957600080fd5b50606654606554036000190161050f565b34801561054657600080fd5b5061016254610163546101645461016554610166546105b8946001600160681b0380821695600160681b830463ffffffff1695600160881b9093046001600160401b039081169581831695600160401b8404831695600160801b90940490921693909216916001600160a01b03169089565b604080516001600160681b039a8b16815263ffffffff9990991660208a01526001600160401b039788169089015294861660608801529285166080870152931660a08501529190931660c08301526001600160a01b031660e08201526101008101919091526101200161041e565b34801561063257600080fd5b506103f0610641366004614d6d565b6110cd565b34801561065257600080fd5b5061050f610661366004614ceb565b600090815261012d602052604090206001015490565b34801561068357600080fd5b50610412610692366004614d50565b6110d8565b61050f6106a5366004614df2565b6110e4565b3480156106b657600080fd5b506106ca6106c5366004614e52565b611311565b604080516001600160a01b03909316835260208301919091520161041e565b3480156106f557600080fd5b506103f0610704366004614f79565b611380565b34801561071557600080fd5b506103f0610724366004615078565b61168e565b34801561073557600080fd5b5061073e6116b4565b60405161041e91906150a8565b34801561075757600080fd5b506103f0610766366004615078565b6117e3565b34801561077757600080fd5b506103f0610786366004614d50565b611861565b34801561079757600080fd5b506103f06107a636600461517a565b611926565b3480156107b757600080fd5b506103f0611a18565b3480156107cc57600080fd5b506103f06107db366004614d6d565b611b1d565b3480156107ec57600080fd5b506103f06107fb366004614ceb565b611b38565b34801561080c57600080fd5b5061082061081b366004614ceb565b611b43565b60405161041e9190615232565b34801561083957600080fd5b5061050f610848366004614ceb565b600090815261016a602052604090205490565b6103f061086936600461517a565b611d65565b34801561087a57600080fd5b5061050f611e1a565b34801561088f57600080fd5b5061050f61089e366004614d50565b6101686020526000908152604090205481565b3480156108bd57600080fd5b506104696108cc366004614ceb565b611ecd565b3480156108dd57600080fd5b50610160546001600160a01b0316610469565b3480156108fc57600080fd5b5061050f61090b366004614d50565b611edf565b34801561091c57600080fd5b506103f061092b366004614ceb565b611f2d565b34801561093c57600080fd5b50610160546101615461097d916001600160a01b03808216926001600160401b03600160a01b80850482169461ffff600160e01b9091041693831692041685565b604080516001600160a01b0396871681526001600160401b03958616602082015261ffff90941690840152931660608201529116608082015260a00161041e565b3480156109ca57600080fd5b506104697f000000000000000000000000602d6235286efe1dd69f4151b8b8dab7bbd5e26281565b3480156109fe57600080fd5b5061050f6101675481565b348015610a1557600080fd5b50610469611f5b565b348015610a2a57600080fd5b50610412610a39366004615078565b611f75565b348015610a4a57600080fd5b5061043c611fa1565b348015610a5f57600080fd5b506103f0610a6e366004615253565b611fb0565b348015610a7f57600080fd5b50610a93610a8e366004614ceb565b6122af565b60405161041e959493929190615270565b348015610ab057600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000232916815260200161041e565b348015610af157600080fd5b506103f0610b00366004615303565b612477565b348015610b1157600080fd5b5061050f600081565b348015610b2657600080fd5b506103f0610b35366004615344565b6124f5565b348015610b4657600080fd5b506103f0610b55366004615372565b61258a565b348015610b6657600080fd5b5061050f610b753660046153dd565b6125d4565b348015610b8657600080fd5b5061043c610b95366004615303565b6126e4565b348015610ba657600080fd5b5061043c610bb5366004614ceb565b6127b8565b348015610bc657600080fd5b50610bda610bd5366004614d50565b61281f565b604080518251815260208084015190820152918101519082015260600161041e565b348015610c0857600080fd5b5061050f7ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc981565b348015610c3c57600080fd5b506103f0610c4b366004615078565b6128a0565b61050f610c5e366004614ceb565b6128c6565b348015610c6f57600080fd5b5061050f7f5ebbf78043a2215b522b1366a193ec74dd1f54e441e841a87b9653246a9c49a681565b348015610ca357600080fd5b506103f0610cb2366004615412565b612b2c565b348015610cc357600080fd5b5061050f610cd2366004614d24565b612d32565b348015610ce357600080fd5b5061043c612df2565b348015610cf857600080fd5b50610412610d073660046154b7565b612e65565b61050f610d1a366004614ceb565b612ed9565b610d2a600033611f75565b610d47576040516302bd6bd160e01b815260040160405180910390fd5b60005b600a811015610de1578181600a8110610d6557610d656154e5565b60209081029190910151600083815261016983526040902081518155918101519091906001820190610d97908261557b565b5060408201516002820190610dac908261557b565b5060608201516003820190610dc1908261557b565b506080919091015160049091015580610dd981615650565b915050610d4a565b50336001600160a01b03167f1433261f918df6b640d17001d8490f5841fef00a243201b2f05120ec893ab1de82604051610e1b9190615669565b60405180910390a250565b6000610e3182613093565b80610e4c5750638da5cb5b60e01b6001600160e01b03198316145b80610e67575063152a902d60e11b6001600160e01b03198316145b80610e8257506322f924a760e11b6001600160e01b03198316145b92915050565b606060678054610e97906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec3906154fb565b8015610f105780601f10610ee557610100808354040283529160200191610f10565b820191906000526020600020905b815481529060010190602001808311610ef357829003601f168201915b5050505050905090565b6000610f25826130b8565b610f42576040516333d1c03960e21b815260040160405180910390fd5b506000908152606b60205260409020546001600160a01b031690565b6000610f6982611ecd565b9050806001600160a01b0316836001600160a01b031603610f9d5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b03821614610fd457610fb78133612e65565b610fd4576040516367d9dca160e11b815260040160405180910390fd5b610fdf8383836130f1565b505050565b7f5ebbf78043a2215b522b1366a193ec74dd1f54e441e841a87b9653246a9c49a6611010600033611f75565b15801561102457506110228133611f75565b155b1561104a576040516333ba055f60e21b8152600481018290526024015b60405180910390fd5b61016180546001600160a01b0319166001600160a01b0384169081179091556040513391907f70a7ea5c664ab9c21baf3da59bb2f1e1ca33557b08a0031fab4f17076744995190600090a35050565b6110a4600033611f75565b6110c1576040516302bd6bd160e01b815260040160405180910390fd5b6110ca8161314d565b50565b610fdf8383836131ab565b6000610e828183611f75565b60006110ee6133a6565b61016154610167548791600160a01b90046001600160401b03169061111390836156b7565b11156111325760405163a84bbf1760e01b815260040160405180910390fd5b61113a6133ff565b61115757604051634af69e0d60e11b815260040160405180910390fd5b6111d284848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050610166549150339050604080516001600160a01b03909216602083015281018a9052606081018990526080016040516020818303038152906040528051906020012061343c565b6111ef576040516342db872960e11b815260040160405180910390fd5b6111f987866156ca565b34146112255761120987866156ca565b60405163350e0bcf60e11b815260040161104191815260200190565b3360009081526101686020526040812080548992906112459084906156b7565b9091555050336000908152610168602052604090205486101561127b5760405163a7b32bb160e01b815260040160405180910390fd5b61016780548801905561128e3388613452565b6000876112996134c8565b6112a391906156e1565b90506112b6816112b16134c8565b6134d9565b8588336001600160a01b03167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a90846040516112f391815260200190565b60405180910390a4915050611308600160fb55565b95945050505050565b6101615460009081906001600160a01b031661133d575050610161546001600160a01b03166000611379565b61016154610160546001600160a01b03909116906127109061136a90600160e01b900461ffff16866156ca565b611374919061570a565b915091505b9250929050565b600054610100900460ff16158080156113a05750600054600160ff909116105b806113ba5750303b1580156113ba575060005460ff166001145b61141d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611041565b6000805460ff191660011790558015611440576000805461ff0019166101001790555b61144a8b8b61355d565b61145261358e565b61145a6135b5565b61146560008a6135e4565b61146e8961314d565b61016054611388600160e01b90910461ffff1611156114a45760405163334074c160e11b81526113886004820152602401611041565b83516101628054602087015160408801516001600160681b0394851670ffffffffffffffffffffffffffffffffff1990931692909217600160681b63ffffffff909216919091021767ffffffffffffffff60881b1916600160881b6001600160401b03928316021790915560608601516101638054608089015160a08a01519385166001600160801b031990921691909117600160401b918516919091021767ffffffffffffffff60801b1916600160801b9284169290920291909117905560c086015161016480546cffffffffffffffffffffffffff1916919093161790915560e085015161016580546001600160a01b03199081166001600160a01b039384161790915561010087015161016655610160805461016180548986166001600160f01b0319909316600160a01b8f891681027fffff0000ffffffffffffffff0000000000000000000000000000000000000000169190911793909317600160e01b61ffff8e1602179093556001600160e01b0319909216948b160290911692909217908a1617905561016c61163a838261557b565b508015611681576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b600082815261012d60205260409020600101546116aa816135ee565b610fdf83836135f8565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915260405180610180016040528061172961367f565b151581526020016117386133ff565b15158152610162546001600160681b03811660208301526001600160401b03600160881b820481166040840152610163548082166060850152600160401b810482166080850152600160801b90041660a08301526101665460c083015263ffffffff600160681b9091041660e0820152610100016117b96065546000190190565b815261016754602082015261016054600160a01b90046001600160401b0316604090910152919050565b6001600160a01b03811633146118535760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401611041565b61185d82826136b6565b5050565b6001600160a01b037f0000000000000000000000001dddb8db1031103a9e790fcfe09906b07ea0a6721630036118a95760405162461bcd60e51b81526004016110419061571e565b7f0000000000000000000000001dddb8db1031103a9e790fcfe09906b07ea0a6726001600160a01b03166118db61371e565b6001600160a01b0316146119015760405162461bcd60e51b81526004016110419061576a565b61190a8161373a565b604080516000808252602082019092526110ca91839190613833565b611931600033611f75565b61194e576040516302bd6bd160e01b815260040160405180910390fd5b61016080546001600160a01b0319166001600160a01b0384161790558051156119d0576040516342b53ffd60e11b81526001600160a01b0383169063856a7ffa9061199d908490600401614cd8565b600060405180830381600087803b1580156119b757600080fd5b505af11580156119cb573d6000803e3d6000fd5b505050505b7f046c5d913c35948c3e0e44c3599eb14bf33b73f141fa8bb282b300414998b86833604080516001600160a01b03928316815291851660208301520160405180910390a15050565b611a206133a6565b6101615460405147916000916001600160a01b03909116907f000000000000000000000000000000000000000000000000000000000003345090849084818181858888f193505050503d8060008114611a95576040519150601f19603f3d011682016040523d82523d6000602084013e611a9a565b606091505b5050905080611abc576040516339debd5b60e01b815260040160405180910390fd5b61016154604080518481526000602082018190528183015290516001600160a01b039092169133917f8a95554e4c9dcaaf33f247387f2ee77390780487d3365e3a804788791a1df500919081900360600190a35050611b1b600160fb55565b565b610fdf8383836040518060200160405280600081525061258a565b6110ca81600161399e565b611b756040518060a0016040528060008152602001606081526020016060815260200160608152602001600081525090565b61016960008381526020019081526020016000206040518060a001604052908160008201548152602001600182018054611bae906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054611bda906154fb565b8015611c275780601f10611bfc57610100808354040283529160200191611c27565b820191906000526020600020905b815481529060010190602001808311611c0a57829003601f168201915b50505050508152602001600282018054611c40906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6c906154fb565b8015611cb95780601f10611c8e57610100808354040283529160200191611cb9565b820191906000526020600020905b815481529060010190602001808311611c9c57829003601f168201915b50505050508152602001600382018054611cd2906154fb565b80601f0160208091040260200160405190810160405280929190818152602001828054611cfe906154fb565b8015611d4b5780601f10611d2057610100808354040283529160200191611d4b565b820191906000526020600020905b815481529060010190602001808311611d2e57829003601f168201915b505050505081526020016004820154815250509050919050565b6001600160a01b037f0000000000000000000000001dddb8db1031103a9e790fcfe09906b07ea0a672163003611dad5760405162461bcd60e51b81526004016110419061571e565b7f0000000000000000000000001dddb8db1031103a9e790fcfe09906b07ea0a6726001600160a01b0316611ddf61371e565b6001600160a01b031614611e055760405162461bcd60e51b81526004016110419061576a565b611e0e8261373a565b61185d82826001613833565b6000306001600160a01b037f0000000000000000000000001dddb8db1031103a9e790fcfe09906b07ea0a6721614611eba5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401611041565b50600080516020615b7e83398151915290565b6000611ed882613b72565b5192915050565b60006001600160a01b038216611f08576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152606a60205260409020546001600160401b031690565b611f38600033611f75565b611f55576040516302bd6bd160e01b815260040160405180910390fd5b61016b55565b6000611f7061015f546001600160a01b031690565b905090565b600091825261012d602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060688054610e97906154fb565b611fbb600033611f75565b611fd8576040516302bd6bd160e01b815260040160405180910390fd5b307f0000000000000000000000006e0b98ed1b874439c55b7459a67a73d54f907d7e6001600160a01b031661202057604051635acc4a8760e11b815260040160405180910390fd5b60405163c3c5a54760e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e169063c3c5a547906024016020604051808303816000875af1158015612088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ac91906157b6565b1580156120b65750815b1561216357604051633e9f1edf60e11b81526001600160a01b0382811660048301527f0000000000000000000000006e0b98ed1b874439c55b7459a67a73d54f907d7e811660248301527f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e1690637d3e3dbe906044015b600060405180830381600087803b15801561214757600080fd5b505af115801561215b573d6000803e3d6000fd5b505050505050565b81156121df57604051632cc5350560e21b81526001600160a01b0382811660048301527f0000000000000000000000006e0b98ed1b874439c55b7459a67a73d54f907d7e811660248301527f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e169063b314d4149060440161212d565b60405163034a0dc160e41b81526001600160a01b038281166004830152600060248301527f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e16906334a0dc1090604401600060405180830381600087803b15801561224957600080fd5b505af115801561225d573d6000803e3d6000fd5b5050604051631761612360e11b81526001600160a01b0384811660048301527f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e169250632ec2c246915060240161212d565b61016960205260009081526040902080546001820180549192916122d2906154fb565b80601f01602080910402602001604051908101604052809291908181526020018280546122fe906154fb565b801561234b5780601f106123205761010080835404028352916020019161234b565b820191906000526020600020905b81548152906001019060200180831161232e57829003601f168201915b505050505090806002018054612360906154fb565b80601f016020809104026020016040519081016040528092919081815260200182805461238c906154fb565b80156123d95780601f106123ae576101008083540402835291602001916123d9565b820191906000526020600020905b8154815290600101906020018083116123bc57829003601f168201915b5050505050908060030180546123ee906154fb565b80601f016020809104026020016040519081016040528092919081815260200182805461241a906154fb565b80156124675780601f1061243c57610100808354040283529160200191612467565b820191906000526020600020905b81548152906001019060200180831161244a57829003601f168201915b5050505050908060040154905085565b612482600033611f75565b61249f576040516302bd6bd160e01b815260040160405180910390fd5b61016c6124ad8284836157d3565b50336001600160a01b03167f981198a74a260b9813b2dc38651c0af99e9533d4f4e1dfe42fdd05cf997cd24c83836040516124e9929190615892565b60405180910390a25050565b336001600160a01b0383160361251e5760405163b06307db60e01b815260040160405180910390fd5b336000818152606c602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6125958484846131ab565b6001600160a01b0383163b156125ce576125b184848484613c94565b6125ce576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b60007ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc96126018233611f75565b15801561261557506126138133611f75565b155b15612636576040516333ba055f60e21b815260048101829052602401611041565b610160548390600160a01b90046001600160401b03166126596065546000190190565b61266390836156b7565b111561268257604051630717c51360e41b815260040160405180910390fd5b606554808581015b808310156126d0576126c588888486038181106126a9576126a96154e5565b90506020020160208101906126be9190614d50565b6001613452565b60019092019161268a565b506126d96134c8565b979650505050505050565b60606126f1600033611f75565b61270e576040516302bd6bd160e01b815260040160405180910390fd5b6000807f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e6001600160a01b0316858560405161274b9291906158c1565b6000604051808303816000865af19150503d8060008114612788576040519150601f19603f3d011682016040523d82523d6000602084013e61278d565b606091505b5091509150816127b05760405163097ce21560e21b815260040160405180910390fd5b949350505050565b60606127c3826130b8565b6127e057604051630a14c4b560e41b815260040160405180910390fd5b61016c6127ee306014613d7f565b6127f784613f1a565b604051602001612809939291906158ed565b6040516020818303038152906040529050919050565b61284360405180606001604052806000815260200160008152602001600081525090565b604051806060016040528061285784613fac565b81526001600160a01b0384166000818152610168602081815260408084205482870181905294909352529091019061288e85613fac565b61289891906156e1565b905292915050565b600082815261012d60205260409020600101546128bc816135ee565b610fdf83836136b6565b60006128d06133a6565b61016154610167548391600160a01b90046001600160401b0316906128f590836156b7565b11156129145760405163a84bbf1760e01b815260040160405180910390fd5b61291c6133ff565b61293957604051634af69e0d60e11b815260040160405180910390fd5b610165546000906001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b791906159a0565b905060018110156129db57604051631126b58b60e21b815260040160405180910390fd5b610164546001600160681b03166129f285826156ca565b3414612a145760405163350e0bcf60e11b815260048101829052602401611041565b61016254600160681b900463ffffffff1615801590612a7f575061016254600160681b900463ffffffff166101686000336001600160a01b0316815260208101919091526040016000205486612a6933613fac565b612a7391906156b7565b612a7d91906156e1565b115b15612a9d57604051630882ba5360e21b815260040160405180910390fd5b610167805486019055612ab03386613452565b600085612abb6134c8565b612ac591906156e1565b9050612ad3816112b16134c8565b8186336001600160a01b03167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a9084604051612b1091815260200190565b60405180910390a49350505050612b27600160fb55565b919050565b7f5ebbf78043a2215b522b1366a193ec74dd1f54e441e841a87b9653246a9c49a6612b58600033611f75565b158015612b6c5750612b6a8133611f75565b155b15612b8d576040516333ba055f60e21b815260048101829052602401611041565b8961016260000160006101000a8154816001600160681b0302191690836001600160681b0316021790555088610162600001600d6101000a81548163ffffffff021916908363ffffffff1602179055508761016260000160116101000a8154816001600160401b0302191690836001600160401b031602179055508661016260010160006101000a8154816001600160401b0302191690836001600160401b031602179055508561016260010160086101000a8154816001600160401b0302191690836001600160401b031602179055508461016260010160106101000a8154816001600160401b0302191690836001600160401b0316021790555081610162600401819055508361016260020160006101000a8154816001600160681b0302191690836001600160681b031602179055508261016260030160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550612cf13390565b6001600160a01b03167fc1ff5e4744ac8dd2b8027a10e3723b165975297501c71c4e7dcb8796d96375db60405160405180910390a250505050505050505050565b60007ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc9612d5f8233611f75565b158015612d735750612d718133611f75565b155b15612d94576040516333ba055f60e21b815260048101829052602401611041565b610160548390600160a01b90046001600160401b0316612db76065546000190190565b612dc190836156b7565b1115612de057604051630717c51360e41b815260040160405180910390fd5b612dea8585613452565b6113086134c8565b610160546040805163e8a3d48560e01b815290516060926001600160a01b03169163e8a3d4859160048083019260009291908290030181865afa158015612e3d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f7091908101906159b9565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612ea857506001610e82565b6001600160a01b038084166000908152606c602090815260408083209386168352929052205460ff165b9392505050565b6000612ee36133a6565b610160548290600160a01b90046001600160401b0316612f066065546000190190565b612f1090836156b7565b1115612f2f57604051630717c51360e41b815260040160405180910390fd5b612f3761367f565b612f545760405163f12dcc7f60e01b815260040160405180910390fd5b610162546001600160681b0316612f6b84826156ca565b3414612f7b5761120984826156ca565b61016254600160681b900463ffffffff1615801590612fe6575061016254600160681b900463ffffffff166101686000336001600160a01b0316815260208101919091526040016000205485612fd033613fac565b612fda91906156b7565b612fe491906156e1565b115b1561300457604051630882ba5360e21b815260040160405180910390fd5b61300e3385613452565b6000846130196134c8565b61302391906156e1565b9050613031816112b16134c8565b8185336001600160a01b03167f4e26b0356a15833a75d497ecc40ebbb716b99466ed0dba9454f1fff451e25a908460405161306e91815260200190565b60405180910390a492505050612b27600160fb55565b6001600160a01b03163b151590565b60006001600160e01b03198216637965db0b60e01b1480610e825750610e8282613fd7565b6000816001111580156130cc575060655482105b8015610e82575050600090815260696020526040902054600160e01b900460ff161590565b6000828152606b602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b61015f546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a361015f80546001600160a01b0319166001600160a01b0392909216919091179055565b60006131b682613b72565b9050836001600160a01b031681600001516001600160a01b0316146131ed5760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b038616148061320b575061320b8533612e65565b8061322657503361321b84610f1a565b6001600160a01b0316145b90508061324657604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03841661326d57604051633a954ecd60e21b815260040160405180910390fd5b61327a8585856001614027565b613286600084876130f1565b6001600160a01b038581166000908152606a60209081526040808320805467ffffffffffffffff198082166001600160401b0392831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652606990945282852080546001600160e01b031916909417600160a01b4290921691909102178355870180845292208054919390911661335a57606554821461335a57805460208601516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038a16171781555b50505082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b5050505050565b600260fb54036133f85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611041565b600260fb55565b6101635460009042600160401b9091046001600160401b031611801590611f705750506101635442600160801b9091046001600160401b03161190565b600082613449858461411c565b14949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000008821161348157816134a3565b7f00000000000000000000000000000000000000000000000000000000000000085b90506134af8382614169565b6134b981836156e1565b91505060008111613452575050565b60006001606554611f7091906156e1565b60006134e68360016156b7565b90505b6134f16134c8565b6134fc9060016156b7565b811015610fdf57600061350e8261429a565b60008181526101696020526040812060040180549293509061352f83615650565b9091555050600082815261016a60205260409020558061354e81615650565b9150506134e9565b600160fb55565b600054610100900460ff166135845760405162461bcd60e51b815260040161104190615a26565b61185d828261446b565b600054610100900460ff16611b1b5760405162461bcd60e51b815260040161104190615a26565b600054610100900460ff166135dc5760405162461bcd60e51b815260040161104190615a26565b611b1b6144b5565b61185d82826135f8565b6110ca81336144dc565b6136028282611f75565b61185d57600082815261012d602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561363b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6101625460009042600160881b9091046001600160401b031611801590611f7057505061016354426001600160401b039091161190565b6136c08282611f75565b1561185d57600082815261012d602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600080516020615b7e833981519152546001600160a01b031690565b613745600033611f75565b613762576040516302bd6bd160e01b815260040160405180910390fd5b7f000000000000000000000000f150d6ce744c1325c53fb183f5d2006811399c6c6001600160a01b031663739958338261379a61371e565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af11580156137e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380b91906157b6565b6110ca57604051633bcafdf560e21b81526001600160a01b0382166004820152602401611041565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561386657610fdf83614535565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156138c0575060408051601f3d908101601f191682019092526138bd918101906159a0565b60015b6139235760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401611041565b600080516020615b7e83398151915281146139925760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401611041565b50610fdf8383836145d1565b60006139a983613b72565b80519091508215613a0f576000336001600160a01b03831614806139d257506139d28233612e65565b806139ed5750336139e286610f1a565b6001600160a01b0316145b905080613a0d57604051632ce44b5f60e11b815260040160405180910390fd5b505b613a1d816000866001614027565b613a29600085836130f1565b6001600160a01b038082166000818152606a602090815260408083208054600160801b6000196001600160401b0380841691909101811667ffffffffffffffff198416811783900482166001908101831690930277ffffffffffffffff0000000000000000ffffffffffffffff19909416179290921783558b86526069909452828520805460ff60e01b1942909316600160a01b026001600160e01b03199091169097179690961716600160e01b178555918901808452922080549194909116613b27576065548214613b2757805460208701516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038716171781555b5050604051869250600091506001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a450506066805460010190555050565b60408051606081018252600080825260208201819052918101919091528180600111613c7b57606554811015613c7b57600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff16151591810182905290613c795780516001600160a01b031615613c10579392505050565b5060001901600081815260696020908152604091829020825160608101845290546001600160a01b038116808352600160a01b82046001600160401b031693830193909352600160e01b900460ff1615159281019290925215613c74579392505050565b613c10565b505b604051636f96cda160e11b815260040160405180910390fd5b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290613cc9903390899088908890600401615a71565b6020604051808303816000875af1925050508015613d04575060408051601f3d908101601f19168201909252613d0191810190615aa4565b60015b613d62573d808015613d32576040519150601f19603f3d011682016040523d82523d6000602084013e613d37565b606091505b508051600003613d5a576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b60606000613d8e8360026156ca565b613d999060026156b7565b6001600160401b03811115613db057613db06149f9565b6040519080825280601f01601f191660200182016040528015613dda576020820181803683370190505b509050600360fc1b81600081518110613df557613df56154e5565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613e2457613e246154e5565b60200101906001600160f81b031916908160001a9053506000613e488460026156ca565b613e539060016156b7565b90505b6001811115613ecb576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613e8757613e876154e5565b1a60f81b828281518110613e9d57613e9d6154e5565b60200101906001600160f81b031916908160001a90535060049490941c93613ec481615ac1565b9050613e56565b508315612ed25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401611041565b60606000613f27836145f6565b60010190506000816001600160401b03811115613f4657613f466149f9565b6040519080825280601f01601f191660200182016040528015613f70576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084613f7a57509392505050565b6001600160a01b03166000908152606a6020526040902054600160401b90046001600160401b031690565b60006001600160e01b031982166380ac58cd60e01b148061400857506001600160e01b03198216635b5e139f60e01b145b80610e8257506301ffc9a760e01b6001600160e01b0319831614610e82565b6001600160a01b038416331480159061406a575060007f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e6001600160a01b03163b115b156125ce57604051633185c44d60e21b81523060048201523360248201527f000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e6001600160a01b03169063c617113490604401602060405180830381865afa1580156140d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140fd91906157b6565b6125ce57604051633b79c77360e21b8152336004820152602401611041565b600081815b84518110156141615761414d82868381518110614140576141406154e5565b60200260200101516146ce565b91508061415981615650565b915050614121565b509392505050565b6065546001600160a01b03831661419257604051622e076360e81b815260040160405180910390fd5b816000036141b35760405163b562e8dd60e01b815260040160405180910390fd5b6141c06000848385614027565b6001600160a01b0383166000818152606a6020908152604080832080546001600160801b031981166001600160401b038083168a018116918217600160401b67ffffffffffffffff1990941690921783900481168a01811690920217909155858452606990925290912080546001600160e01b031916909217600160a01b4290921691909102179055808083015b6040516001830192906001600160a01b038716906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a480821061424e5750606555505050565b60006142a46149bf565b6000805b600a81101561433257600081815261016960205260408120600481015490546142d191906156e1565b9050801561431f57818484600a81106142ec576142ec6154e5565b602002015152808484600a8110614305576143056154e5565b6020908102919091015101528261431b81615650565b9350505b508061432a81615650565b9150506142a8565b5060006143426065546000190190565b610160546143609190600160a01b90046001600160401b03166156e1565b61436b9060016156b7565b61016b54604080516020810192909252810187905242606082015290915060009060800160408051601f198184030181529190528051602090910120905060006143b761271083615ad8565b90506000805b8581101561445f576000856127108984600a81106143dd576143dd6154e5565b6020020151602001516143f091906156ca565b6143fa919061570a565b9050828410158015614414575061441181846156b7565b84105b1561443f578782600a811061442b5761442b6154e5565b6020020151519a9950505050505050505050565b61444981846156b7565b925050808061445790615650565b9150506143bd565b50505050505050919050565b600054610100900460ff166144925760405162461bcd60e51b815260040161104190615a26565b606761449e838261557b565b5060686144ab828261557b565b5060016065555050565b600054610100900460ff166135565760405162461bcd60e51b815260040161104190615a26565b6144e68282611f75565b61185d576144f3816146fd565b6144fe83602061470f565b60405160200161450f929190615aec565b60408051601f198184030181529082905262461bcd60e51b825261104191600401614cd8565b6001600160a01b0381163b6145a25760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401611041565b600080516020615b7e83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6145da8361485b565b6000825111806145e75750805b15610fdf576125ce838361489b565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106146355772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310614661576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061467f57662386f26fc10000830492506010015b6305f5e1008310614697576305f5e100830492506008015b61271083106146ab57612710830492506004015b606483106146bd576064830492506002015b600a8310610e825760010192915050565b60008183106146ea576000828152602084905260409020612ed2565b6000838152602083905260409020612ed2565b6060610e826001600160a01b03831660145b6060600061471e8360026156ca565b6147299060026156b7565b6001600160401b03811115614740576147406149f9565b6040519080825280601f01601f19166020018201604052801561476a576020820181803683370190505b509050600360fc1b81600081518110614785576147856154e5565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106147b4576147b46154e5565b60200101906001600160f81b031916908160001a90535060006147d88460026156ca565b6147e39060016156b7565b90505b6001811115613ecb576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614817576148176154e5565b1a60f81b82828151811061482d5761482d6154e5565b60200101906001600160f81b031916908160001a90535060049490941c9361485481615ac1565b90506147e6565b61486481614535565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6149035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401611041565b600080846001600160a01b03168460405161491e9190615b61565b600060405180830381855af49150503d8060008114614959576040519150601f19603f3d011682016040523d82523d6000602084013e61495e565b606091505b50915091506113088282604051806060016040528060278152602001615b9e6027913960608315614990575081612ed2565b612ed283838151156149a55781518083602001fd5b8060405162461bcd60e51b81526004016110419190614cd8565b604051806101400160405280600a905b60408051808201909152600080825260208201528152602001906001900390816149cf5790505090565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b0381118282101715614a3257614a326149f9565b60405290565b60405160a081016001600160401b0381118282101715614a3257614a326149f9565b60405161012081016001600160401b0381118282101715614a3257614a326149f9565b604051601f8201601f191681016001600160401b0381118282101715614aa557614aa56149f9565b604052919050565b60006001600160401b03821115614ac657614ac66149f9565b50601f01601f191660200190565b600082601f830112614ae557600080fd5b8135614af8614af382614aad565b614a7d565b818152846020838601011115614b0d57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215614b3d57600080fd5b82356001600160401b0380821115614b5457600080fd5b818501915085601f830112614b6857600080fd5b614b70614a0f565b80610140840188811115614b8357600080fd5b845b81811015614c4757803585811115614b9d5760008081fd5b860160a0818c031215614bb05760008081fd5b614bb8614a38565b813581528882013587811115614bce5760008081fd5b614bda8d828501614ad4565b8a8301525060408083013588811115614bf35760008081fd5b614bff8e828601614ad4565b82840152505060608083013588811115614c195760008081fd5b614c258e828601614ad4565b9183019190915250608091820135918101919091528452928601928601614b85565b509098975050505050505050565b6001600160e01b0319811681146110ca57600080fd5b600060208284031215614c7d57600080fd5b8135612ed281614c55565b60005b83811015614ca3578181015183820152602001614c8b565b50506000910152565b60008151808452614cc4816020860160208601614c88565b601f01601f19169290920160200192915050565b602081526000612ed26020830184614cac565b600060208284031215614cfd57600080fd5b5035919050565b6001600160a01b03811681146110ca57600080fd5b8035612b2781614d04565b60008060408385031215614d3757600080fd5b8235614d4281614d04565b946020939093013593505050565b600060208284031215614d6257600080fd5b8135612ed281614d04565b600080600060608486031215614d8257600080fd5b8335614d8d81614d04565b92506020840135614d9d81614d04565b929592945050506040919091013590565b60008083601f840112614dc057600080fd5b5081356001600160401b03811115614dd757600080fd5b6020830191508360208260051b850101111561137957600080fd5b600080600080600060808688031215614e0a57600080fd5b85359450602086013593506040860135925060608601356001600160401b03811115614e3557600080fd5b614e4188828901614dae565b969995985093965092949392505050565b60008060408385031215614e6557600080fd5b50508035926020909101359150565b80356001600160401b0381168114612b2757600080fd5b803561ffff81168114612b2757600080fd5b80356001600160681b0381168114612b2757600080fd5b803563ffffffff81168114612b2757600080fd5b60006101208284031215614edb57600080fd5b614ee3614a5a565b9050614eee82614e9d565b8152614efc60208301614eb4565b6020820152614f0d60408301614e74565b6040820152614f1e60608301614e74565b6060820152614f2f60808301614e74565b6080820152614f4060a08301614e74565b60a0820152614f5160c08301614e9d565b60c0820152614f6260e08301614d19565b60e082015261010080830135818301525092915050565b6000806000806000806000806000806102408b8d031215614f9957600080fd5b8a356001600160401b0380821115614fb057600080fd5b614fbc8e838f01614ad4565b9b5060208d0135915080821115614fd257600080fd5b614fde8e838f01614ad4565b9a50614fec60408e01614d19565b9950614ffa60608e01614d19565b985061500860808e01614e74565b975061501660a08e01614e74565b965061502460c08e01614e8b565b95506150338e60e08f01614ec8565b94506150426102008e01614d19565b93506102208d013591508082111561505957600080fd5b506150668d828e01614ad4565b9150509295989b9194979a5092959850565b6000806040838503121561508b57600080fd5b82359150602083013561509d81614d04565b809150509250929050565b815115158152610180810160208301516150c6602084018215159052565b506040830151604083015260608301516150eb60608401826001600160401b03169052565b50608083015161510660808401826001600160401b03169052565b5060a083015161512160a08401826001600160401b03169052565b5060c083015161513c60c08401826001600160401b03169052565b5060e0838101519083015261010080840151908301526101208084015190830152610140808401519083015261016092830151929091019190915290565b6000806040838503121561518d57600080fd5b823561519881614d04565b915060208301356001600160401b038111156151b357600080fd5b6151bf85828601614ad4565b9150509250929050565b805182526000602082015160a060208501526151e860a0850182614cac565b9050604083015184820360408601526152018282614cac565b9150506060830151848203606086015261521b8282614cac565b915050608083015160808501528091505092915050565b602081526000612ed260208301846151c9565b80151581146110ca57600080fd5b60006020828403121561526557600080fd5b8135612ed281615245565b85815260a06020820152600061528960a0830187614cac565b828103604084015261529b8187614cac565b905082810360608401526152af8186614cac565b9150508260808301529695505050505050565b60008083601f8401126152d457600080fd5b5081356001600160401b038111156152eb57600080fd5b60208301915083602082850101111561137957600080fd5b6000806020838503121561531657600080fd5b82356001600160401b0381111561532c57600080fd5b615338858286016152c2565b90969095509350505050565b6000806040838503121561535757600080fd5b823561536281614d04565b9150602083013561509d81615245565b6000806000806080858703121561538857600080fd5b843561539381614d04565b935060208501356153a381614d04565b92506040850135915060608501356001600160401b038111156153c557600080fd5b6153d187828801614ad4565b91505092959194509250565b600080602083850312156153f057600080fd5b82356001600160401b0381111561540657600080fd5b61533885828601614dae565b60008060008060008060008060006101208a8c03121561543157600080fd5b61543a8a614e9d565b985061544860208b01614eb4565b975061545660408b01614e74565b965061546460608b01614e74565b955061547260808b01614e74565b945061548060a08b01614e74565b935061548e60c08b01614e9d565b925060e08a013561549e81614d04565b809250506101008a013590509295985092959850929598565b600080604083850312156154ca57600080fd5b82356154d581614d04565b9150602083013561509d81614d04565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061550f57607f821691505b60208210810361552f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610fdf57600081815260208120601f850160051c8101602086101561555c5750805b601f850160051c820191505b8181101561215b57828155600101615568565b81516001600160401b03811115615594576155946149f9565b6155a8816155a284546154fb565b84615535565b602080601f8311600181146155dd57600084156155c55750858301515b600019600386901b1c1916600185901b17855561215b565b600085815260208120601f198616915b8281101561560c578886015182559484019460019091019084016155ed565b508582101561562a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b6000600182016156625761566261563a565b5060010190565b6020808252600090610160830183820185845b600a8110156156ab57601f198785030183526156998483516151c9565b9350918401919084019060010161567c565b50919695505050505050565b80820180821115610e8257610e8261563a565b8082028115828204841417610e8257610e8261563a565b81810381811115610e8257610e8261563a565b634e487b7160e01b600052601260045260246000fd5b600082615719576157196156f4565b500490565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6000602082840312156157c857600080fd5b8151612ed281615245565b6001600160401b038311156157ea576157ea6149f9565b6157fe836157f883546154fb565b83615535565b6000601f841160018114615832576000851561581a5750838201355b600019600387901b1c1916600186901b17835561339f565b600083815260209020601f19861690835b828110156158635786850135825560209485019460019092019101615843565b50868210156158805760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b8183823760009101908152919050565b600081516158e3818560208601614c88565b9290920192915050565b60008085546158fb816154fb565b60018281168015615913576001811461592857615957565b60ff1984168752821515830287019450615957565b8960005260208060002060005b8581101561594e5781548a820152908401908201615935565b50505082870194505b50602f60f81b8452875192506159738382860160208b01614c88565b92820192615986818501602f60f81b9052565b50505061599660028201856158d1565b9695505050505050565b6000602082840312156159b257600080fd5b5051919050565b6000602082840312156159cb57600080fd5b81516001600160401b038111156159e157600080fd5b8201601f810184136159f257600080fd5b8051615a00614af382614aad565b818152856020838501011115615a1557600080fd5b611308826020830160208601614c88565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061599690830184614cac565b600060208284031215615ab657600080fd5b8151612ed281614c55565b600081615ad057615ad061563a565b506000190190565b600082615ae757615ae76156f4565b500690565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351615b24816017850160208801614c88565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351615b55816028840160208801614c88565b01602801949350505050565b60008251615b73818460208701614c88565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e9f4dcef31ffcb069ec495fd81deef4c23dc3039cdde5f436f233de16334563a64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000602d6235286efe1dd69f4151b8b8dab7bbd5e2620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f150d6ce744c1325c53fb183f5d2006811399c6c0000000000000000000000006e0b98ed1b874439c55b7459a67a73d54f907d7e
-----Decoded View---------------
Arg [0] : _kitsFeeManager (address): 0x602d6235286eFE1dD69F4151B8b8dAb7bbd5E262
Arg [1] : _kitsERC721TransferHelper (address): 0x0000000000000000000000000000000000000000
Arg [2] : _factoryUpgradeGate (address): 0xf150D6ce744c1325C53FB183f5d2006811399C6c
Arg [3] : _marketFilterDAOAddress (address): 0x6E0B98eD1B874439c55b7459a67A73d54f907d7e
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000602d6235286efe1dd69f4151b8b8dab7bbd5e262
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 000000000000000000000000f150d6ce744c1325c53fb183f5d2006811399c6c
Arg [3] : 0000000000000000000000006e0b98ed1b874439c55b7459a67a73d54f907d7e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.