Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 551 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Mint | 20295057 | 4 days ago | IN | 0 ETH | 0.00025299 | ||||
Mint | 20295035 | 4 days ago | IN | 0 ETH | 0.00029966 | ||||
Mint | 20295028 | 4 days ago | IN | 0 ETH | 0.00027485 | ||||
Mint | 20295023 | 4 days ago | IN | 0 ETH | 0.00027057 | ||||
Mint | 20295020 | 4 days ago | IN | 0 ETH | 0.00028832 | ||||
Mint | 20295014 | 4 days ago | IN | 0 ETH | 0.00026891 | ||||
Mint | 20267614 | 8 days ago | IN | 0 ETH | 0.00054341 | ||||
Mint | 20252137 | 10 days ago | IN | 0 ETH | 0.00026395 | ||||
Mint | 19927932 | 55 days ago | IN | 0 ETH | 0.00341124 | ||||
Mint | 19925948 | 56 days ago | IN | 0 ETH | 0.0025477 | ||||
Mint | 19891767 | 60 days ago | IN | 0 ETH | 0.00058559 | ||||
Mint | 19891755 | 60 days ago | IN | 0 ETH | 0.00053621 | ||||
Mint | 19891752 | 60 days ago | IN | 0 ETH | 0.0005356 | ||||
Mint | 19891749 | 60 days ago | IN | 0 ETH | 0.00058019 | ||||
Mint | 19891746 | 60 days ago | IN | 0 ETH | 0.00058438 | ||||
Mint | 19891744 | 60 days ago | IN | 0 ETH | 0.00061101 | ||||
Mint | 19891741 | 60 days ago | IN | 0 ETH | 0.0005528 | ||||
Mint | 19891737 | 60 days ago | IN | 0 ETH | 0.00060523 | ||||
Mint | 19681258 | 90 days ago | IN | 0 ETH | 0.00201268 | ||||
Mint | 19300800 | 143 days ago | IN | 0 ETH | 0.00360941 | ||||
Mint | 19300797 | 143 days ago | IN | 0 ETH | 0.00342254 | ||||
Mint | 19300795 | 143 days ago | IN | 0 ETH | 0.00408009 | ||||
Mint | 19246138 | 151 days ago | IN | 0 ETH | 0.00264599 | ||||
Mint | 19241594 | 151 days ago | IN | 0 ETH | 0.00543979 | ||||
Mint | 19241574 | 151 days ago | IN | 0 ETH | 0.00671885 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
TokenGating
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC721, IERC165} from "../../openzeppelin/token/ERC721/IERC721.sol"; import "../../openzeppelin/token/ERC1155/IERC1155.sol"; import "../../manifold/libraries-solidity/access/AdminControlUpgradeable.sol"; import "../../openzeppelin/utils/introspection/ERC165Checker.sol"; import "../../openzeppelin-upgradeable/access/IAccessControlUpgradeable.sol"; import "../../manifold/royalty-registry/specs/INiftyGateway.sol"; import "../../manifold/royalty-registry/specs/IFoundation.sol"; import {IERC721CreatorCore} from "../../manifold/creator-core/core/IERC721CreatorCore.sol"; import {IERC1155CreatorCore} from "../../manifold/creator-core/core/IERC1155CreatorCore.sol"; import {ReentrancyGuard} from "../../openzeppelin/security/ReentrancyGuard.sol"; import {AdminControl} from "../../manifold/libraries-solidity/access/AdminControl.sol"; import {ECDSA} from "../../openzeppelin/utils/cryptography/ECDSA.sol"; /** * @title Token Gating * @dev This contract facilitates to gate the collections and gives privilages for the gated token owners to claim the nft from the * required nft collections. */ contract TokenGating is ReentrancyGuard, AdminControl { using ECDSA for bytes32; /// @notice The Gating data at collection level /// @param perTokenLimit the limit per token /// @param perCollectionLimit the limit per collection struct CollectionGatingData { uint256 perTokenLimit; uint256 perCollectionLimit; } /// @notice The signing data by admin /// @param expirationTime the expiration time for the signature /// @param nonce the unique nonce for the signature /// @param signature the signature data given by signer /// @param signer the address of the signer struct Approval { uint32 expirationTime; string nonce; bytes signature; address signer; } // admin approval requirement bool public adminApprovalRequired; // sets Collection gating data with respect to collection mapping(address => CollectionGatingData) private collectionLimitations; // sets token limit with respect to tokenID of collection concerned mapping(address => mapping(uint256 => uint256)) private tokenLimitations; // sets perToken limit with respect to tokenID of collection concerned mapping(address => mapping(uint256 => uint256)) private perTokenLimitation; // signature validation mapping(bytes => bool) public signatureUsed; // sets interface ERC721 Id bytes4 private constant ERC721_INTERFACE_ID = 0x80ac58cd; // sets interface ERC1155 Id bytes4 private constant ERC1155_INTERFACE_ID = 0xd9b67a26; /// @notice the type of gating enum GatingType { collection, token } /// @notice emits an event when gated minting /// @param gatedCollection the collection address which is gated /// @param tokenId the token id /// @param mintedWallet the minter wallet address /// @param mintingContract the contract address of minting process /// @param tokenIdMinted the minted token ids event gatedMinting( address indexed gatedCollection, uint256 indexed tokenId, address mintedWallet, address mintingContract, uint256[] tokenIdMinted ); /// @notice emits an event when gated transfer /// @param gatedCollection the collection address which is gated /// @param tokenId the token id /// @param transferWallet the wallet address of Nft transferred /// @param transferContract the contract address of transfer process /// @param transferTokenId the token id which is transferred /// @param transferOwner the Owner address where the nft transfers from event gatedTransfer( address indexed gatedCollection, uint256 indexed tokenId, address transferWallet, address transferContract, uint256 transferTokenId, address transferOwner ); /// @notice emits an event when acquiring gated info /// @param gatedCollection the collection address which is gated /// @param gatedTokenId the token id which is gated /// @param acquiredAddress the address of acquiring entity /// @param gatingType the contract address of transfer process event gatingAcquired( address gatedCollection, uint256 gatedTokenId, address acquiredAddress, string gatingType ); /// @notice emits an event when token is gated /// @param gatedCollection the collection address which is gated /// @param tokenId the token id /// @param limit the gating limit event tokenGated(address gatedCollection, uint256 tokenId, uint256 limit); /// @notice emits an event when Collection is gated /// @param gatedCollection the collection address which is gated /// @param perCollectionLimit the gating limit at collection level /// @param petTokenLimit the gating limit at token level event collectionGated( address gatedCollection, uint256 perCollectionLimit, uint256 petTokenLimit ); /** * @notice constructor * @param _adminApprovalRequired the set/reset the admin approval */ constructor(bool _adminApprovalRequired) { adminApprovalRequired = _adminApprovalRequired; } /** * @notice setTokenGating, sets gating data at token level * @param collectionAddress the address of nft collection * @param tokenId the id of token * @param limit the gating limit of token id */ function setTokenGating( address collectionAddress, uint256 tokenId, uint256 limit ) public nonReentrant { require( isAdmin(msg.sender) , "sender should be a Admin" ); tokenLimitations[collectionAddress][tokenId] = limit; emit tokenGated(collectionAddress, tokenId, limit); } /** * @notice setCollectionGating, sets gating data at collection level * @param collectionAddress the address of nft collection * @param perTokenLimit the gating limit of per token * @param perCollectionLimit the gating limit of collection */ function setCollectionGating( address collectionAddress, uint256 perTokenLimit, uint256 perCollectionLimit ) public nonReentrant { require( isAdmin(msg.sender), "sender should be a Admin " ); collectionLimitations[collectionAddress] = CollectionGatingData( perTokenLimit, perCollectionLimit ); emit collectionGated( collectionAddress, perCollectionLimit, perTokenLimit ); } /** * @notice acquireGating, updates gating data while acquiring the gated related info * @param collectionAddress the address of nft collection * @param tokenId the Token id * @param walletAddress the user wallet address who acquiring the info. */ function acquireGating( address collectionAddress, uint256 tokenId, address walletAddress ) public nonReentrant returns (bool) { require( walletAddress == tx.origin || walletAddress == msg.sender || isAdmin(msg.sender), "msg.sender should be wallet address or the admin" ); require( ownerOf(collectionAddress, tokenId, walletAddress), "allows only whitelisted collections tokens wallet" ); string memory gatingType; if ( collectionLimitations[collectionAddress].perTokenLimit != 0 && collectionLimitations[collectionAddress].perCollectionLimit > 0 && perTokenLimitation[collectionAddress][tokenId] < collectionLimitations[collectionAddress].perTokenLimit ) { collectionLimitations[collectionAddress].perCollectionLimit -= 1; perTokenLimitation[collectionAddress][tokenId] += 1; gatingType = "CollectionLevel"; } if ( tokenLimitations[collectionAddress][tokenId] > 0 && bytes(gatingType).length == 0 ) { tokenLimitations[collectionAddress][tokenId] -= 1; gatingType = "TokenLevel"; } if (bytes(gatingType).length == 0) { revert("the token in the collection does not have any limitation"); } emit gatingAcquired(collectionAddress, tokenId, msg.sender, gatingType); return true; } /** * @notice mint, mintng the nft * @param gatedCollection the address of gated nft collection * @param gatedTokenId the id of the gated token * @param walletAddress the user wallet address * @param mintCollectionAddress the collection address of minting process * @param tokenIdExt1155 the token id * @param approval the approval status */ function mint( address gatedCollection, uint256 gatedTokenId, address walletAddress, address mintCollectionAddress, uint256 tokenIdExt1155, Approval calldata approval ) public { if (adminApprovalRequired ) { require( isAdmin(approval.signer), "only owner or admin can sign for discount" ); require( !signatureUsed[approval.signature], "signature already applied" ); require( _verifySignature( walletAddress, approval.expirationTime, approval.signer, approval.nonce, approval.signature ), "invalid approval signature" ); signatureUsed[approval.signature] = true; } acquireGating(gatedCollection, gatedTokenId, walletAddress); uint256[] memory mintedTokenId = new uint256[](1); if ( IERC165(mintCollectionAddress).supportsInterface( ERC721_INTERFACE_ID ) ) { // Minting the ERC721 in a batch mintedTokenId[0] = IERC721CreatorCore(mintCollectionAddress) .mintExtension(walletAddress); } else if ( IERC165(mintCollectionAddress).supportsInterface( ERC1155_INTERFACE_ID ) ) { address[] memory to = new address[](1); uint256[] memory amounts = new uint256[](1); string[] memory uris = new string[](1); to[0] = walletAddress; amounts[0] = 1; if ( IERC1155CreatorCore(mintCollectionAddress).totalSupply( tokenIdExt1155 ) == 0 ) { // Minting ERC1155 of already existing tokens mintedTokenId = IERC1155CreatorCore(mintCollectionAddress) .mintExtensionNew(to, amounts, uris); } else if ( IERC1155CreatorCore(mintCollectionAddress).totalSupply( tokenIdExt1155 ) > 0 ) { uint256[] memory tokenIdNew = new uint256[](1); tokenIdNew[0] = tokenIdExt1155; // Minting new ERC1155 tokens IERC1155CreatorCore(mintCollectionAddress) .mintExtensionExisting(to, tokenIdNew, amounts); } } emit gatedMinting( gatedCollection, gatedTokenId, walletAddress, mintCollectionAddress, mintedTokenId ); } /** * @notice transfer, transfer the nft * @param gatedCollection the address of gated nft collection * @param gatedTokenId the id of the gated token * @param walletAddress the user wallet address * @param transferCollection the collection address of transfer process * @param transferTokenId the token id * @param transferOwner the owner address * @param approval the approval status */ function transfer( address gatedCollection, uint256 gatedTokenId, address walletAddress, address transferCollection, uint256 transferTokenId, address transferOwner, Approval calldata approval ) public { if (adminApprovalRequired ) { require( isAdmin(approval.signer), "only owner or admin can sign for discount" ); require( !signatureUsed[approval.signature], "signature already applied" ); require( _verifySignature( walletAddress, approval.expirationTime, approval.signer, approval.nonce, approval.signature ), "invalid approval signature" ); signatureUsed[approval.signature] = true; } acquireGating(gatedCollection, gatedTokenId, walletAddress); if ( IERC165(transferCollection).supportsInterface(ERC721_INTERFACE_ID) ) { // Transferring the ERC721 IERC721(transferCollection).safeTransferFrom( transferOwner, walletAddress, transferTokenId ); } else if ( IERC165(transferCollection).supportsInterface(ERC1155_INTERFACE_ID) ) { // Transferring the ERC1155 IERC1155(transferCollection).safeTransferFrom( transferOwner, walletAddress, transferTokenId, 1, "0x" ); } emit gatedTransfer( gatedCollection, gatedTokenId, walletAddress, transferCollection, transferTokenId, transferOwner ); } /** * @notice cancelTokenGating, cancels gating data at token level * @param collectionAddress the address of nft collection * @param tokenId the id of token * @param limit the gating limit of token id */ function cancelTokenGating( address collectionAddress, uint256 tokenId, uint256 limit ) public nonReentrant { require( isAdmin(msg.sender), "sender should be a Admin " ); delete tokenLimitations[collectionAddress][tokenId]; emit tokenGated(collectionAddress, tokenId, limit); } /** * @notice cancelCollectionGating, cancels gating data at collection level * @param collectionAddress the address of nft collection * @param perTokenLimit the gating limit of per token * @param perCollectionLimit the gating limit of collection */ function cancelCollectionGating( address collectionAddress, uint256 perTokenLimit, uint256 perCollectionLimit ) public nonReentrant { require( isAdmin(msg.sender) , "sender should be a Admin " ); delete collectionLimitations[collectionAddress]; emit collectionGated( collectionAddress, perCollectionLimit, perTokenLimit ); } /** * @notice getTokenLimitation, gets gating limit of token * @param gatedCollection the address of nft collection * @param gatedTokenId the id of gated token id */ function getTokenLimitation( address gatedCollection, uint256 gatedTokenId ) public view returns (uint256) { return tokenLimitations[gatedCollection][gatedTokenId]; } /** * @notice getCollectionLimitation, gets gating limit of collection * @param gatedCollection the address of nft collection */ function getCollectionLimitation( address gatedCollection ) public view returns (uint256 perCollectionLimit, uint256 perTokenLimit) { perCollectionLimit = collectionLimitations[gatedCollection] .perCollectionLimit; perTokenLimit = collectionLimitations[gatedCollection].perTokenLimit; } /** * @notice getCollectionTokenLimit, gets gating limit gated collection of given token id * @param gatedCollection the address of nft collection * @param gatedTokenId the id of gated token id * @param walletAddress the address that owns the nft */ function getCollectionTokenLimit( address gatedCollection, uint256 gatedTokenId, address walletAddress ) public view returns (uint256 perTokenLimitRemining) { if(ownerOf(gatedCollection,gatedTokenId, walletAddress)) { perTokenLimitRemining = collectionLimitations[gatedCollection].perTokenLimit - perTokenLimitation[gatedCollection][gatedTokenId]; } else { perTokenLimitRemining = 0; } } /** * @notice Verifes the signature * @param buyer the buyer address * @param expirationTime the exprire time stamp of signature * @param _signer the signer address * @param nonce the nonce used for sign generation * @param _signature the signature */ function _verifySignature( address buyer, uint32 expirationTime, address _signer, string calldata nonce, bytes calldata _signature ) internal view returns (bool) { require( expirationTime >= block.timestamp, "admin signature is already expired" ); return keccak256( abi.encodePacked( buyer, expirationTime, nonce, "GATING", block.chainid ) ).toEthSignedMessageHash().recover(_signature) == _signer; } /** * @notice ownerOf, gets owner address * @param collectionAddress the address of collection contract * @param tokenId the id of token * @param sender the sender address */ function ownerOf( address collectionAddress, uint256 tokenId, address sender ) internal view returns (bool isOwner) { if (IERC165(collectionAddress).supportsInterface(ERC721_INTERFACE_ID)) { IERC721 erc721 = IERC721(collectionAddress); return erc721.ownerOf(tokenId) == sender; } if ( IERC165(collectionAddress).supportsInterface(ERC1155_INTERFACE_ID) ) { IERC1155 erc1155 = IERC1155(collectionAddress); return erc1155.balanceOf(sender, tokenId) > 0; } } /** * @notice updateAdminApproval, updates the admin approval * @param _adminApprovalRequired the boolean value of _adminApprovalRequired */ function updateAdminApproval(bool _adminApprovalRequired) external adminRequired { adminApprovalRequired = _adminApprovalRequired; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "../../../openzeppelin/utils/introspection/ERC165.sol"; import "../../../openzeppelin/utils/structs/EnumerableSet.sol"; import "../../../openzeppelin/access/Ownable.sol"; import "./IAdminControl.sol"; abstract contract AdminControl is Ownable, IAdminControl, ERC165 { using EnumerableSet for EnumerableSet.AddressSet; // Track registered admins EnumerableSet.AddressSet private _admins; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IAdminControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Only allows approved admins to call the specified function */ modifier adminRequired() { require( owner() == msg.sender || _admins.contains(msg.sender), "AdminControl: Must be owner or admin" ); _; } /** * @dev See {IAdminControl-getAdmins}. */ function getAdmins() external view override returns (address[] memory admins) { admins = new address[](_admins.length()); for (uint256 i = 0; i < _admins.length(); i++) { admins[i] = _admins.at(i); } return admins; } /** * @dev See {IAdminControl-approveAdmin}. */ function approveAdmin(address admin) external override onlyOwner { if (!_admins.contains(admin)) { emit AdminApproved(admin, msg.sender); _admins.add(admin); } } /** * @dev See {IAdminControl-revokeAdmin}. */ function revokeAdmin(address admin) external override onlyOwner { if (_admins.contains(admin)) { emit AdminRevoked(admin, msg.sender); _admins.remove(admin); } } /** * @dev See {IAdminControl-isAdmin}. */ function isAdmin(address admin) public view override returns (bool) { return (owner() == admin || _admins.contains(admin)); } }
// SPDX-License-Identifier: MIT 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; /// @custom:oz-upgrades-unsafe-allow constructor 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 make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "./CreatorCore.sol"; /** * @dev Core ERC1155 creator interface */ interface IERC1155CreatorCore is ICreatorCore { /** * @dev mint a token with no extension. Can only be called by an admin. * * @param to - Can be a single element array (all tokens go to same address) or multi-element array (single token to many recipients) * @param amounts - Can be a single element array (all recipients get the same amount) or a multi-element array * @param uris - If no elements, all tokens use the default uri. * If any element is an empty string, the corresponding token uses the default uri. * * * Requirements: If to is a multi-element array, then uris must be empty or single element array * If to is a multi-element array, then amounts must be a single element array or a multi-element array of the same size * If to is a single element array, uris must be empty or the same length as amounts * * Examples: * mintBaseNew(['0x....1', '0x....2'], [1], []) * Mints a single new token, and gives 1 each to '0x....1' and '0x....2'. Token uses default uri. * * mintBaseNew(['0x....1', '0x....2'], [1, 2], []) * Mints a single new token, and gives 1 to '0x....1' and 2 to '0x....2'. Token uses default uri. * * mintBaseNew(['0x....1'], [1, 2], ["", "http://token2.com"]) * Mints two new tokens to '0x....1'. 1 of the first token, 2 of the second. 1st token uses default uri, second uses "http://token2.com". * * @return Returns list of tokenIds minted */ function mintBaseNew(address[] calldata to, uint256[] calldata amounts, string[] calldata uris) external returns (uint256[] memory); /** * @dev batch mint existing token with no extension. Can only be called by an admin. * * @param to - Can be a single element array (all tokens go to same address) or multi-element array (single token to many recipients) * @param tokenIds - Can be a single element array (all recipients get the same token) or a multi-element array * @param amounts - Can be a single element array (all recipients get the same amount) or a multi-element array * * Requirements: If any of the parameters are multi-element arrays, they need to be the same length as other multi-element arrays * * Examples: * mintBaseExisting(['0x....1', '0x....2'], [1], [10]) * Mints 10 of tokenId 1 to each of '0x....1' and '0x....2'. * * mintBaseExisting(['0x....1', '0x....2'], [1, 2], [10, 20]) * Mints 10 of tokenId 1 to '0x....1' and 20 of tokenId 2 to '0x....2'. * * mintBaseExisting(['0x....1'], [1, 2], [10, 20]) * Mints 10 of tokenId 1 and 20 of tokenId 2 to '0x....1'. * * mintBaseExisting(['0x....1', '0x....2'], [1], [10, 20]) * Mints 10 of tokenId 1 to '0x....1' and 20 of tokenId 1 to '0x....2'. * */ function mintBaseExisting(address[] calldata to, uint256[] calldata tokenIds, uint256[] calldata amounts) external; /** * @dev mint a token from an extension. Can only be called by a registered extension. * * @param to - Can be a single element array (all tokens go to same address) or multi-element array (single token to many recipients) * @param amounts - Can be a single element array (all recipients get the same amount) or a multi-element array * @param uris - If no elements, all tokens use the default uri. * If any element is an empty string, the corresponding token uses the default uri. * * * Requirements: If to is a multi-element array, then uris must be empty or single element array * If to is a multi-element array, then amounts must be a single element array or a multi-element array of the same size * If to is a single element array, uris must be empty or the same length as amounts * * Examples: * mintExtensionNew(['0x....1', '0x....2'], [1], []) * Mints a single new token, and gives 1 each to '0x....1' and '0x....2'. Token uses default uri. * * mintExtensionNew(['0x....1', '0x....2'], [1, 2], []) * Mints a single new token, and gives 1 to '0x....1' and 2 to '0x....2'. Token uses default uri. * * mintExtensionNew(['0x....1'], [1, 2], ["", "http://token2.com"]) * Mints two new tokens to '0x....1'. 1 of the first token, 2 of the second. 1st token uses default uri, second uses "http://token2.com". * * @return Returns list of tokenIds minted */ function mintExtensionNew(address[] calldata to, uint256[] calldata amounts, string[] calldata uris) external returns (uint256[] memory); /** * @dev batch mint existing token from extension. Can only be called by a registered extension. * * @param to - Can be a single element array (all tokens go to same address) or multi-element array (single token to many recipients) * @param tokenIds - Can be a single element array (all recipients get the same token) or a multi-element array * @param amounts - Can be a single element array (all recipients get the same amount) or a multi-element array * * Requirements: If any of the parameters are multi-element arrays, they need to be the same length as other multi-element arrays * * Examples: * mintExtensionExisting(['0x....1', '0x....2'], [1], [10]) * Mints 10 of tokenId 1 to each of '0x....1' and '0x....2'. * * mintExtensionExisting(['0x....1', '0x....2'], [1, 2], [10, 20]) * Mints 10 of tokenId 1 to '0x....1' and 20 of tokenId 2 to '0x....2'. * * mintExtensionExisting(['0x....1'], [1, 2], [10, 20]) * Mints 10 of tokenId 1 and 20 of tokenId 2 to '0x....1'. * * mintExtensionExisting(['0x....1', '0x....2'], [1], [10, 20]) * Mints 10 of tokenId 1 to '0x....1' and 20 of tokenId 1 to '0x....2'. * */ function mintExtensionExisting(address[] calldata to, uint256[] calldata tokenIds, uint256[] calldata amounts) external; /** * @dev burn tokens. Can only be called by token owner or approved address. * On burn, calls back to the registered extension's onBurn method */ function burn(address account, uint256[] calldata tokenIds, uint256[] calldata amounts) external; /** * @dev Total amount of tokens in with a given tokenId. */ function totalSupply(uint256 tokenId) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "./ICreatorCore.sol"; /** * @dev Core ERC721 creator interface */ interface IERC721CreatorCore is ICreatorCore { /** * @dev mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBase(address to) external returns (uint256); /** * @dev mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBase(address to, string calldata uri) external returns (uint256); /** * @dev batch mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory); /** * @dev batch mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory); /** * @dev mint a token. Can only be called by a registered extension. * Returns tokenId minted */ function mintExtension(address to) external returns (uint256); /** * @dev mint a token. Can only be called by a registered extension. * Returns tokenId minted */ function mintExtension(address to, string calldata uri) external returns (uint256); /** * @dev batch mint a token. Can only be called by a registered extension. * Returns tokenIds minted */ function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory); /** * @dev batch mint a token. Can only be called by a registered extension. * Returns tokenId minted */ function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory); /** * @dev burn a token. Can only be called by token owner or approved address. * On burn, calls back to the registered extension's onBurn method */ function burn(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFoundation { /* * bytes4(keccak256('getFees(uint256)')) == 0xd5a06d4c * * => 0xd5a06d4c = 0xd5a06d4c */ function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory); } interface IFoundationTreasuryNode { function getFoundationTreasury() external view returns (address payable); } interface IFoundationTreasury { function isAdmin(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Nifty builder instance */ interface INiftyBuilderInstance { function niftyRegistryContract() external view returns (address); } /** * @dev Nifty registry */ interface INiftyRegistry { /** * @dev function to see if sending key is valid */ function isValidNiftySender(address sending_key) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControlUpgradeable { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165Checker.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return _supportsERC165Interface(account, type(IERC165).interfaceId) && !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return supportsERC165(account) && _supportsERC165Interface(account, interfaceId); } /** * @dev Returns a boolean array where each value corresponds to the * interfaces passed in and whether they're supported or not. This allows * you to batch check interfaces for a contract where your expectation * is that some interfaces may not be supported. * * See {IERC165-supportsInterface}. * * _Available since v3.4._ */ function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool[] memory) { // an array of booleans corresponding to interfaceIds and whether they're supported or not bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); // query support of ERC165 itself if (supportsERC165(account)) { // query support of each interface in interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]); } } return interfaceIdsSupported; } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with {supportsERC165}. * Interface identification is specified in ERC-165. */ function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId); (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams); if (result.length < 32) return false; return success && abi.decode(result, (bool)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "../../../openzeppelin/utils/structs/EnumerableSet.sol"; import "../../../openzeppelin/utils/introspection/ERC165.sol"; import "../../../openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; import "./IAdminControl.sol"; abstract contract AdminControlUpgradeable is OwnableUpgradeable, IAdminControl, ERC165 { using EnumerableSet for EnumerableSet.AddressSet; // Track registered admins EnumerableSet.AddressSet private _admins; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IAdminControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Only allows approved admins to call the specified function */ modifier adminRequired() { require( owner() == msg.sender || _admins.contains(msg.sender), "AdminControl: Must be owner or admin" ); _; } /** * @dev See {IAdminControl-getAdmins}. */ function getAdmins() external view override returns (address[] memory admins) { admins = new address[](_admins.length()); for (uint256 i = 0; i < _admins.length(); i++) { admins[i] = _admins.at(i); } return admins; } /** * @dev See {IAdminControl-approveAdmin}. */ function approveAdmin(address admin) external override onlyOwner { if (!_admins.contains(admin)) { emit AdminApproved(admin, msg.sender); _admins.add(admin); } } /** * @dev See {IAdminControl-revokeAdmin}. */ function revokeAdmin(address admin) external override onlyOwner { if (_admins.contains(admin)) { emit AdminRevoked(admin, msg.sender); _admins.remove(admin); } } /** * @dev See {IAdminControl-isAdmin}. */ function isAdmin(address admin) public view override returns (bool) { return (owner() == admin || _admins.contains(admin)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.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`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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 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); /** * @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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (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 v4.4.0 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "../../../openzeppelin/utils/introspection/IERC165.sol"; /** * @dev Interface for admin control */ interface IAdminControl is IERC165 { event AdminApproved(address indexed account, address indexed sender); event AdminRevoked(address indexed account, address indexed sender); /** * @dev gets address of all admins */ function getAdmins() external view returns (address[] memory); /** * @dev add an admin. Can only be called by contract owner. */ function approveAdmin(address admin) external; /** * @dev remove an admin. Can only be called by contract owner. */ function revokeAdmin(address admin) external; /** * @dev checks whether or not given address is an admin * Returns True if they are */ function isAdmin(address admin) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal initializer { __Context_init_unchained(); __Ownable_init_unchained(); } function __Ownable_init_unchained() internal initializer { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (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.0 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT 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 () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "../../../openzeppelin/utils/introspection/IERC165.sol"; /** * @dev Core creator interface */ interface ICreatorCore is IERC165 { event ExtensionRegistered( address indexed extension, address indexed sender ); event ExtensionUnregistered( address indexed extension, address indexed sender ); event ExtensionBlacklisted( address indexed extension, address indexed sender ); event MintPermissionsUpdated( address indexed extension, address indexed permissions, address indexed sender ); event RoyaltiesUpdated( uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints ); event DefaultRoyaltiesUpdated( address payable[] receivers, uint256[] basisPoints ); event ExtensionRoyaltiesUpdated( address indexed extension, address payable[] receivers, uint256[] basisPoints ); event ExtensionApproveTransferUpdated( address indexed extension, bool enabled ); /** * @dev gets address of all extensions */ function getExtensions() external view returns (address[] memory); /** * @dev add an extension. Can only be called by contract owner or admin. * extension address must point to a contract implementing ICreatorExtension. * Returns True if newly added, False if already added. */ function registerExtension(address extension, string calldata baseURI) external; /** * @dev add an extension. Can only be called by contract owner or admin. * extension address must point to a contract implementing ICreatorExtension. * Returns True if newly added, False if already added. */ function registerExtension( address extension, string calldata baseURI, bool baseURIIdentical ) external; /** * @dev add an extension. Can only be called by contract owner or admin. * Returns True if removed, False if already removed. */ function unregisterExtension(address extension) external; /** * @dev blacklist an extension. Can only be called by contract owner or admin. * This function will destroy all ability to reference the metadata of any tokens created * by the specified extension. It will also unregister the extension if needed. * Returns True if removed, False if already removed. */ function blacklistExtension(address extension) external; /** * @dev set the baseTokenURI of an extension. Can only be called by extension. */ function setBaseTokenURIExtension(string calldata uri) external; /** * @dev set the baseTokenURI of an extension. Can only be called by extension. * For tokens with no uri configured, tokenURI will return "uri+tokenId" */ function setBaseTokenURIExtension(string calldata uri, bool identical) external; /** * @dev set the common prefix of an extension. Can only be called by extension. * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI" * Useful if you want to use ipfs/arweave */ function setTokenURIPrefixExtension(string calldata prefix) external; /** * @dev set the tokenURI of a token extension. Can only be called by extension that minted token. */ function setTokenURIExtension(uint256 tokenId, string calldata uri) external; /** * @dev set the tokenURI of a token extension for multiple tokens. Can only be called by extension that minted token. */ function setTokenURIExtension( uint256[] memory tokenId, string[] calldata uri ) external; /** * @dev set the baseTokenURI for tokens with no extension. Can only be called by owner/admin. * For tokens with no uri configured, tokenURI will return "uri+tokenId" */ function setBaseTokenURI(string calldata uri) external; /** * @dev set the common prefix for tokens with no extension. Can only be called by owner/admin. * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI" * Useful if you want to use ipfs/arweave */ function setTokenURIPrefix(string calldata prefix) external; /** * @dev set the tokenURI of a token with no extension. Can only be called by owner/admin. */ function setTokenURI(uint256 tokenId, string calldata uri) external; /** * @dev set the tokenURI of multiple tokens with no extension. Can only be called by owner/admin. */ function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external; /** * @dev set a permissions contract for an extension. Used to control minting. */ function setMintPermissions(address extension, address permissions) external; /** * @dev Configure so transfers of tokens created by the caller (must be extension) gets approval * from the extension before transferring */ function setApproveTransferExtension(bool enabled) external; /** * @dev get the extension of a given token */ function tokenExtension(uint256 tokenId) external view returns (address); /** * @dev Set default royalties */ function setRoyalties( address payable[] calldata receivers, uint256[] calldata basisPoints ) external; /** * @dev Set royalties of a token */ function setRoyalties( uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints ) external; /** * @dev Set royalties of an extension */ function setRoyaltiesExtension( address extension, address payable[] calldata receivers, uint256[] calldata basisPoints ) external; /** * @dev Get royalites of a token. Returns list of receivers and basisPoints */ function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory); // Royalty support for various other standards function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory); function getFeeBps(uint256 tokenId) external view returns (uint256[] memory); function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory); function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "../../../openzeppelin/security/ReentrancyGuard.sol"; import "../../../openzeppelin/utils/Strings.sol"; import "../../../openzeppelin/utils/introspection/ERC165.sol"; import "../../../openzeppelin/utils/introspection/ERC165Checker.sol"; import "../../../openzeppelin/utils/structs/EnumerableSet.sol"; import "../../../openzeppelin-upgradeable/utils/AddressUpgradeable.sol"; import "../extensions/ICreatorExtensionTokenURI.sol"; import "./ICreatorCore.sol"; /** * @dev Core creator implementation */ abstract contract CreatorCore is ReentrancyGuard, ICreatorCore, ERC165 { using Strings for uint256; using EnumerableSet for EnumerableSet.AddressSet; using AddressUpgradeable for address; /// @custom:oz-upgrades-unsafe-allow state-variable-assignment uint256 _tokenCount = 0; // Track registered extensions data EnumerableSet.AddressSet internal _extensions; EnumerableSet.AddressSet internal _blacklistedExtensions; mapping(address => address) internal _extensionPermissions; mapping(address => bool) internal _extensionApproveTransfers; // For tracking which extension a token was minted by mapping(uint256 => address) internal _tokensExtension; // The baseURI for a given extension mapping(address => string) private _extensionBaseURI; mapping(address => bool) private _extensionBaseURIIdentical; // The prefix for any tokens with a uri configured mapping(address => string) private _extensionURIPrefix; // Mapping for individual token URIs mapping(uint256 => string) internal _tokenURIs; // Royalty configurations mapping(address => address payable[]) internal _extensionRoyaltyReceivers; mapping(address => uint256[]) internal _extensionRoyaltyBPS; mapping(uint256 => address payable[]) internal _tokenRoyaltyReceivers; mapping(uint256 => uint256[]) internal _tokenRoyaltyBPS; // Allowist EnumerableSet.AddressSet internal _MarketplaceAllowList; bool internal _marketplaceRestricted; /** * External interface identifiers for royalties */ /** * @dev CreatorCore * * bytes4(keccak256('getRoyalties(uint256)')) == 0xbb3bafd6 * * => 0xbb3bafd6 = 0xbb3bafd6 */ bytes4 private constant _INTERFACE_ID_ROYALTIES_CREATORCORE = 0xbb3bafd6; /** * @dev Rarible: RoyaltiesV1 * * bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb * bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f * * => 0xb9c4d9fb ^ 0x0ebd4c7f = 0xb7799584 */ bytes4 private constant _INTERFACE_ID_ROYALTIES_RARIBLE = 0xb7799584; /** * @dev Foundation * * bytes4(keccak256('getFees(uint256)')) == 0xd5a06d4c * * => 0xd5a06d4c = 0xd5a06d4c */ bytes4 private constant _INTERFACE_ID_ROYALTIES_FOUNDATION = 0xd5a06d4c; /** * @dev EIP-2981 * * bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a * * => 0x2a55205a = 0x2a55205a */ bytes4 private constant _INTERFACE_ID_ROYALTIES_EIP2981 = 0x2a55205a; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(ICreatorCore).interfaceId || super.supportsInterface(interfaceId) || interfaceId == _INTERFACE_ID_ROYALTIES_CREATORCORE || interfaceId == _INTERFACE_ID_ROYALTIES_RARIBLE || interfaceId == _INTERFACE_ID_ROYALTIES_FOUNDATION || interfaceId == _INTERFACE_ID_ROYALTIES_EIP2981; } /** * @dev Only allows registered extensions to call the specified function */ modifier extensionRequired() { require( _extensions.contains(msg.sender), "Must be registered extension" ); _; } /** * @dev Only allows non-blacklisted extensions */ modifier nonBlacklistRequired(address extension) { require( !_blacklistedExtensions.contains(extension), "Extension blacklisted" ); _; } /** * @dev See {ICreatorCore-getExtensions}. */ function getExtensions() external view override returns (address[] memory extensions) { extensions = new address[](_extensions.length()); for (uint256 i = 0; i < _extensions.length(); i++) { extensions[i] = _extensions.at(i); } return extensions; } /** * @dev Register an extension */ function _registerExtension( address extension, string calldata baseURI, bool baseURIIdentical ) internal { require(extension != address(this), "Creator: Invalid"); require( extension.isContract(), "Creator: Extension must be a contract" ); if (!_extensions.contains(extension)) { _extensionBaseURI[extension] = baseURI; _extensionBaseURIIdentical[extension] = baseURIIdentical; emit ExtensionRegistered(extension, msg.sender); _extensions.add(extension); } } /** * @dev Unregister an extension */ function _unregisterExtension(address extension) internal { if (_extensions.contains(extension)) { emit ExtensionUnregistered(extension, msg.sender); _extensions.remove(extension); } } /** * @dev Blacklist an extension */ function _blacklistExtension(address extension) internal { require(extension != address(this), "Cannot blacklist yourself"); if (_extensions.contains(extension)) { emit ExtensionUnregistered(extension, msg.sender); _extensions.remove(extension); } if (!_blacklistedExtensions.contains(extension)) { emit ExtensionBlacklisted(extension, msg.sender); _blacklistedExtensions.add(extension); } } /** * @dev Set base token uri for an extension */ function _setBaseTokenURIExtension(string calldata uri, bool identical) internal { _extensionBaseURI[msg.sender] = uri; _extensionBaseURIIdentical[msg.sender] = identical; } /** * @dev Set token uri prefix for an extension */ function _setTokenURIPrefixExtension(string calldata prefix) internal { _extensionURIPrefix[msg.sender] = prefix; } /** * @dev Set token uri for a token of an extension */ function _setTokenURIExtension(uint256 tokenId, string calldata uri) internal { require(_tokensExtension[tokenId] == msg.sender, "Invalid token"); _tokenURIs[tokenId] = uri; } /** * @dev Set base token uri for tokens with no extension */ function _setBaseTokenURI(string memory uri) internal { _extensionBaseURI[address(this)] = uri; } /** * @dev Set token uri prefix for tokens with no extension */ function _setTokenURIPrefix(string calldata prefix) internal { _extensionURIPrefix[address(this)] = prefix; } /** * @dev Set token uri for a token with no extension */ function _setTokenURI(uint256 tokenId, string calldata uri) internal { require(_tokensExtension[tokenId] == address(this), "Invalid token"); _tokenURIs[tokenId] = uri; } /** * @dev Retrieve a token's URI */ function _tokenURI(uint256 tokenId) internal view returns (string memory) { address extension = _tokensExtension[tokenId]; require( !_blacklistedExtensions.contains(extension), "Extension blacklisted" ); if (bytes(_tokenURIs[tokenId]).length != 0) { if (bytes(_extensionURIPrefix[extension]).length != 0) { return string( abi.encodePacked( _extensionURIPrefix[extension], _tokenURIs[tokenId] ) ); } return _tokenURIs[tokenId]; } if ( ERC165Checker.supportsInterface( extension, type(ICreatorExtensionTokenURI).interfaceId ) ) { return ICreatorExtensionTokenURI(extension).tokenURI( address(this), tokenId ); } if (bytes(_extensionBaseURI[extension]).length != 0) { if (!_extensionBaseURIIdentical[extension]) { return string( abi.encodePacked( _extensionBaseURI[extension], tokenId.toString() ) ); } else { return _extensionBaseURI[extension]; } } else { if (!_extensionBaseURIIdentical[address(this)]) { return string( abi.encodePacked( _extensionBaseURI[address(this)], tokenId.toString() ) ); }else{ return _extensionBaseURI[address(this)]; } } } /** * Get token extension */ function _tokenExtension(uint256 tokenId) internal view returns (address extension) { extension = _tokensExtension[tokenId]; require(extension != address(this), "No extension for token"); require( !_blacklistedExtensions.contains(extension), "Extension blacklisted" ); return extension; } /** * Helper to get royalties for a token */ function _getRoyalties(uint256 tokenId) internal view returns (address payable[] storage, uint256[] storage) { return (_getRoyaltyReceivers(tokenId), _getRoyaltyBPS(tokenId)); } /** * Helper to get royalty receivers for a token */ function _getRoyaltyReceivers(uint256 tokenId) internal view returns (address payable[] storage) { if (_tokenRoyaltyReceivers[tokenId].length > 0) { return _tokenRoyaltyReceivers[tokenId]; } else if ( _extensionRoyaltyReceivers[_tokensExtension[tokenId]].length > 0 ) { return _extensionRoyaltyReceivers[_tokensExtension[tokenId]]; } return _extensionRoyaltyReceivers[address(this)]; } /** * Helper to get royalty basis points for a token */ function _getRoyaltyBPS(uint256 tokenId) internal view returns (uint256[] storage) { if (_tokenRoyaltyBPS[tokenId].length > 0) { return _tokenRoyaltyBPS[tokenId]; } else if (_extensionRoyaltyBPS[_tokensExtension[tokenId]].length > 0) { return _extensionRoyaltyBPS[_tokensExtension[tokenId]]; } return _extensionRoyaltyBPS[address(this)]; } function _getRoyaltyInfo(uint256 tokenId, uint256 value) internal view returns (address receiver, uint256 amount) { address payable[] storage receivers = _getRoyaltyReceivers(tokenId); require(receivers.length <= 1, "More than 1 royalty receiver"); if (receivers.length == 0) { return (address(this), 0); } return (receivers[0], (_getRoyaltyBPS(tokenId)[0] * value) / 10000); } /** * Set royalties for a token */ function _setRoyalties( uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints ) internal { require(receivers.length == basisPoints.length, "Invalid input"); uint256 totalBasisPoints; for (uint256 i = 0; i < basisPoints.length; i++) { totalBasisPoints += basisPoints[i]; } require(totalBasisPoints < 10000, "Invalid total royalties"); _tokenRoyaltyReceivers[tokenId] = receivers; _tokenRoyaltyBPS[tokenId] = basisPoints; emit RoyaltiesUpdated(tokenId, receivers, basisPoints); } /** * Set royalties for all tokens of an extension */ function _setRoyaltiesExtension( address extension, address payable[] calldata receivers, uint256[] calldata basisPoints ) internal { require(receivers.length == basisPoints.length, "Invalid input"); uint256 totalBasisPoints; for (uint256 i = 0; i < basisPoints.length; i++) { totalBasisPoints += basisPoints[i]; } require(totalBasisPoints < 10000, "Invalid total royalties"); _extensionRoyaltyReceivers[extension] = receivers; _extensionRoyaltyBPS[extension] = basisPoints; if (extension == address(this)) { emit DefaultRoyaltiesUpdated(receivers, basisPoints); } else { emit ExtensionRoyaltiesUpdated(extension, receivers, basisPoints); } } /** * Set third party transfer restrictions */ function _setMarketplaceRestriction(bool restricted, address[] calldata allowedMarketplace )internal { _marketplaceRestricted = restricted; if(_marketplaceRestricted) { for (uint256 i = 0; i < allowedMarketplace.length; i++) { _MarketplaceAllowList.add(allowedMarketplace[i]); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal initializer { __Context_init_unchained(); } function __Context_init_unchained() internal initializer { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "../../../openzeppelin/utils/introspection/IERC165.sol"; /** * @dev Implement this if you want your extension to have overloadable URI's */ interface ICreatorExtensionTokenURI is IERC165 { /** * Get the uri for a given creator/tokenId */ function tokenURI(address creator, uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bool","name":"_adminApprovalRequired","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"gatedCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"perCollectionLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"petTokenLimit","type":"uint256"}],"name":"collectionGated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gatedCollection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"mintedWallet","type":"address"},{"indexed":false,"internalType":"address","name":"mintingContract","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIdMinted","type":"uint256[]"}],"name":"gatedMinting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gatedCollection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"transferWallet","type":"address"},{"indexed":false,"internalType":"address","name":"transferContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"transferTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"transferOwner","type":"address"}],"name":"gatedTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"gatedCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"gatedTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"acquiredAddress","type":"address"},{"indexed":false,"internalType":"string","name":"gatingType","type":"string"}],"name":"gatingAcquired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"gatedCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"}],"name":"tokenGated","type":"event"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"walletAddress","type":"address"}],"name":"acquireGating","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminApprovalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"approveAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"internalType":"uint256","name":"perTokenLimit","type":"uint256"},{"internalType":"uint256","name":"perCollectionLimit","type":"uint256"}],"name":"cancelCollectionGating","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"cancelTokenGating","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmins","outputs":[{"internalType":"address[]","name":"admins","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gatedCollection","type":"address"}],"name":"getCollectionLimitation","outputs":[{"internalType":"uint256","name":"perCollectionLimit","type":"uint256"},{"internalType":"uint256","name":"perTokenLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gatedCollection","type":"address"},{"internalType":"uint256","name":"gatedTokenId","type":"uint256"},{"internalType":"address","name":"walletAddress","type":"address"}],"name":"getCollectionTokenLimit","outputs":[{"internalType":"uint256","name":"perTokenLimitRemining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gatedCollection","type":"address"},{"internalType":"uint256","name":"gatedTokenId","type":"uint256"}],"name":"getTokenLimitation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gatedCollection","type":"address"},{"internalType":"uint256","name":"gatedTokenId","type":"uint256"},{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"address","name":"mintCollectionAddress","type":"address"},{"internalType":"uint256","name":"tokenIdExt1155","type":"uint256"},{"components":[{"internalType":"uint32","name":"expirationTime","type":"uint32"},{"internalType":"string","name":"nonce","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct TokenGating.Approval","name":"approval","type":"tuple"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"revokeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"internalType":"uint256","name":"perTokenLimit","type":"uint256"},{"internalType":"uint256","name":"perCollectionLimit","type":"uint256"}],"name":"setCollectionGating","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setTokenGating","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"signatureUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"gatedCollection","type":"address"},{"internalType":"uint256","name":"gatedTokenId","type":"uint256"},{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"address","name":"transferCollection","type":"address"},{"internalType":"uint256","name":"transferTokenId","type":"uint256"},{"internalType":"address","name":"transferOwner","type":"address"},{"components":[{"internalType":"uint32","name":"expirationTime","type":"uint32"},{"internalType":"string","name":"nonce","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct TokenGating.Approval","name":"approval","type":"tuple"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_adminApprovalRequired","type":"bool"}],"name":"updateAdminApproval","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162002b3638038062002b36833981016040819052620000349162000091565b6001600081815581546001600160a01b031916339081179092556040518291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506004805460ff1916911515919091179055620000bc565b600060208284031215620000a457600080fd5b81518015158114620000b557600080fd5b9392505050565b612a6a80620000cc6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c8063715018a6116100b8578063a72c9c6c1161007c578063a72c9c6c146102cc578063bb10c829146102df578063d421ab021461030d578063f2fde38b14610320578063f35653d514610333578063f7f3a5851461034657600080fd5b8063715018a61461023f5780637bcca4d91461024757806382892b13146102685780638da5cb5b1461029e57806393dec796146102b957600080fd5b806331ae450b116100ff57806331ae450b146101ac5780635821e1c2146101c15780635f23d016146101d45780636822065c146102195780636d73e6691461022c57600080fd5b806301ffc9a71461013c57806324d7806c146101645780632a6cc247146101775780632ca355421461018c5780632d34567014610199575b600080fd5b61014f61014a366004612457565b610359565b60405190151581526020015b60405180910390f35b61014f610172366004612171565b610390565b61018a61018536600461233b565b6103c9565b005b60045461014f9060ff1681565b61018a6101a7366004612171565b61048b565b6101b461050b565b60405161015b919061270d565b61014f6101cf3660046121d7565b6105ba565b6102046101e2366004612171565b6001600160a01b03166000908152600560205260409020600181015490549091565b6040805192835260208301919091520161015b565b61018a61022736600461233b565b610951565b61018a61023a366004612171565b610a28565b61018a610aa2565b61025a6102553660046121d7565b610b16565b60405190815260200161015b565b61025a6102763660046121ab565b6001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6001546040516001600160a01b03909116815260200161015b565b61018a6102c736600461241d565b610b73565b61018a6102da36600461233b565b610c0c565b61014f6102ed366004612481565b805160208183018101805160088252928201919093012091525460ff1681565b61018a61031b3660046122b4565b610cc2565b61018a61032e366004612171565b611368565b61018a610341366004612219565b611453565b61018a61035436600461233b565b61180f565b60006001600160e01b03198216632a9f3abf60e11b148061038a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000816001600160a01b03166103ae6001546001600160a01b031690565b6001600160a01b0316148061038a575061038a6002836118b1565b600260005414156103f55760405162461bcd60e51b81526004016103ec906128aa565b60405180910390fd5b600260005561040333610390565b61041f5760405162461bcd60e51b81526004016103ec906127f5565b6001600160a01b038316600090815260066020908152604080832085845290915280822091909155517fbe2efdf01e931999aed0444a32f53a5cbc427e5a9bfba3c155653665ecd985db90610479908590859085906126ec565b60405180910390a15050600160005550565b6001546001600160a01b031633146104b55760405162461bcd60e51b81526004016103ec90612875565b6104c06002826118b1565b156105085760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a36105066002826118d3565b505b50565b606061051760026118e8565b67ffffffffffffffff81111561052f5761052f6129fb565b604051908082528060200260200182016040528015610558578160200160208202803683370190505b50905060005b61056860026118e8565b8110156105b65761057a6002826118f2565b82828151811061058c5761058c6129e5565b6001600160a01b0390921660209283029190910190910152806105ae81612988565b91505061055e565b5090565b6000600260005414156105df5760405162461bcd60e51b81526004016103ec906128aa565b60026000556001600160a01b03821632148061060357506001600160a01b03821633145b80610612575061061233610390565b6106775760405162461bcd60e51b815260206004820152603060248201527f6d73672e73656e6465722073686f756c642062652077616c6c6574206164647260448201526f32b9b99037b9103a34329030b236b4b760811b60648201526084016103ec565b6106828484846118fe565b6106e85760405162461bcd60e51b815260206004820152603160248201527f616c6c6f7773206f6e6c792077686974656c697374656420636f6c6c656374696044820152701bdb9cc81d1bdad95b9cc81dd85b1b195d607a1b60648201526084016103ec565b6001600160a01b0384166000908152600560205260409020546060901580159061072c57506001600160a01b03851660009081526005602052604090206001015415155b801561076257506001600160a01b0385166000908152600560209081526040808320546007835281842088855290925290912054105b156107fc576001600160a01b03851660009081526005602052604081206001908101805491929091610795908490612971565b90915550506001600160a01b038516600090815260076020908152604080832087845290915281208054600192906107ce908490612959565b909155505060408051808201909152600f81526e10dbdb1b1958dd1a5bdb93195d995b608a1b602082015290505b6001600160a01b03851660009081526006602090815260408083208784529091529020541580159061082d57508051155b1561088f576001600160a01b03851660009081526006602090815260408083208784529091528120805460019290610866908490612971565b909155505060408051808201909152600a815269151bdad95b93195d995b60b21b602082015290505b80516109035760405162461bcd60e51b815260206004820152603860248201527f74686520746f6b656e20696e2074686520636f6c6c656374696f6e20646f657360448201527f206e6f74206861766520616e79206c696d69746174696f6e000000000000000060648201526084016103ec565b7f83f7f1ea4d680976c2472903a9e678bc1d856b3d76fbd0f7d40a69098557f5f08585338460405161093894939291906126af565b60405180910390a1600191505060016000559392505050565b600260005414156109745760405162461bcd60e51b81526004016103ec906128aa565b600260005561098233610390565b6109ce5760405162461bcd60e51b815260206004820152601860248201527f73656e6465722073686f756c6420626520612041646d696e000000000000000060448201526064016103ec565b6001600160a01b038316600090815260066020908152604080832085845290915290819020829055517fbe2efdf01e931999aed0444a32f53a5cbc427e5a9bfba3c155653665ecd985db90610479908590859085906126ec565b6001546001600160a01b03163314610a525760405162461bcd60e51b81526004016103ec90612875565b610a5d6002826118b1565b6105085760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3610506600282611b2e565b6001546001600160a01b03163314610acc5760405162461bcd60e51b81526004016103ec90612875565b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b6000610b238484846118fe565b15610b68576001600160a01b03841660008181526007602090815260408083208784528252808320549383526005909152902054610b619190612971565b9050610b6c565b5060005b9392505050565b33610b866001546001600160a01b031690565b6001600160a01b03161480610ba15750610ba16002336118b1565b610bf95760405162461bcd60e51b8152602060048201526024808201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616044820152633236b4b760e11b60648201526084016103ec565b6004805460ff1916911515919091179055565b60026000541415610c2f5760405162461bcd60e51b81526004016103ec906128aa565b6002600055610c3d33610390565b610c595760405162461bcd60e51b81526004016103ec906127f5565b60408051808201825283815260208082018481526001600160a01b03871660009081526005909252908390209151825551600190910155517f515a2ca48e8a7d46b8e4455ae6ebee6067a0729218c07ce1f4d8dcc2ab11791790610479908590849086906126ec565b60045460ff1615610e4157610ce06101726080830160608401612171565b610cfc5760405162461bcd60e51b81526004016103ec9061282c565b6008610d0b60408301836128e1565b604051610d1992919061266a565b9081526040519081900360200190205460ff1615610d755760405162461bcd60e51b81526020600482015260196024820152781cda59db985d1d5c9948185b1c9958591e48185c1c1b1a5959603a1b60448201526064016103ec565b610db584610d86602084018461252f565b610d966080850160608601612171565b610da360208601866128e1565b610db060408801886128e1565b611b43565b610e015760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420617070726f76616c207369676e617475726500000000000060448201526064016103ec565b60016008610e1260408401846128e1565b604051610e2092919061266a565b908152604051908190036020019020805491151560ff199092169190911790555b610e4c8686866105ba565b506040805160018082528183019092526000916020808301908036833750506040516301ffc9a760e01b8152919250506001600160a01b038516906301ffc9a790610ea2906380ac58cd60e01b906004016127e0565b60206040518083038186803b158015610eba57600080fd5b505afa158015610ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef2919061243a565b15610f9657604051630525194b60e31b81526001600160a01b038681166004830152851690632928ca5890602401602060405180830381600087803b158015610f3a57600080fd5b505af1158015610f4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f729190612516565b81600081518110610f8557610f856129e5565b602002602001018181525050611319565b6040516301ffc9a760e01b81526001600160a01b038516906301ffc9a790610fc990636cdb3d1360e11b906004016127e0565b60206040518083038186803b158015610fe157600080fd5b505afa158015610ff5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611019919061243a565b156113195760408051600180825281830190925260009160208083019080368337505060408051600180825281830190925292935060009291506020808301908036833750506040805160018082528183019092529293506000929150602082015b606081526020019060019003908161107b57905050905087836000815181106110a6576110a66129e5565b60200260200101906001600160a01b031690816001600160a01b0316815250506001826000815181106110db576110db6129e5565b602090810291909101015260405163bd85b03960e01b8152600481018790526001600160a01b0388169063bd85b0399060240160206040518083038186803b15801561112657600080fd5b505afa15801561113a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115e9190612516565b6111ef57604051634637423960e11b81526001600160a01b03881690638c6e84729061119290869086908690600401612720565b600060405180830381600087803b1580156111ac57600080fd5b505af11580156111c0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111e89190810190612370565b9350611315565b60405163bd85b03960e01b8152600481018790526000906001600160a01b0389169063bd85b0399060240160206040518083038186803b15801561123257600080fd5b505afa158015611246573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126a9190612516565b1115611315576040805160018082528183019092526000916020808301908036833701905050905086816000815181106112a6576112a66129e5565b60209081029190910101526040516339b2213760e21b81526001600160a01b0389169063e6c884dc906112e1908790859088906004016127a7565b600060405180830381600087803b1580156112fb57600080fd5b505af115801561130f573d6000803e3d6000fd5b50505050505b5050505b85876001600160a01b03167f63166c18fe0d3fe72d2f8f1d4911eb3e2e53191cea4fb348eea4efee3e23d9738787856040516113579392919061267a565b60405180910390a350505050505050565b6001546001600160a01b031633146113925760405162461bcd60e51b81526004016103ec90612875565b6001600160a01b0381166113f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103ec565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60045460ff16156115a3576114716101726080830160608401612171565b61148d5760405162461bcd60e51b81526004016103ec9061282c565b600861149c60408301836128e1565b6040516114aa92919061266a565b9081526040519081900360200190205460ff16156115065760405162461bcd60e51b81526020600482015260196024820152781cda59db985d1d5c9948185b1c9958591e48185c1c1b1a5959603a1b60448201526064016103ec565b61151785610d86602084018461252f565b6115635760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420617070726f76616c207369676e617475726500000000000060448201526064016103ec565b6001600861157460408401846128e1565b60405161158292919061266a565b908152604051908190036020019020805491151560ff199092169190911790555b6115ae8787876105ba565b506040516301ffc9a760e01b81526001600160a01b038516906301ffc9a7906115e2906380ac58cd60e01b906004016127e0565b60206040518083038186803b1580156115fa57600080fd5b505afa15801561160e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611632919061243a565b156116a657604051632142170760e11b81526001600160a01b0383811660048301528681166024830152604482018590528516906342842e0e90606401600060405180830381600087803b15801561168957600080fd5b505af115801561169d573d6000803e3d6000fd5b505050506117b9565b6040516301ffc9a760e01b81526001600160a01b038516906301ffc9a7906116d990636cdb3d1360e11b906004016127e0565b60206040518083038186803b1580156116f157600080fd5b505afa158015611705573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611729919061243a565b156117b957604051637921219560e11b81526001600160a01b0383811660048301528681166024830152604482018590526001606483015260a06084830152600260a483015261060f60f31b60c483015285169063f242432a9060e401600060405180830381600087803b1580156117a057600080fd5b505af11580156117b4573d6000803e3d6000fd5b505050505b604080516001600160a01b0387811682528681166020830152918101859052838216606082015287918916907f2faabf129795c8c8f86e75b8c7d4825bba43566e9d8a0abb5108a5243054f2ad90608001611357565b600260005414156118325760405162461bcd60e51b81526004016103ec906128aa565b600260005561184033610390565b61185c5760405162461bcd60e51b81526004016103ec906127f5565b6001600160a01b03831660009081526005602052604080822082815560010191909155517f515a2ca48e8a7d46b8e4455ae6ebee6067a0729218c07ce1f4d8dcc2ab11791790610479908590849086906126ec565b6001600160a01b03811660009081526001830160205260408120541515610b6c565b6000610b6c836001600160a01b038416611c82565b600061038a825490565b6000610b6c8383611d75565b6040516301ffc9a760e01b81526000906001600160a01b038516906301ffc9a790611934906380ac58cd60e01b906004016127e0565b60206040518083038186803b15801561194c57600080fd5b505afa158015611960573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611984919061243a565b15611a1a576040516331a9108f60e11b81526004810184905284906001600160a01b038481169190831690636352211e9060240160206040518083038186803b1580156119d057600080fd5b505afa1580156119e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a08919061218e565b6001600160a01b031614915050610b6c565b6040516301ffc9a760e01b81526001600160a01b038516906301ffc9a790611a4d90636cdb3d1360e11b906004016127e0565b60206040518083038186803b158015611a6557600080fd5b505afa158015611a79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9d919061243a565b15610b6c57604051627eeac760e11b81526001600160a01b03838116600483015260248201859052859160009183169062fdd58e9060440160206040518083038186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b259190612516565b11915050610b6c565b6000610b6c836001600160a01b038416611d9f565b6000428763ffffffff161015611ba65760405162461bcd60e51b815260206004820152602260248201527f61646d696e207369676e617475726520697320616c7265616479206578706972604482015261195960f21b60648201526084016103ec565b856001600160a01b0316611c6c84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051611c669250611c0691508d908d908c908c904690602001612616565b60408051601f1981840301815282825280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000084830152603c8085019190915282518085039091018152605c909301909152815191012090565b90611dee565b6001600160a01b03161498975050505050505050565b60008181526001830160205260408120548015611d6b576000611ca6600183612971565b8554909150600090611cba90600190612971565b9050818114611d1f576000866000018281548110611cda57611cda6129e5565b9060005260206000200154905080876000018481548110611cfd57611cfd6129e5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d3057611d306129cf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061038a565b600091505061038a565b6000826000018281548110611d8c57611d8c6129e5565b9060005260206000200154905092915050565b6000818152600183016020526040812054611de65750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561038a565b50600061038a565b6000806000611dfd8585611e12565b91509150611e0a81611e82565b509392505050565b600080825160411415611e495760208301516040840151606085015160001a611e3d8782858561203d565b94509450505050611e7b565b825160401415611e735760208301516040840151611e6886838361212a565b935093505050611e7b565b506000905060025b9250929050565b6000816004811115611e9657611e966129b9565b1415611e9f5750565b6001816004811115611eb357611eb36129b9565b1415611f015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016103ec565b6002816004811115611f1557611f156129b9565b1415611f635760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016103ec565b6003816004811115611f7757611f776129b9565b1415611fd05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016103ec565b6004816004811115611fe457611fe46129b9565b14156105085760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016103ec565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156120745750600090506003612121565b8460ff16601b1415801561208c57508460ff16601c14155b1561209d5750600090506004612121565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156120f1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661211a57600060019250925050612121565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161214b8782888561203d565b935093505050935093915050565b60006080828403121561216b57600080fd5b50919050565b60006020828403121561218357600080fd5b8135610b6c81612a11565b6000602082840312156121a057600080fd5b8151610b6c81612a11565b600080604083850312156121be57600080fd5b82356121c981612a11565b946020939093013593505050565b6000806000606084860312156121ec57600080fd5b83356121f781612a11565b925060208401359150604084013561220e81612a11565b809150509250925092565b600080600080600080600060e0888a03121561223457600080fd5b873561223f81612a11565b965060208801359550604088013561225681612a11565b9450606088013561226681612a11565b93506080880135925060a088013561227d81612a11565b915060c088013567ffffffffffffffff81111561229957600080fd5b6122a58a828b01612159565b91505092959891949750929550565b60008060008060008060c087890312156122cd57600080fd5b86356122d881612a11565b95506020870135945060408701356122ef81612a11565b935060608701356122ff81612a11565b92506080870135915060a087013567ffffffffffffffff81111561232257600080fd5b61232e89828a01612159565b9150509295509295509295565b60008060006060848603121561235057600080fd5b833561235b81612a11565b95602085013595506040909401359392505050565b6000602080838503121561238357600080fd5b825167ffffffffffffffff8082111561239b57600080fd5b818501915085601f8301126123af57600080fd5b8151818111156123c1576123c16129fb565b8060051b91506123d2848301612928565b8181528481019084860184860187018a10156123ed57600080fd5b600095505b838610156124105780518352600195909501949186019186016123f2565b5098975050505050505050565b60006020828403121561242f57600080fd5b8135610b6c81612a26565b60006020828403121561244c57600080fd5b8151610b6c81612a26565b60006020828403121561246957600080fd5b81356001600160e01b031981168114610b6c57600080fd5b6000602080838503121561249457600080fd5b823567ffffffffffffffff808211156124ac57600080fd5b818501915085601f8301126124c057600080fd5b8135818111156124d2576124d26129fb565b6124e4601f8201601f19168501612928565b915080825286848285010111156124fa57600080fd5b8084840185840137600090820190930192909252509392505050565b60006020828403121561252857600080fd5b5051919050565b60006020828403121561254157600080fd5b813563ffffffff81168114610b6c57600080fd5b600081518084526020808501945080840160005b8381101561258e5781516001600160a01b031687529582019590820190600101612569565b509495945050505050565b600081518084526020808501945080840160005b8381101561258e578151875295820195908201906001016125ad565b6000815180845260005b818110156125ef576020818501810151868301820152016125d3565b81811115612601576000602083870101525b50601f01601f19169290920160200192915050565b606086901b6bffffffffffffffffffffffff1916815260e085901b6001600160e01b03191660148201528284601883013765474154494e4760d01b92016018810192909252601e820152603e019392505050565b8183823760009101908152919050565b6001600160a01b038481168252831660208201526060604082018190526000906126a690830184612599565b95945050505050565b6001600160a01b03858116825260208201859052831660408201526080606082018190526000906126e2908301846125c9565b9695505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b602081526000610b6c6020830184612555565b6060815260006127336060830186612555565b6020838203818501526127468287612599565b915083820360408501528185518084528284019150828160051b85010183880160005b8381101561279757601f198784030185526127858383516125c9565b94860194925090850190600101612769565b50909a9950505050505050505050565b6060815260006127ba6060830186612555565b82810360208401526127cc8186612599565b905082810360408401526126e28185612599565b6001600160e01b031991909116815260200190565b60208082526019908201527f73656e6465722073686f756c6420626520612041646d696e2000000000000000604082015260600190565b60208082526029908201527f6f6e6c79206f776e6572206f722061646d696e2063616e207369676e20666f7260408201526808191a5cd8dbdd5b9d60ba1b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000808335601e198436030181126128f857600080fd5b83018035915067ffffffffffffffff82111561291357600080fd5b602001915036819003821315611e7b57600080fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612951576129516129fb565b604052919050565b6000821982111561296c5761296c6129a3565b500190565b600082821015612983576129836129a3565b500390565b600060001982141561299c5761299c6129a3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461050857600080fd5b801515811461050857600080fdfea2646970667358221220d509e8ceef1740051c82205cfa282666218a665123f50e7535ff5fd8f389451964736f6c634300080700330000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101375760003560e01c8063715018a6116100b8578063a72c9c6c1161007c578063a72c9c6c146102cc578063bb10c829146102df578063d421ab021461030d578063f2fde38b14610320578063f35653d514610333578063f7f3a5851461034657600080fd5b8063715018a61461023f5780637bcca4d91461024757806382892b13146102685780638da5cb5b1461029e57806393dec796146102b957600080fd5b806331ae450b116100ff57806331ae450b146101ac5780635821e1c2146101c15780635f23d016146101d45780636822065c146102195780636d73e6691461022c57600080fd5b806301ffc9a71461013c57806324d7806c146101645780632a6cc247146101775780632ca355421461018c5780632d34567014610199575b600080fd5b61014f61014a366004612457565b610359565b60405190151581526020015b60405180910390f35b61014f610172366004612171565b610390565b61018a61018536600461233b565b6103c9565b005b60045461014f9060ff1681565b61018a6101a7366004612171565b61048b565b6101b461050b565b60405161015b919061270d565b61014f6101cf3660046121d7565b6105ba565b6102046101e2366004612171565b6001600160a01b03166000908152600560205260409020600181015490549091565b6040805192835260208301919091520161015b565b61018a61022736600461233b565b610951565b61018a61023a366004612171565b610a28565b61018a610aa2565b61025a6102553660046121d7565b610b16565b60405190815260200161015b565b61025a6102763660046121ab565b6001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6001546040516001600160a01b03909116815260200161015b565b61018a6102c736600461241d565b610b73565b61018a6102da36600461233b565b610c0c565b61014f6102ed366004612481565b805160208183018101805160088252928201919093012091525460ff1681565b61018a61031b3660046122b4565b610cc2565b61018a61032e366004612171565b611368565b61018a610341366004612219565b611453565b61018a61035436600461233b565b61180f565b60006001600160e01b03198216632a9f3abf60e11b148061038a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000816001600160a01b03166103ae6001546001600160a01b031690565b6001600160a01b0316148061038a575061038a6002836118b1565b600260005414156103f55760405162461bcd60e51b81526004016103ec906128aa565b60405180910390fd5b600260005561040333610390565b61041f5760405162461bcd60e51b81526004016103ec906127f5565b6001600160a01b038316600090815260066020908152604080832085845290915280822091909155517fbe2efdf01e931999aed0444a32f53a5cbc427e5a9bfba3c155653665ecd985db90610479908590859085906126ec565b60405180910390a15050600160005550565b6001546001600160a01b031633146104b55760405162461bcd60e51b81526004016103ec90612875565b6104c06002826118b1565b156105085760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a36105066002826118d3565b505b50565b606061051760026118e8565b67ffffffffffffffff81111561052f5761052f6129fb565b604051908082528060200260200182016040528015610558578160200160208202803683370190505b50905060005b61056860026118e8565b8110156105b65761057a6002826118f2565b82828151811061058c5761058c6129e5565b6001600160a01b0390921660209283029190910190910152806105ae81612988565b91505061055e565b5090565b6000600260005414156105df5760405162461bcd60e51b81526004016103ec906128aa565b60026000556001600160a01b03821632148061060357506001600160a01b03821633145b80610612575061061233610390565b6106775760405162461bcd60e51b815260206004820152603060248201527f6d73672e73656e6465722073686f756c642062652077616c6c6574206164647260448201526f32b9b99037b9103a34329030b236b4b760811b60648201526084016103ec565b6106828484846118fe565b6106e85760405162461bcd60e51b815260206004820152603160248201527f616c6c6f7773206f6e6c792077686974656c697374656420636f6c6c656374696044820152701bdb9cc81d1bdad95b9cc81dd85b1b195d607a1b60648201526084016103ec565b6001600160a01b0384166000908152600560205260409020546060901580159061072c57506001600160a01b03851660009081526005602052604090206001015415155b801561076257506001600160a01b0385166000908152600560209081526040808320546007835281842088855290925290912054105b156107fc576001600160a01b03851660009081526005602052604081206001908101805491929091610795908490612971565b90915550506001600160a01b038516600090815260076020908152604080832087845290915281208054600192906107ce908490612959565b909155505060408051808201909152600f81526e10dbdb1b1958dd1a5bdb93195d995b608a1b602082015290505b6001600160a01b03851660009081526006602090815260408083208784529091529020541580159061082d57508051155b1561088f576001600160a01b03851660009081526006602090815260408083208784529091528120805460019290610866908490612971565b909155505060408051808201909152600a815269151bdad95b93195d995b60b21b602082015290505b80516109035760405162461bcd60e51b815260206004820152603860248201527f74686520746f6b656e20696e2074686520636f6c6c656374696f6e20646f657360448201527f206e6f74206861766520616e79206c696d69746174696f6e000000000000000060648201526084016103ec565b7f83f7f1ea4d680976c2472903a9e678bc1d856b3d76fbd0f7d40a69098557f5f08585338460405161093894939291906126af565b60405180910390a1600191505060016000559392505050565b600260005414156109745760405162461bcd60e51b81526004016103ec906128aa565b600260005561098233610390565b6109ce5760405162461bcd60e51b815260206004820152601860248201527f73656e6465722073686f756c6420626520612041646d696e000000000000000060448201526064016103ec565b6001600160a01b038316600090815260066020908152604080832085845290915290819020829055517fbe2efdf01e931999aed0444a32f53a5cbc427e5a9bfba3c155653665ecd985db90610479908590859085906126ec565b6001546001600160a01b03163314610a525760405162461bcd60e51b81526004016103ec90612875565b610a5d6002826118b1565b6105085760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3610506600282611b2e565b6001546001600160a01b03163314610acc5760405162461bcd60e51b81526004016103ec90612875565b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b6000610b238484846118fe565b15610b68576001600160a01b03841660008181526007602090815260408083208784528252808320549383526005909152902054610b619190612971565b9050610b6c565b5060005b9392505050565b33610b866001546001600160a01b031690565b6001600160a01b03161480610ba15750610ba16002336118b1565b610bf95760405162461bcd60e51b8152602060048201526024808201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616044820152633236b4b760e11b60648201526084016103ec565b6004805460ff1916911515919091179055565b60026000541415610c2f5760405162461bcd60e51b81526004016103ec906128aa565b6002600055610c3d33610390565b610c595760405162461bcd60e51b81526004016103ec906127f5565b60408051808201825283815260208082018481526001600160a01b03871660009081526005909252908390209151825551600190910155517f515a2ca48e8a7d46b8e4455ae6ebee6067a0729218c07ce1f4d8dcc2ab11791790610479908590849086906126ec565b60045460ff1615610e4157610ce06101726080830160608401612171565b610cfc5760405162461bcd60e51b81526004016103ec9061282c565b6008610d0b60408301836128e1565b604051610d1992919061266a565b9081526040519081900360200190205460ff1615610d755760405162461bcd60e51b81526020600482015260196024820152781cda59db985d1d5c9948185b1c9958591e48185c1c1b1a5959603a1b60448201526064016103ec565b610db584610d86602084018461252f565b610d966080850160608601612171565b610da360208601866128e1565b610db060408801886128e1565b611b43565b610e015760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420617070726f76616c207369676e617475726500000000000060448201526064016103ec565b60016008610e1260408401846128e1565b604051610e2092919061266a565b908152604051908190036020019020805491151560ff199092169190911790555b610e4c8686866105ba565b506040805160018082528183019092526000916020808301908036833750506040516301ffc9a760e01b8152919250506001600160a01b038516906301ffc9a790610ea2906380ac58cd60e01b906004016127e0565b60206040518083038186803b158015610eba57600080fd5b505afa158015610ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef2919061243a565b15610f9657604051630525194b60e31b81526001600160a01b038681166004830152851690632928ca5890602401602060405180830381600087803b158015610f3a57600080fd5b505af1158015610f4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f729190612516565b81600081518110610f8557610f856129e5565b602002602001018181525050611319565b6040516301ffc9a760e01b81526001600160a01b038516906301ffc9a790610fc990636cdb3d1360e11b906004016127e0565b60206040518083038186803b158015610fe157600080fd5b505afa158015610ff5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611019919061243a565b156113195760408051600180825281830190925260009160208083019080368337505060408051600180825281830190925292935060009291506020808301908036833750506040805160018082528183019092529293506000929150602082015b606081526020019060019003908161107b57905050905087836000815181106110a6576110a66129e5565b60200260200101906001600160a01b031690816001600160a01b0316815250506001826000815181106110db576110db6129e5565b602090810291909101015260405163bd85b03960e01b8152600481018790526001600160a01b0388169063bd85b0399060240160206040518083038186803b15801561112657600080fd5b505afa15801561113a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115e9190612516565b6111ef57604051634637423960e11b81526001600160a01b03881690638c6e84729061119290869086908690600401612720565b600060405180830381600087803b1580156111ac57600080fd5b505af11580156111c0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111e89190810190612370565b9350611315565b60405163bd85b03960e01b8152600481018790526000906001600160a01b0389169063bd85b0399060240160206040518083038186803b15801561123257600080fd5b505afa158015611246573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126a9190612516565b1115611315576040805160018082528183019092526000916020808301908036833701905050905086816000815181106112a6576112a66129e5565b60209081029190910101526040516339b2213760e21b81526001600160a01b0389169063e6c884dc906112e1908790859088906004016127a7565b600060405180830381600087803b1580156112fb57600080fd5b505af115801561130f573d6000803e3d6000fd5b50505050505b5050505b85876001600160a01b03167f63166c18fe0d3fe72d2f8f1d4911eb3e2e53191cea4fb348eea4efee3e23d9738787856040516113579392919061267a565b60405180910390a350505050505050565b6001546001600160a01b031633146113925760405162461bcd60e51b81526004016103ec90612875565b6001600160a01b0381166113f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103ec565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60045460ff16156115a3576114716101726080830160608401612171565b61148d5760405162461bcd60e51b81526004016103ec9061282c565b600861149c60408301836128e1565b6040516114aa92919061266a565b9081526040519081900360200190205460ff16156115065760405162461bcd60e51b81526020600482015260196024820152781cda59db985d1d5c9948185b1c9958591e48185c1c1b1a5959603a1b60448201526064016103ec565b61151785610d86602084018461252f565b6115635760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420617070726f76616c207369676e617475726500000000000060448201526064016103ec565b6001600861157460408401846128e1565b60405161158292919061266a565b908152604051908190036020019020805491151560ff199092169190911790555b6115ae8787876105ba565b506040516301ffc9a760e01b81526001600160a01b038516906301ffc9a7906115e2906380ac58cd60e01b906004016127e0565b60206040518083038186803b1580156115fa57600080fd5b505afa15801561160e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611632919061243a565b156116a657604051632142170760e11b81526001600160a01b0383811660048301528681166024830152604482018590528516906342842e0e90606401600060405180830381600087803b15801561168957600080fd5b505af115801561169d573d6000803e3d6000fd5b505050506117b9565b6040516301ffc9a760e01b81526001600160a01b038516906301ffc9a7906116d990636cdb3d1360e11b906004016127e0565b60206040518083038186803b1580156116f157600080fd5b505afa158015611705573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611729919061243a565b156117b957604051637921219560e11b81526001600160a01b0383811660048301528681166024830152604482018590526001606483015260a06084830152600260a483015261060f60f31b60c483015285169063f242432a9060e401600060405180830381600087803b1580156117a057600080fd5b505af11580156117b4573d6000803e3d6000fd5b505050505b604080516001600160a01b0387811682528681166020830152918101859052838216606082015287918916907f2faabf129795c8c8f86e75b8c7d4825bba43566e9d8a0abb5108a5243054f2ad90608001611357565b600260005414156118325760405162461bcd60e51b81526004016103ec906128aa565b600260005561184033610390565b61185c5760405162461bcd60e51b81526004016103ec906127f5565b6001600160a01b03831660009081526005602052604080822082815560010191909155517f515a2ca48e8a7d46b8e4455ae6ebee6067a0729218c07ce1f4d8dcc2ab11791790610479908590849086906126ec565b6001600160a01b03811660009081526001830160205260408120541515610b6c565b6000610b6c836001600160a01b038416611c82565b600061038a825490565b6000610b6c8383611d75565b6040516301ffc9a760e01b81526000906001600160a01b038516906301ffc9a790611934906380ac58cd60e01b906004016127e0565b60206040518083038186803b15801561194c57600080fd5b505afa158015611960573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611984919061243a565b15611a1a576040516331a9108f60e11b81526004810184905284906001600160a01b038481169190831690636352211e9060240160206040518083038186803b1580156119d057600080fd5b505afa1580156119e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a08919061218e565b6001600160a01b031614915050610b6c565b6040516301ffc9a760e01b81526001600160a01b038516906301ffc9a790611a4d90636cdb3d1360e11b906004016127e0565b60206040518083038186803b158015611a6557600080fd5b505afa158015611a79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9d919061243a565b15610b6c57604051627eeac760e11b81526001600160a01b03838116600483015260248201859052859160009183169062fdd58e9060440160206040518083038186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b259190612516565b11915050610b6c565b6000610b6c836001600160a01b038416611d9f565b6000428763ffffffff161015611ba65760405162461bcd60e51b815260206004820152602260248201527f61646d696e207369676e617475726520697320616c7265616479206578706972604482015261195960f21b60648201526084016103ec565b856001600160a01b0316611c6c84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051611c669250611c0691508d908d908c908c904690602001612616565b60408051601f1981840301815282825280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000084830152603c8085019190915282518085039091018152605c909301909152815191012090565b90611dee565b6001600160a01b03161498975050505050505050565b60008181526001830160205260408120548015611d6b576000611ca6600183612971565b8554909150600090611cba90600190612971565b9050818114611d1f576000866000018281548110611cda57611cda6129e5565b9060005260206000200154905080876000018481548110611cfd57611cfd6129e5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d3057611d306129cf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061038a565b600091505061038a565b6000826000018281548110611d8c57611d8c6129e5565b9060005260206000200154905092915050565b6000818152600183016020526040812054611de65750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561038a565b50600061038a565b6000806000611dfd8585611e12565b91509150611e0a81611e82565b509392505050565b600080825160411415611e495760208301516040840151606085015160001a611e3d8782858561203d565b94509450505050611e7b565b825160401415611e735760208301516040840151611e6886838361212a565b935093505050611e7b565b506000905060025b9250929050565b6000816004811115611e9657611e966129b9565b1415611e9f5750565b6001816004811115611eb357611eb36129b9565b1415611f015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016103ec565b6002816004811115611f1557611f156129b9565b1415611f635760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016103ec565b6003816004811115611f7757611f776129b9565b1415611fd05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016103ec565b6004816004811115611fe457611fe46129b9565b14156105085760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016103ec565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156120745750600090506003612121565b8460ff16601b1415801561208c57508460ff16601c14155b1561209d5750600090506004612121565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156120f1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661211a57600060019250925050612121565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161214b8782888561203d565b935093505050935093915050565b60006080828403121561216b57600080fd5b50919050565b60006020828403121561218357600080fd5b8135610b6c81612a11565b6000602082840312156121a057600080fd5b8151610b6c81612a11565b600080604083850312156121be57600080fd5b82356121c981612a11565b946020939093013593505050565b6000806000606084860312156121ec57600080fd5b83356121f781612a11565b925060208401359150604084013561220e81612a11565b809150509250925092565b600080600080600080600060e0888a03121561223457600080fd5b873561223f81612a11565b965060208801359550604088013561225681612a11565b9450606088013561226681612a11565b93506080880135925060a088013561227d81612a11565b915060c088013567ffffffffffffffff81111561229957600080fd5b6122a58a828b01612159565b91505092959891949750929550565b60008060008060008060c087890312156122cd57600080fd5b86356122d881612a11565b95506020870135945060408701356122ef81612a11565b935060608701356122ff81612a11565b92506080870135915060a087013567ffffffffffffffff81111561232257600080fd5b61232e89828a01612159565b9150509295509295509295565b60008060006060848603121561235057600080fd5b833561235b81612a11565b95602085013595506040909401359392505050565b6000602080838503121561238357600080fd5b825167ffffffffffffffff8082111561239b57600080fd5b818501915085601f8301126123af57600080fd5b8151818111156123c1576123c16129fb565b8060051b91506123d2848301612928565b8181528481019084860184860187018a10156123ed57600080fd5b600095505b838610156124105780518352600195909501949186019186016123f2565b5098975050505050505050565b60006020828403121561242f57600080fd5b8135610b6c81612a26565b60006020828403121561244c57600080fd5b8151610b6c81612a26565b60006020828403121561246957600080fd5b81356001600160e01b031981168114610b6c57600080fd5b6000602080838503121561249457600080fd5b823567ffffffffffffffff808211156124ac57600080fd5b818501915085601f8301126124c057600080fd5b8135818111156124d2576124d26129fb565b6124e4601f8201601f19168501612928565b915080825286848285010111156124fa57600080fd5b8084840185840137600090820190930192909252509392505050565b60006020828403121561252857600080fd5b5051919050565b60006020828403121561254157600080fd5b813563ffffffff81168114610b6c57600080fd5b600081518084526020808501945080840160005b8381101561258e5781516001600160a01b031687529582019590820190600101612569565b509495945050505050565b600081518084526020808501945080840160005b8381101561258e578151875295820195908201906001016125ad565b6000815180845260005b818110156125ef576020818501810151868301820152016125d3565b81811115612601576000602083870101525b50601f01601f19169290920160200192915050565b606086901b6bffffffffffffffffffffffff1916815260e085901b6001600160e01b03191660148201528284601883013765474154494e4760d01b92016018810192909252601e820152603e019392505050565b8183823760009101908152919050565b6001600160a01b038481168252831660208201526060604082018190526000906126a690830184612599565b95945050505050565b6001600160a01b03858116825260208201859052831660408201526080606082018190526000906126e2908301846125c9565b9695505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b602081526000610b6c6020830184612555565b6060815260006127336060830186612555565b6020838203818501526127468287612599565b915083820360408501528185518084528284019150828160051b85010183880160005b8381101561279757601f198784030185526127858383516125c9565b94860194925090850190600101612769565b50909a9950505050505050505050565b6060815260006127ba6060830186612555565b82810360208401526127cc8186612599565b905082810360408401526126e28185612599565b6001600160e01b031991909116815260200190565b60208082526019908201527f73656e6465722073686f756c6420626520612041646d696e2000000000000000604082015260600190565b60208082526029908201527f6f6e6c79206f776e6572206f722061646d696e2063616e207369676e20666f7260408201526808191a5cd8dbdd5b9d60ba1b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000808335601e198436030181126128f857600080fd5b83018035915067ffffffffffffffff82111561291357600080fd5b602001915036819003821315611e7b57600080fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612951576129516129fb565b604052919050565b6000821982111561296c5761296c6129a3565b500190565b600082821015612983576129836129a3565b500390565b600060001982141561299c5761299c6129a3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461050857600080fd5b801515811461050857600080fdfea2646970667358221220d509e8ceef1740051c82205cfa282666218a665123f50e7535ff5fd8f389451964736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _adminApprovalRequired (bool): True
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.