Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,551 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 19817909 | 199 days ago | IN | 0 ETH | 0.00018802 | ||||
Withdraw | 19817906 | 199 days ago | IN | 0 ETH | 0.00023199 | ||||
Signed Mint | 18684438 | 358 days ago | IN | 0.03 ETH | 0.00365488 | ||||
Reserved Mint | 18113878 | 438 days ago | IN | 0 ETH | 0.00521854 | ||||
Signed Mint | 18093059 | 441 days ago | IN | 0.03 ETH | 0.00343045 | ||||
Signed Mint | 17965818 | 459 days ago | IN | 0.03 ETH | 0.0032254 | ||||
Signed Mint | 17519583 | 522 days ago | IN | 0.03 ETH | 0.00158876 | ||||
Withdraw | 17484078 | 527 days ago | IN | 0 ETH | 0.00074565 | ||||
Signed Mint | 17444926 | 532 days ago | IN | 0.03 ETH | 0.00220043 | ||||
Signed Mint | 17438574 | 533 days ago | IN | 0.03 ETH | 0.00246427 | ||||
Signed Mint | 17438152 | 533 days ago | IN | 0.03 ETH | 0.00254723 | ||||
Signed Mint | 17437870 | 533 days ago | IN | 0.03 ETH | 0.00261107 | ||||
Signed Mint | 17418712 | 536 days ago | IN | 0.03 ETH | 0.00257543 | ||||
Signed Mint | 17346169 | 546 days ago | IN | 0.03 ETH | 0.00347039 | ||||
Signed Mint | 17345823 | 546 days ago | IN | 0.03 ETH | 0.00411709 | ||||
Signed Mint | 17345612 | 546 days ago | IN | 0.03 ETH | 0.00329631 | ||||
Signed Mint | 17345334 | 546 days ago | IN | 0.03 ETH | 0.00331001 | ||||
Signed Mint | 17345155 | 546 days ago | IN | 0.03 ETH | 0.00371292 | ||||
Signed Mint | 17344791 | 546 days ago | IN | 0.03 ETH | 0.00483187 | ||||
Signed Mint | 17344748 | 546 days ago | IN | 0.03 ETH | 0.0044063 | ||||
Signed Mint | 17343866 | 546 days ago | IN | 0.03 ETH | 0.00399912 | ||||
Signed Mint | 17343775 | 546 days ago | IN | 0.03 ETH | 0.00474748 | ||||
Signed Mint | 17342365 | 546 days ago | IN | 0.03 ETH | 0.00340346 | ||||
Reserved Mint | 17336842 | 547 days ago | IN | 0 ETH | 0.00360504 | ||||
Signed Mint | 17287819 | 554 days ago | IN | 0.03 ETH | 0.00732954 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19817906 | 199 days ago | 0.18 ETH | ||||
17500906 | 524 days ago | 0.03 ETH | ||||
17500906 | 524 days ago | 0.03 ETH | ||||
17484078 | 527 days ago | 3.66 ETH | ||||
17381704 | 541 days ago | 0.03 ETH | ||||
17381704 | 541 days ago | 0.03 ETH | ||||
17366972 | 543 days ago | 0.03 ETH | ||||
17366972 | 543 days ago | 0.03 ETH | ||||
17366972 | 543 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17362998 | 544 days ago | 0.03 ETH | ||||
17353473 | 545 days ago | 0.03 ETH | ||||
17353473 | 545 days ago | 0.03 ETH | ||||
17353473 | 545 days ago | 0.03 ETH | ||||
17353473 | 545 days ago | 0.03 ETH |
Loading...
Loading
Contract Name:
TributeBrand
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /* ╭━━━╮╱╱╱╱╱╱╱╭╮╭━╮╱╭╮╱╱╱╱╭╮╱╱╱╱╭━━━╮ ┃╭━╮┃╱╱╱╱╱╱╱┃┃┃┃╰╮┃┃╱╱╱╱┃┃╱╱╱╱┃╭━╮┃ ┃╰━━┳━━┳━╮╭━╯┃┃╭╮╰╯┣╮╭┳━╯┣━━┳━┻┫╭╯┃ ╰━━╮┃┃━┫╭╮┫╭╮┃┃┃╰╮┃┃┃┃┃╭╮┃┃━┫━━┫┃╭╯ ┃╰━╯┃┃━┫┃┃┃╰╯┃┃┃╱┃┃┃╰╯┃╰╯┃┃━╋━━┃╭╮ ╰━━━┻━━┻╯╰┻━━╯╰╯╱╰━┻━━┻━━┻━━┻━━╯╰╯ */ import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import {LicenseVersion, CantBeEvil} from "@a16z/contracts/licenses/CantBeEvil.sol"; import "./DropNFT.sol"; // ============================================================= // FRONTEND API // ============================================================= interface ITributeBrand { function signedMint( address to, bytes32 uuid, bytes32 mintData, uint256 expiresAt, uint256 price, bytes calldata signature ) external payable; function signedPayment( bytes32 uuid, uint256 expiresAt, uint256 price, bytes calldata signature ) external payable; /** * @dev See comment in DropNFT.sol over the function tokensOfOwner for info * on how to enumerate all the tokens in all the drops owned by some user. * */ function currentDrop() external view returns (DropNFT); /** * @dev This function (drops) exists, its just commented out because its created internally * by the compiler (due to there existing a state variable with the same and public visibility). * * See comment in DropNFT.sol over the function tokensOfOwner for info on how to use this function * to enumerate all the tokens in all the drops owned by some specific user (it has to be done off-chain). */ // function drops() public returns(DropNFT); } /// @title Tribute Brand /// @author Tribute Brand LLC /// @notice This contract serves as interface and factory to all Tribute Brand blockchain processes. contract TributeBrand is EIP712, ReentrancyGuard, Ownable, ITributeBrand, CantBeEvil(LicenseVersion.PUBLIC) { error ActionAlreadyUsed(); error BadSignature(); error SignatureExpired(); error InvalidPayment(uint256 required, uint256 received); // ============================================================= // EVENTS // ============================================================= event TokenMinted( address indexed receiver, address indexed dropNFT, uint256 tokenId, bytes32 indexed mintData ); // if quantity == 1, startTokenId is the only tokenId. event ReservedTokensMinted( address indexed receiver, address indexed dropNFT, uint256 indexed startTokenId, uint256 quantity ); event PaymentReceived( bytes32 indexed uuid, address indexed from, uint256 amount ); // ============================================================= // TYPES / UTILITY // ============================================================= address private constant VERIFIER_ADDRESS = 0x2C1c452924C085566d764e3186a886A7eAA23229; bytes32 public constant SIGNED_ACTION_TYPEHASH = keccak256( "SignedAction(bytes32 uuid,bytes32 data,uint256 expiresAt,uint256 price)" ); struct SignedAction { bytes32 uuid; bytes32 data; uint256 expiresAt; uint256 price; } // Utility function for backend to create digest for a signed action. // A digest can only be used once, so it can be seen as the UUID for the action. // Both signed mint and payment use this. // Mint uses data to specify tokenId and dropId. Payment uses data to specify payment uuid on backend. function actionDigest( bytes32 uuid, bytes32 data, uint256 expiresAt, uint256 price ) public view returns (bytes32 digest) { digest = _hashTypedDataV4( keccak256( abi.encode(SIGNED_ACTION_TYPEHASH, uuid, data, expiresAt, price) ) ); } // ============================================================= // CONSTRUCTOR // ============================================================= constructor( string memory name, string memory version ) EIP712(name, version) {} // ============================================================= // DROPS // ============================================================= DropNFT[] public drops; // Adds the given drop (note: it appears on opensea after the first token is minted). function publishDrop(address dropNFTAddress) external onlyOwner { DropNFT dropNFT = DropNFT(dropNFTAddress); drops.push(dropNFT); dropNFT.requestEntropy(); } function revealDrop(string calldata realBaseTokenURI) external onlyOwner { currentDrop().reveal(realBaseTokenURI); } function currentDrop() public view returns (DropNFT) { require(drops.length > 0, "No drops have been created yet."); return drops[drops.length - 1]; } // ============================================================= // PAYMENTS // ============================================================= function signedPayment( bytes32 uuid, uint256 expiresAt, uint256 price, bytes calldata signature ) external payable verifySignature(uuid, bytes32(0), expiresAt, price, signature) { emit PaymentReceived(uuid, msg.sender, msg.value); } // ============================================================= // MINTING // ============================================================= // mintData is 32 bytes long and currently encodes drop id. // drop id = 0 means use currentDrop, so leave it empty to mint on the latest. function signedMint( address to, bytes32 uuid, bytes32 mintData, uint256 expiresAt, uint256 price, bytes calldata signature ) external payable verifySignature(uuid, mintData, expiresAt, price, signature) { uint256 dropId = uint256(mintData); address receiver = to == address(0) ? msg.sender : to; DropNFT drop = dropId == 0 ? currentDrop() : drops[dropId]; uint256 tokenId = drop.mint(receiver, 0); emit TokenMinted(receiver, address(drop), tokenId, mintData); } function reservedMint( address to, uint256 dropId, // 0 means current drop uint256 quantity ) external onlyOwner { DropNFT drop = dropId == 0 ? currentDrop() : drops[dropId]; uint256 startTokenId = drop.reservedMint(to, quantity, 0); emit ReservedTokensMinted(to, address(drop), startTokenId, quantity); } // ============================================================= // OTHER // ============================================================= function checkClaimEligibility( uint256 quantity ) external view returns (string memory) { if (drops.length == 0) { return "not live yet"; } else { DropNFT drop = drops[drops.length - 1]; return drop.checkClaimEligibility(quantity); } } // keep track of used action signatures mapping(bytes32 => bool) private _actionDigestUsed; modifier verifySignature( bytes32 uuid, bytes32 data, uint256 expiresAt, uint256 price, bytes calldata signature ) { if (price != msg.value) revert InvalidPayment(price, msg.value); if (block.timestamp > expiresAt) revert SignatureExpired(); bytes32 digest = actionDigest(uuid, data, expiresAt, price); if (_actionDigestUsed[digest]) revert ActionAlreadyUsed(); if (VERIFIER_ADDRESS != ECDSA.recover(digest, signature)) revert BadSignature(); _actionDigestUsed[digest] = true; _; } function withdraw(address _receiver) public onlyOwner { (bool os, ) = payable(_receiver).call{value: address(this).balance}(""); require(os, "Withdraw unsuccesful"); } }
// SPDX-License-Identifier: MIT // a16z Contracts v0.0.1 (CantBeEvil.sol) pragma solidity ^0.8.13; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "./ICantBeEvil.sol"; enum LicenseVersion { PUBLIC, EXCLUSIVE, COMMERCIAL, COMMERCIAL_NO_HATE, PERSONAL, PERSONAL_NO_HATE } contract CantBeEvil is ERC165, ICantBeEvil { using Strings for uint; string internal constant _BASE_LICENSE_URI = "ar://zmc1WTspIhFyVY82bwfAIcIExLFH5lUcHHUN0wXg4W8/"; LicenseVersion internal licenseVersion; constructor(LicenseVersion _licenseVersion) { licenseVersion = _licenseVersion; } function getLicenseURI() public view returns (string memory) { return string.concat(_BASE_LICENSE_URI, uint(licenseVersion).toString()); } function getLicenseName() public view returns (string memory) { return _getLicenseVersionKeyByValue(licenseVersion); } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165) returns (bool) { return interfaceId == type(ICantBeEvil).interfaceId || super.supportsInterface(interfaceId); } function _getLicenseVersionKeyByValue(LicenseVersion _licenseVersion) internal pure returns (string memory) { require(uint8(_licenseVersion) <= 6); if (LicenseVersion.PUBLIC == _licenseVersion) return "PUBLIC"; if (LicenseVersion.EXCLUSIVE == _licenseVersion) return "EXCLUSIVE"; if (LicenseVersion.COMMERCIAL == _licenseVersion) return "COMMERCIAL"; if (LicenseVersion.COMMERCIAL_NO_HATE == _licenseVersion) return "COMMERCIAL_NO_HATE"; if (LicenseVersion.PERSONAL == _licenseVersion) return "PERSONAL"; else return "PERSONAL_NO_HATE"; } }
// SPDX-License-Identifier: MIT // a16z Contracts v0.0.1 (ICantBeEvil.sol) pragma solidity ^0.8.13; interface ICantBeEvil { function getLicenseURI() external view returns (string memory); function getLicenseName() external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256, /* firstTokenId */ uint256 batchSize ) internal virtual { if (batchSize > 1) { if (from != address(0)) { _balances[from] -= batchSize; } if (to != address(0)) { _balances[to] += batchSize; } } } /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: 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 (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Royalty.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../common/ERC2981.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment * information. * * Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually for * specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC721Royalty is ERC2981, ERC721 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) { return super.supportsInterface(interfaceId); } /** * @dev See {ERC721-_burn}. This override additionally clears the royalty information for the token. */ function _burn(uint256 tokenId) internal virtual override { super._burn(tokenId); _resetTokenRoyalty(tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol) pragma solidity ^0.8.0; import "../../interfaces/IERC2981.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981 */ function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) { RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId]; if (royalty.receiver == address(0)) { royalty = _defaultRoyaltyInfo; } uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator(); return (royalty.receiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: invalid receiver"); _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty( uint256 tokenId, address receiver, uint96 feeNumerator ) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: Invalid parameters"); _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return 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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(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; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; // EIP-712 is Final as of 2022-08-11. This file is deprecated. import "./EIP712.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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 pragma solidity ^0.8.13; import {OperatorFilterer} from "./OperatorFilterer.sol"; /** * @title DefaultOperatorFilterer * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription. */ abstract contract DefaultOperatorFilterer is OperatorFilterer { address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; /** * @title OperatorFilterer * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another * registrant's entries in the OperatorFilterRegistry. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. */ abstract contract OperatorFilterer { error OperatorNotAllowed(address operator); IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); constructor(address subscriptionOrRegistrantToCopy, bool subscribe) { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (subscribe) { OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { OPERATOR_FILTER_REGISTRY.register(address(this)); } } } } modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } function _checkFilterOperator(address operator) internal view virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "@openzeppelin/contracts/access/Ownable.sol"; import "./VRFv2Consumer.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol"; import "operator-filter-registry/src/DefaultOperatorFilterer.sol"; import "./ITokenDNAStorage.sol"; /// @title Tribute Drop NFT Abstract Contract /// @author Tribute Brand LLC /// @notice This contract defines the interface and default behavior of drop nft contracts. /// @dev This contract is meant to be implemented by actual drop contracts. /// It is mainly interacted with through the TributeBrand contract. abstract contract DropNFT is DefaultOperatorFilterer, ERC721Royalty, VRFv2Consumer, Ownable { error AwaitingEntropy(); error WrongReveal(); error MintingPaused(); error ReservedSupplyReached(); error TotalSupplyReached(); string private _revealedBaseURI; uint256 private _reservedMinted; address immutable deployer; uint256 internal _totalMinted; bool public mintingPaused; ITokenDNAStorage public DNAResolverContract; constructor( address tributeBrandFactory, address dnaContract, string memory name_, string memory symbol_, uint64 chainlinkKey ) VRFv2Consumer(chainlinkKey) ERC721(name_, symbol_) { DNAResolverContract = ITokenDNAStorage(dnaContract); deployer = msg.sender; _setDefaultRoyalty(deployer, 750); // 750 basis points <=> 7.5 % royalty fee transferOwnership(tributeBrandFactory); } // ============================================================= // ROYALTY OVERRIDES (OPERATOR FILTER) // ============================================================= function setApprovalForAll( address operator, bool approved ) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } function approve( address operator, uint256 tokenId ) public override onlyAllowedOperatorApproval(operator) { super.approve(operator, tokenId); } function transferFrom( address from, address to, uint256 tokenId ) public override onlyAllowedOperator(from) { super.transferFrom(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, data); } // ============================================================= // OWNER METHODS // ============================================================= modifier onlyOwnerOrDeployer() { require( owner() == _msgSender() || deployer == msg.sender, "Ownable: caller is not the owner or deployer" ); _; } function mint( address to, uint256 ) external virtual onlyOwner returns (uint256) { if (_totalMinted + 1 > _maxSupply() - _reservedSupply()) revert TotalSupplyReached(); return _mintTo(to); } function reservedMint( address to, uint256 quantity, uint256 ) external virtual onlyOwnerOrDeployer returns (uint256 startTokenId) { if (quantity > _reservedRemaining()) revert ReservedSupplyReached(); startTokenId = _totalMinted; for (uint i; i < quantity; i++) { _mintTo(to); } _reservedMinted += quantity; } function manualSetEntropy() external virtual onlyOwnerOrDeployer { if (entropy == 0) entropy = uint( keccak256(abi.encodePacked(block.difficulty, block.timestamp)) ); } function requestEntropy() public virtual returns (uint256) { if (entropy > 0) return 0; return requestRandomWords(); } function reveal( string calldata realBaseTokenURI ) external onlyOwnerOrDeployer { _reveal(realBaseTokenURI); } function pause(bool on) external onlyOwnerOrDeployer { mintingPaused = on; } function usesEntropy() external pure returns (bool) { return _useEntropy(); } // ============================================================= // CONSTANTS / TYPES / OVERRIDEABLES // ============================================================= struct Trait { string trait_type; string trait_value; string trait_extra; } function tokenDNA( uint256 tokenId ) public view virtual returns (bytes16 dna) { dna = DNAResolverContract.getTokenDNA(tokenId, entropy); } // ------ REQUIRED ------ function dropUUID() external pure virtual returns (string memory); function contractURI() external pure virtual returns (string memory); function provenanceHash() external pure virtual returns (string memory); function _encodedBaseURI() internal pure virtual returns (bytes32); function _unrevealedBaseURI() internal pure virtual returns (string memory); function _reservedSupply() internal pure virtual returns (uint256); // ------ OPTIONAL ------ function _traitsToAttributeString( Trait[] memory traits ) internal pure virtual returns (string memory) { string memory bStr; for (uint idx = 0; idx < traits.length; idx++) { bStr = string.concat( bStr, '{"trait_type":"', traits[idx].trait_type, '","value":"', traits[idx].trait_value, '"}' ); if (idx < traits.length - 1) bStr = string.concat(bStr, ","); } return bStr; } function _maxSupply() internal pure virtual returns (uint256) { return 10000; } function _useEntropy() internal pure virtual returns (bool) { return false; } function _baseURI() internal view virtual override returns (string memory) { return _isRevealed() ? _revealedBaseURI : _unrevealedBaseURI(); } function _startTokenId() internal view virtual returns (uint256) { return 0; } function _isRevealed() internal view virtual returns (bool) { return bytes(_revealedBaseURI).length > 0; } function _mintTo(address to) internal virtual returns (uint256 tokenId) { // We only have one entropy for the first drop. This is here so that no one can mint between the moment of nft contract publishing // (which is when the entropy is requested from chainlink VFR) and the moment that request is fulfilled (~30s later). if (mintingPaused) revert MintingPaused(); if (_useEntropy() && entropy == 0) revert AwaitingEntropy(); tokenId = _totalMinted++; super._mint(to, tokenId); } // ============================================================= // OTHER // ============================================================= /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * (off-chain calls to view/pure functions are free, but calling * them on-chain, for instance from the TributeBrand contract, is not free). * * To get all the tokens in all drops that an account owns: first read drops() from the * TributeBrand contract, then for each of these addresses call this function. */ function tokensOfOwner( address owner ) external view returns (uint256[] memory) { unchecked { uint256 tokenIdsIdx; address currOwner; uint256 tokenIdsLength = balanceOf(owner); uint256[] memory tokenIds = new uint256[](tokenIdsLength); for (uint256 i = 0; tokenIdsIdx != tokenIdsLength; ++i) { if (currOwner == owner) { tokenIds[tokenIdsIdx++] = i; } } return tokenIds; } } function checkClaimEligibility( uint256 quantity ) external view returns (string memory) { if (mintingPaused || (_useEntropy() && entropy == 0)) { return "not live yet"; } else if (_totalMinted + quantity > _maxSupply() - _reservedSupply()) { return "not enough supply"; } return ""; } // ============================================================= // INTERNAL UTILS // ============================================================= function _reservedRemaining() private view returns (uint256) { return _reservedSupply() - _reservedMinted; } function _reveal(string calldata realBaseTokenURI) private { if (keccak256(abi.encodePacked(realBaseTokenURI)) != _encodedBaseURI()) revert WrongReveal(); _revealedBaseURI = realBaseTokenURI; } function withdraw(address _receiver) public onlyOwnerOrDeployer { (bool os, ) = payable(_receiver).call{value: address(this).balance}(""); require(os, "Withdraw unsuccesful"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; interface ITokenDNAStorage { function getTokenDNA( uint256 tokenId, uint256 entropy ) external view returns (bytes16); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; contract VRFv2Consumer is VRFConsumerBaseV2 { event RequestSent(uint256 requestId, uint32 numWords); event RequestFulfilled(uint256 requestId, uint256[] randomWords); struct RequestStatus { bool fulfilled; // whether the request has been successfully fulfilled bool exists; // whether a requestId exists uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ VRFCoordinatorV2Interface COORDINATOR; // Your subscription ID. uint64 s_subscriptionId; // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; uint256 public entropy; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2/subscription/supported-networks/#configurations bytes32 keyHash = 0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, // so 100,000 is a safe default for this example contract. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 callbackGasLimit = 100000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. uint32 numWords = 1; /** * HARDCODED FOR GOERLI * COORDINATOR: 0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D */ constructor( uint64 subscriptionId ) VRFConsumerBaseV2(0x271682DEB8C4E0901D1a1550aD2e64D568E69909) { COORDINATOR = VRFCoordinatorV2Interface( 0x271682DEB8C4E0901D1a1550aD2e64D568E69909 ); s_subscriptionId = subscriptionId; } // Assumes the subscription is funded sufficiently. function requestRandomWords() internal returns (uint256 requestId) { // Will revert if subscription is not set and funded. requestId = COORDINATOR.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); s_requests[requestId] = RequestStatus({ randomWords: new uint256[](0), exists: true, fulfilled: false }); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, numWords); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { require(s_requests[_requestId].exists, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; entropy = _randomWords[0]; emit RequestFulfilled(_requestId, _randomWords); } function getRequestStatus( uint256 _requestId ) external view returns (bool fulfilled, uint256[] memory randomWords) { require(s_requests[_requestId].exists, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.fulfilled, request.randomWords); } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 100000000 }, "remappings": [], "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionAlreadyUsed","type":"error"},{"inputs":[],"name":"BadSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"InvalidPayment","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"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":"uuid","type":"bytes32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"dropNFT","type":"address"},{"indexed":true,"internalType":"uint256","name":"startTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"ReservedTokensMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"dropNFT","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"mintData","type":"bytes32"}],"name":"TokenMinted","type":"event"},{"inputs":[],"name":"SIGNED_ACTION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"uuid","type":"bytes32"},{"internalType":"bytes32","name":"data","type":"bytes32"},{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"actionDigest","outputs":[{"internalType":"bytes32","name":"digest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"checkClaimEligibility","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentDrop","outputs":[{"internalType":"contract DropNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"drops","outputs":[{"internalType":"contract DropNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLicenseName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLicenseURI","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":"address","name":"dropNFTAddress","type":"address"}],"name":"publishDrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"dropId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"reservedMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"realBaseTokenURI","type":"string"}],"name":"revealDrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32","name":"uuid","type":"bytes32"},{"internalType":"bytes32","name":"mintData","type":"bytes32"},{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"signedMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"uuid","type":"bytes32"},{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"signedPayment","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61014080604052346200019b57620020868038038091620000218285620001a0565b83398101906040818303126200019b5780516001600160401b0391908281116200019b578362000053918301620001c4565b9260208201518381116200019b576200006d9201620001c4565b91602081519101209160208151910120918060e052610100928084524660a05260405160208101917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f93848452604083015260608201524660808201523060a082015260a0815260c0810193818510908511176200018557836040525190206080523060c05261012090815260016000556001543360018060a01b0382167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a81b0319163360ff60a01b191617600155611e4a92836200023c843960805183611878015260a0518361192d015260c05183611849015260e051836118c7015251826118ed015251816118a40152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176200018557604052565b919080601f840112156200019b578251906001600160401b03821162000185576040519160209162000200601f8301601f1916840185620001a0565b8184528282870101116200019b5760005b8181106200022757508260009394955001015290565b85810183015184820184015282016200021156fe6080604081815260048036101561001557600080fd5b600092833560e01c90816301ffc9a71461126d57508063072dad781461122e5780631245c653146111d657806315f319a014610f605780631854dc7a14610f075780633c1d9b6214610d8b57806343913bfd14610c5757806351cff8d914610b66578381635b8925b914610a17575080635eb3996814610992578063715018a6146108f35780638da5cb5b146108a0578063a29989b71461084f578063a341793b146107ff578063c7db2893146104f7578063d33ad4321461021c5763f2fde38b146100e057600080fd5b346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610218576101176113c5565b9061012061170e565b73ffffffffffffffffffffffffffffffffffffffff809216928315610195575050600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b50919060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f3576102516113c5565b9260443591606435946084359060a43567ffffffffffffffff81116104ef5761027d9036908601611397565b9290973482036104ba57804211610492579061029c918760243561178d565b8087526020926003845260ff858920541661046a576102c56102d39798996102cb923691611a3c565b82611bdd565b969096611a73565b73ffffffffffffffffffffffffffffffffffffffff809616732c1c452924c085566d764e3186a886a7eaa23229036104415787526003825282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580851661043b575033915b856104235784610350611953565b16948151937f40c10f1900000000000000000000000000000000000000000000000000000000855216809484015286602484015281836044818a895af190811561041a5787916103c6575b7f4dfa4c5462629780dc1c2b195bca972cb90dcb44959921c61a4ee942bfb1a22e935051908152a480f35b90508183813d8311610413575b6103dd81836114d1565b8101031261040e577f4dfa4c5462629780dc1c2b195bca972cb90dcb44959921c61a4ee942bfb1a22e92519061039b565b600080fd5b503d6103d3565b513d88823e3d90fd5b848061042e886113e8565b90549060031b1c16610350565b91610342565b505050517f5cd5d233000000000000000000000000000000000000000000000000000000008152fd5b8585517ffae12290000000000000000000000000000000000000000000000000000000008152fd5b8585517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b604486838751917f7f7d5b96000000000000000000000000000000000000000000000000000000008352820152346024820152fd5b8680fd5b5080fd5b5091346107fc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc578151906060820182811067ffffffffffffffff8211176107ce578352603182526020938483017f61723a2f2f7a6d63315754737049684679565938326277664149634945784c4681527f48356c55634848554e307758673457382f0000000000000000000000000000008585015260019160ff835460a01c169260068410156107a2578390849286957a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000009081811015610795575b5050896d04ee2d6d415b85acef810000000080861015610787575b5050662386f26fc1000080851015610778575b506305f5e10080851015610769575b506127108085101561075b575b5050606483101561074b575b600a80931015610742575b908160218187019661066061064b89611512565b986106588d519a8b6114d1565b808a52611512565b987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08d8a019a01368b3750870101905b6106e1575b6106dd6106b88a6106d38d8c8c8c6106c78d87519889955180928888019061132a565b8401915180938684019061132a565b010380855201836114d1565b519182918261134d565b0390f35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019083907f30313233343536373839616263646566000000000000000000000000000000008282061a83530491821561073d57919082610690565b610695565b80940193610637565b939160646002910492019361062c565b950194909204913880610620565b60089196940493019438610613565b60109196940493019438610604565b9601959093049289386105f1565b8a975004935038806105d6565b6024856021847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6041857f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b80fd5b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f3576106dd9061084460ff60015460a01c1661154c565b90519182918261134d565b5091346107fc5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc57506108996020926064359060443590602435903561178d565b9051908152f35b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f35760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b83346107fc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc5761092a61170e565b600073ffffffffffffffffffffffffffffffffffffffff6001547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102185735916002548310156107fc575073ffffffffffffffffffffffffffffffffffffffff60209260026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0154169051908152f35b80848434610b625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b625767ffffffffffffffff8135818111610b5e57610a689036908401611397565b9490610a7261170e565b73ffffffffffffffffffffffffffffffffffffffff610a8f611953565b16803b15610218576020836044877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8c8c519d8e998a9889967f4c2612470000000000000000000000000000000000000000000000000000000088528701528160248701528686013785858286010152011681010301925af18015610b5457610b18578480f35b8311610b28575052818080808480f35b8360416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b83513d87823e3d90fd5b8480fd5b5050fd5b5090346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102185782808080610ba36113c5565b610bab61170e565b73ffffffffffffffffffffffffffffffffffffffff4791165af13d15610c52573d610bd581611512565b90610be2845192836114d1565b81528460203d92013e5b15610bf5578280f35b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601460248201527f576974686472617720756e73756363657366756c0000000000000000000000006044820152fd5b610bec565b509190346104f35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f357610c916113c5565b610c9961170e565b73ffffffffffffffffffffffffffffffffffffffff8091169060025468010000000000000000811015610d5f57948291602093610cdd886001899a016002556113e8565b909283549160031b90811b9283911b169119161790558351809581937fb13038a10000000000000000000000000000000000000000000000000000000083525af1908115610d565750610d2e575080f35b602090813d8111610d4f575b610d4481836114d1565b810103126107fc5780f35b503d610d3a565b513d84823e3d90fd5b6024856041887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5090346102185760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021857610dc46113c5565b91604435602435610dd361170e565b80610edb5750610de1611953565b925b73ffffffffffffffffffffffffffffffffffffffff809416938151957f3c1d9b6200000000000000000000000000000000000000000000000000000000875216809386015281602486015285604486015260208560648189885af1948515610ed1578695610e7a575b507f67f3cf0be86c1a69dddebf6544ffbd39aba7c0716db39d794c159714151121629160209151908152a480f35b9094506020813d8211610ec9575b81610e95602093836114d1565b81010312610ec55751937f67f3cf0be86c1a69dddebf6544ffbd39aba7c0716db39d794c15971415112162610e4c565b8580fd5b3d9150610e88565b81513d88823e3d90fd5b610ef973ffffffffffffffffffffffffffffffffffffffff916113e8565b90549060031b1c1692610de3565b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f357602090517f7071f25206f23efe1be959d1ffa68a043acba31cb39d7e3dbe40f1ae14cd360c8152f35b509060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610218578135916024359060443560643567ffffffffffffffff81116104ef57610fb59036908401611397565b9390913481036111a1578142116111795785519060208201927f7071f25206f23efe1be959d1ffa68a043acba31cb39d7e3dbe40f1ae14cd360c84528888840152896060840152608083015260a082015260a081526110138161144e565b51902061101e611832565b9085519060208201927f19010000000000000000000000000000000000000000000000000000000000008452602283015260428201526042815261106181611499565b51902092838752600360205260ff8588205416611151576110a561109f73ffffffffffffffffffffffffffffffffffffffff936110ad933691611a3c565b85611bdd565b919091611a73565b16732c1c452924c085566d764e3186a886a7eaa232290361112a57508352600360205280832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905551903482527f3b5907c9aaeaeef015f385111975b015225e1001bf659370e62c15e13373bc6d60203393a380f35b82517f5cd5d233000000000000000000000000000000000000000000000000000000008152fd5b8285517ffae12290000000000000000000000000000000000000000000000000000000008152fd5b8386517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b836044918751917f7f7d5b96000000000000000000000000000000000000000000000000000000008352820152346024820152fd5b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f35760209073ffffffffffffffffffffffffffffffffffffffff611226611953565b915191168152f35b5091346107fc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc57506108446106dd9235611cb1565b925050346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021857357fffffffff00000000000000000000000000000000000000000000000000000000811680910361021857602092507f649a51a8000000000000000000000000000000000000000000000000000000008114908115611300575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386112f9565b60005b83811061133d5750506000910152565b818101518382015260200161132d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60409360208452611390815180928160208801526020888801910161132a565b0116010190565b9181601f8401121561040e5782359167ffffffffffffffff831161040e576020838186019501011161040e57565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361040e57565b60025481101561141f5760026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60c0810190811067ffffffffffffffff82111761146a57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff82111761146a57604052565b6040810190811067ffffffffffffffff82111761146a57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761146a57604052565b67ffffffffffffffff811161146a57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60068110156116df57600660ff82161161040e5780156116a5578060011461166b578060021461163157806003146115f7576004036115be57604051611591816114b5565b600881527f504552534f4e414c000000000000000000000000000000000000000000000000602082015290565b6040516115ca816114b5565b601081527f504552534f4e414c5f4e4f5f4841544500000000000000000000000000000000602082015290565b50604051611604816114b5565b601281527f434f4d4d45524349414c5f4e4f5f484154450000000000000000000000000000602082015290565b5060405161163e816114b5565b600a81527f434f4d4d45524349414c00000000000000000000000000000000000000000000602082015290565b50604051611678816114b5565b600981527f4558434c55534956450000000000000000000000000000000000000000000000602082015290565b506040516116b2816114b5565b600681527f5055424c49430000000000000000000000000000000000000000000000000000602082015290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff60015416330361172f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b9290916040519260208401947f7071f25206f23efe1be959d1ffa68a043acba31cb39d7e3dbe40f1ae14cd360c865260408501526060840152608083015260a082015260a081526117dd8161144e565b5190206117e8611832565b906040519060208201927f19010000000000000000000000000000000000000000000000000000000000008452602283015260428201526042815261182c81611499565b51902090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630148061192a575b1561189a577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f000000000000000000000000000000000000000000000000000000000000000082527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815261182c8161144e565b507f00000000000000000000000000000000000000000000000000000000000000004614611871565b60025480156119de577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81019081116119af576119a473ffffffffffffffffffffffffffffffffffffffff916113e8565b90549060031b1c1690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4e6f2064726f70732068617665206265656e2063726561746564207965742e006044820152fd5b929192611a4882611512565b91611a5660405193846114d1565b82948184528183011161040e578281602093846000960137010152565b60058110156116df5780611a845750565b60018103611aea5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152fd5b60028103611b505760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152fd5b600314611b5957565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b906041815114600014611c0b57611c07916020820151906060604084015193015160001a90611c15565b9091565b5050600090600290565b9291907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311611ca55791608094939160ff602094604051948552168484015260408301526060820152600093849182805260015afa15611c9857815173ffffffffffffffffffffffffffffffffffffffff811615611c92579190565b50600190565b50604051903d90823e3d90fd5b50505050600090600390565b60025480611cf4575050604051611cc7816114b5565b600c81527f6e6f74206c697665207965740000000000000000000000000000000000000000602082015290565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81019081116119af57611d27906113e8565b91905491604051917f072dad7800000000000000000000000000000000000000000000000000000000835260048301528160248173ffffffffffffffffffffffffffffffffffffffff600096879560031b1c165afa918215611e08578092611d8e57505090565b9091503d8082843e611da081846114d1565b8201916020818403126104f35780519067ffffffffffffffff8211610218570182601f820112156104f357805191611dd783611512565b93611de560405195866114d1565b838552602084840101116107fc575090611e05916020808501910161132a565b90565b604051903d90823e3d90fdfea2646970667358221220d29b7514f7b8c809a81a346697a1fe4673e6f30b7bc70d93cad36f09db72cb6564736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000d545249425554455f4252414e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004312e303000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604081815260048036101561001557600080fd5b600092833560e01c90816301ffc9a71461126d57508063072dad781461122e5780631245c653146111d657806315f319a014610f605780631854dc7a14610f075780633c1d9b6214610d8b57806343913bfd14610c5757806351cff8d914610b66578381635b8925b914610a17575080635eb3996814610992578063715018a6146108f35780638da5cb5b146108a0578063a29989b71461084f578063a341793b146107ff578063c7db2893146104f7578063d33ad4321461021c5763f2fde38b146100e057600080fd5b346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610218576101176113c5565b9061012061170e565b73ffffffffffffffffffffffffffffffffffffffff809216928315610195575050600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b50919060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f3576102516113c5565b9260443591606435946084359060a43567ffffffffffffffff81116104ef5761027d9036908601611397565b9290973482036104ba57804211610492579061029c918760243561178d565b8087526020926003845260ff858920541661046a576102c56102d39798996102cb923691611a3c565b82611bdd565b969096611a73565b73ffffffffffffffffffffffffffffffffffffffff809616732c1c452924c085566d764e3186a886a7eaa23229036104415787526003825282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580851661043b575033915b856104235784610350611953565b16948151937f40c10f1900000000000000000000000000000000000000000000000000000000855216809484015286602484015281836044818a895af190811561041a5787916103c6575b7f4dfa4c5462629780dc1c2b195bca972cb90dcb44959921c61a4ee942bfb1a22e935051908152a480f35b90508183813d8311610413575b6103dd81836114d1565b8101031261040e577f4dfa4c5462629780dc1c2b195bca972cb90dcb44959921c61a4ee942bfb1a22e92519061039b565b600080fd5b503d6103d3565b513d88823e3d90fd5b848061042e886113e8565b90549060031b1c16610350565b91610342565b505050517f5cd5d233000000000000000000000000000000000000000000000000000000008152fd5b8585517ffae12290000000000000000000000000000000000000000000000000000000008152fd5b8585517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b604486838751917f7f7d5b96000000000000000000000000000000000000000000000000000000008352820152346024820152fd5b8680fd5b5080fd5b5091346107fc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc578151906060820182811067ffffffffffffffff8211176107ce578352603182526020938483017f61723a2f2f7a6d63315754737049684679565938326277664149634945784c4681527f48356c55634848554e307758673457382f0000000000000000000000000000008585015260019160ff835460a01c169260068410156107a2578390849286957a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000009081811015610795575b5050896d04ee2d6d415b85acef810000000080861015610787575b5050662386f26fc1000080851015610778575b506305f5e10080851015610769575b506127108085101561075b575b5050606483101561074b575b600a80931015610742575b908160218187019661066061064b89611512565b986106588d519a8b6114d1565b808a52611512565b987fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08d8a019a01368b3750870101905b6106e1575b6106dd6106b88a6106d38d8c8c8c6106c78d87519889955180928888019061132a565b8401915180938684019061132a565b010380855201836114d1565b519182918261134d565b0390f35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019083907f30313233343536373839616263646566000000000000000000000000000000008282061a83530491821561073d57919082610690565b610695565b80940193610637565b939160646002910492019361062c565b950194909204913880610620565b60089196940493019438610613565b60109196940493019438610604565b9601959093049289386105f1565b8a975004935038806105d6565b6024856021847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6041857f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b80fd5b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f3576106dd9061084460ff60015460a01c1661154c565b90519182918261134d565b5091346107fc5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc57506108996020926064359060443590602435903561178d565b9051908152f35b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f35760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b83346107fc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc5761092a61170e565b600073ffffffffffffffffffffffffffffffffffffffff6001547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102185735916002548310156107fc575073ffffffffffffffffffffffffffffffffffffffff60209260026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0154169051908152f35b80848434610b625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610b625767ffffffffffffffff8135818111610b5e57610a689036908401611397565b9490610a7261170e565b73ffffffffffffffffffffffffffffffffffffffff610a8f611953565b16803b15610218576020836044877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8c8c519d8e998a9889967f4c2612470000000000000000000000000000000000000000000000000000000088528701528160248701528686013785858286010152011681010301925af18015610b5457610b18578480f35b8311610b28575052818080808480f35b8360416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b83513d87823e3d90fd5b8480fd5b5050fd5b5090346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102185782808080610ba36113c5565b610bab61170e565b73ffffffffffffffffffffffffffffffffffffffff4791165af13d15610c52573d610bd581611512565b90610be2845192836114d1565b81528460203d92013e5b15610bf5578280f35b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601460248201527f576974686472617720756e73756363657366756c0000000000000000000000006044820152fd5b610bec565b509190346104f35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f357610c916113c5565b610c9961170e565b73ffffffffffffffffffffffffffffffffffffffff8091169060025468010000000000000000811015610d5f57948291602093610cdd886001899a016002556113e8565b909283549160031b90811b9283911b169119161790558351809581937fb13038a10000000000000000000000000000000000000000000000000000000083525af1908115610d565750610d2e575080f35b602090813d8111610d4f575b610d4481836114d1565b810103126107fc5780f35b503d610d3a565b513d84823e3d90fd5b6024856041887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5090346102185760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021857610dc46113c5565b91604435602435610dd361170e565b80610edb5750610de1611953565b925b73ffffffffffffffffffffffffffffffffffffffff809416938151957f3c1d9b6200000000000000000000000000000000000000000000000000000000875216809386015281602486015285604486015260208560648189885af1948515610ed1578695610e7a575b507f67f3cf0be86c1a69dddebf6544ffbd39aba7c0716db39d794c159714151121629160209151908152a480f35b9094506020813d8211610ec9575b81610e95602093836114d1565b81010312610ec55751937f67f3cf0be86c1a69dddebf6544ffbd39aba7c0716db39d794c15971415112162610e4c565b8580fd5b3d9150610e88565b81513d88823e3d90fd5b610ef973ffffffffffffffffffffffffffffffffffffffff916113e8565b90549060031b1c1692610de3565b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f357602090517f7071f25206f23efe1be959d1ffa68a043acba31cb39d7e3dbe40f1ae14cd360c8152f35b509060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610218578135916024359060443560643567ffffffffffffffff81116104ef57610fb59036908401611397565b9390913481036111a1578142116111795785519060208201927f7071f25206f23efe1be959d1ffa68a043acba31cb39d7e3dbe40f1ae14cd360c84528888840152896060840152608083015260a082015260a081526110138161144e565b51902061101e611832565b9085519060208201927f19010000000000000000000000000000000000000000000000000000000000008452602283015260428201526042815261106181611499565b51902092838752600360205260ff8588205416611151576110a561109f73ffffffffffffffffffffffffffffffffffffffff936110ad933691611a3c565b85611bdd565b919091611a73565b16732c1c452924c085566d764e3186a886a7eaa232290361112a57508352600360205280832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905551903482527f3b5907c9aaeaeef015f385111975b015225e1001bf659370e62c15e13373bc6d60203393a380f35b82517f5cd5d233000000000000000000000000000000000000000000000000000000008152fd5b8285517ffae12290000000000000000000000000000000000000000000000000000000008152fd5b8386517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b836044918751917f7f7d5b96000000000000000000000000000000000000000000000000000000008352820152346024820152fd5b5050346104f357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104f35760209073ffffffffffffffffffffffffffffffffffffffff611226611953565b915191168152f35b5091346107fc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107fc57506108446106dd9235611cb1565b925050346102185760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021857357fffffffff00000000000000000000000000000000000000000000000000000000811680910361021857602092507f649a51a8000000000000000000000000000000000000000000000000000000008114908115611300575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386112f9565b60005b83811061133d5750506000910152565b818101518382015260200161132d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60409360208452611390815180928160208801526020888801910161132a565b0116010190565b9181601f8401121561040e5782359167ffffffffffffffff831161040e576020838186019501011161040e57565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361040e57565b60025481101561141f5760026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60c0810190811067ffffffffffffffff82111761146a57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff82111761146a57604052565b6040810190811067ffffffffffffffff82111761146a57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761146a57604052565b67ffffffffffffffff811161146a57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60068110156116df57600660ff82161161040e5780156116a5578060011461166b578060021461163157806003146115f7576004036115be57604051611591816114b5565b600881527f504552534f4e414c000000000000000000000000000000000000000000000000602082015290565b6040516115ca816114b5565b601081527f504552534f4e414c5f4e4f5f4841544500000000000000000000000000000000602082015290565b50604051611604816114b5565b601281527f434f4d4d45524349414c5f4e4f5f484154450000000000000000000000000000602082015290565b5060405161163e816114b5565b600a81527f434f4d4d45524349414c00000000000000000000000000000000000000000000602082015290565b50604051611678816114b5565b600981527f4558434c55534956450000000000000000000000000000000000000000000000602082015290565b506040516116b2816114b5565b600681527f5055424c49430000000000000000000000000000000000000000000000000000602082015290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff60015416330361172f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b9290916040519260208401947f7071f25206f23efe1be959d1ffa68a043acba31cb39d7e3dbe40f1ae14cd360c865260408501526060840152608083015260a082015260a081526117dd8161144e565b5190206117e8611832565b906040519060208201927f19010000000000000000000000000000000000000000000000000000000000008452602283015260428201526042815261182c81611499565b51902090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000008a72a8a49debb183ac5c0f25053c23c863c9a721630148061192a575b1561189a577f1a52c117ef1da1be552e464797baa95dca10cf897f6dd605e93604a70be37d3690565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527ff4222f92931ee260db97ccac3ddd1b78de466c0b39b312ed5fdccc820c72c89060408201527fc40121ef69fdba06ed462a953b1212faa18c76d512fafd9cc86790dc2e8ca9bc60608201524660808201523060a082015260a0815261182c8161144e565b507f00000000000000000000000000000000000000000000000000000000000000014614611871565b60025480156119de577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81019081116119af576119a473ffffffffffffffffffffffffffffffffffffffff916113e8565b90549060031b1c1690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4e6f2064726f70732068617665206265656e2063726561746564207965742e006044820152fd5b929192611a4882611512565b91611a5660405193846114d1565b82948184528183011161040e578281602093846000960137010152565b60058110156116df5780611a845750565b60018103611aea5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152fd5b60028103611b505760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152fd5b600314611b5957565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b906041815114600014611c0b57611c07916020820151906060604084015193015160001a90611c15565b9091565b5050600090600290565b9291907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311611ca55791608094939160ff602094604051948552168484015260408301526060820152600093849182805260015afa15611c9857815173ffffffffffffffffffffffffffffffffffffffff811615611c92579190565b50600190565b50604051903d90823e3d90fd5b50505050600090600390565b60025480611cf4575050604051611cc7816114b5565b600c81527f6e6f74206c697665207965740000000000000000000000000000000000000000602082015290565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81019081116119af57611d27906113e8565b91905491604051917f072dad7800000000000000000000000000000000000000000000000000000000835260048301528160248173ffffffffffffffffffffffffffffffffffffffff600096879560031b1c165afa918215611e08578092611d8e57505090565b9091503d8082843e611da081846114d1565b8201916020818403126104f35780519067ffffffffffffffff8211610218570182601f820112156104f357805191611dd783611512565b93611de560405195866114d1565b838552602084840101116107fc575090611e05916020808501910161132a565b90565b604051903d90823e3d90fdfea2646970667358221220d29b7514f7b8c809a81a346697a1fe4673e6f30b7bc70d93cad36f09db72cb6564736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000d545249425554455f4252414e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004312e303000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name (string): TRIBUTE_BRAND
Arg [1] : version (string): 1.00
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [3] : 545249425554455f4252414e4400000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [5] : 312e303000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ 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.