RobinhoodPixies
0x64713dda62c3559e3ee77873bb468c519b1a970a
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
17,638 bytes
ABI entries
93
30 read · 29 write
License
none
Contract information
- Address
- 0x64713dda62c3559e3ee77873bb468c519b1a970a
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0x166A6cde06…25c6C68e53
- Creation tx
- 0xad380f4dd0…c969dff516
Token
- Name
- Robinhood Pixies
- Symbol
- PIXIE
- Decimals
- —
- Holders
- 329
- Market
- View token page →
Read contract (30)
MAX_SUPPLY() → uint256
allowedSeaDrop(address) → bool
balanceOf(address) → uint256
baseURI() → string
contractURI() → string
displayMaxSupply() → uint256
getAllowedSeaDrop() → address[]
getApproved(uint256) → address
getMintStats(address) → uint256, uint256, uint256
getTransferValidationFunction() → bytes4, bool
getTransferValidator() → address
isApprovedForAll(address, address) → bool
maxSupply() → uint256
metadata() → address
name() → string
numMinted(address) → uint256
owner() → address
ownerOf(uint256) → address
provenanceHash() → bytes32
renderSVG(uint256) → string
renderer() → address
royaltyAddress() → address
royaltyBps() → uint96
royaltyInfo(uint256, uint256) → address, uint256
royaltyReceiver() → address
supportsInterface(bytes4) → bool
symbol() → string
tokenURI(uint256) → string
totalSupply() → uint256
transferValidator() → address
Events (15)
AllowedSeaDropUpdatedApprovalApprovalForAllBaseURIUpdatedBatchMetadataUpdateContractURIUpdatedMaxSupplyUpdatedMetadataUpdatedMintedOwnershipTransferredProvenanceHashUpdatedRendererUpdatedRoyaltyInfoUpdatedTransferTransferValidatorUpdated
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "initialOwner",
"type": "address"
},
{
"internalType": "address",
"name": "_renderer",
"type": "address"
},
{
"internalType": "address",
"name": "_metadata",
"type": "address"
},
{
"internalType": "address[]",
"name": "allowedSeaDrop_",
"type": "address[]"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "ERC721IncorrectOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ERC721InsufficientApproval",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "approver",
"type": "address"
}
],
"name": "ERC721InvalidApprover",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
}
],
"name": "ERC721InvalidOperator",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "ERC721InvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
}
],
"name": "ERC721InvalidReceiver",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "ERC721InvalidSender",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ERC721NonexistentToken",
"type": "error"
},
{
"inputs": [],
"name": "ExceedsHardCap",
"type": "error"
},
{
"inputs": [],
"name": "LengthMismatch",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "NonexistentToken",
"type": "error"
},
{
"inputs": [],
"name": "NotOwnerOrSelf",
"type": "error"
},
{
"inputs": [],
"name": "OnlyAllowedSeaDrop",
"type": "error"
},
{
"inputs": [],
"name": "OutOfRange",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{
"inputs": [],
"name": "SoldOut",
"type": "error"
},
{
"inputs": [],
"name": "ZeroAddress",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address[]",
"name": "allowedSeaDrop",
"type": "address[]"
}
],
"name": "AllowedSeaDropUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "newBaseURI",
"type": "string"
}
],
"name": "BaseURIUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "_fromTokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "_toTokenId",
"type": "uint256"
}
],
"name": "BatchMetadataUpdate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "newContractURI",
"type": "string"
}
],
"name": "ContractURIUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "newMaxSupply",
"type": "uint256"
}
],
"name": "MaxSupplyUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "metadata",
"type": "address"
}
],
"name": "MetadataUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
}
],
"name": "Minted",
"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": "bytes32",
"name": "previousHash",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "newHash",
"type": "bytes32"
}
],
"name": "ProvenanceHashUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "renderer",
"type": "address"
}
],
"name": "RendererUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"indexed": false,
"internalType": "uint96",
"name": "bps",
"type": "uint96"
}
],
"name": "RoyaltyInfoUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "oldValidator",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newValidator",
"type": "address"
}
],
"name": "TransferValidatorUpdated",
"type": "event"
},
{
"inputs": [],
"name": "MAX_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "allowedSeaDrop",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "baseURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "contractURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "displayMaxSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "fromTokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "toTokenId",
"type": "uint256"
}
],
"name": "emitBatchMetadataUpdate",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getAllowedSeaDrop",
"outputs": [
{
"internalType": "address[]",
"name": "",
"type": "address[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "minter",
"type": "address"
}
],
"name": "getMintStats",
"outputs": [
{
"internalType": "uint256",
"name": "minterNumMinted",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "currentTotalSupply",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxSupply_",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getTransferValidationFunction",
"outputs": [
{
"internalType": "bytes4",
"name": "functionSignature",
"type": "bytes4"
},
{
"internalType": "bool",
"name": "isViewFunction",
"type": "bool"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "getTransferValidator",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "metadata",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "minter",
"type": "address"
},
{
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
}
],
"name": "mintSeaDrop",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "uint256",
"name": "maxSupply",
"type": "uint256"
},
{
"internalType": "string",
"name": "baseURI",
"type": "string"
},
{
"internalType": "string",
"name": "contractURI",
"type": "string"
},
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"components": [
{
"internalType": "uint80",
"name": "mintPrice",
"type": "uint80"
},
{
"internalType": "uint48",
"name": "startTime",
"type": "uint48"
},
{
"internalType": "uint48",
"name": "endTime",
"type": "uint48"
},
{
"internalType": "uint16",
"name": "maxTotalMintableByWallet",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "feeBps",
"type": "uint16"
},
{
"internalType": "bool",
"name": "restrictFeeRecipients",
"type": "bool"
}
],
"internalType": "struct PublicDrop",
"name": "publicDrop",
"type": "tuple"
},
{
"internalType": "string",
"name": "dropURI",
"type": "string"
},
{
"components": [
{
"internalType": "bytes32",
"name": "merkleRoot",
"type": "bytes32"
},
{
"internalType": "string[]",
"name": "publicKeyURIs",
"type": "string[]"
},
{
"internalType": "string",
"name": "allowListURI",
"type": "string"
}
],
"internalType": "struct AllowListData",
"name": "allowListData",
"type": "tuple"
},
{
"internalType": "address",
"name": "creatorPayoutAddress",
"type": "address"
},
{
"internalType": "bytes32",
"name": "provenanceHash",
"type": "bytes32"
},
{
"internalType": "address[]",
"name": "allowedFeeRecipients",
"type": "address[]"
},
{
"internalType": "address[]",
"name": "disallowedFeeRecipients",
"type": "address[]"
},
{
"internalType": "address[]",
"name": "allowedPayers",
"type": "address[]"
},
{
"internalType": "address[]",
"name": "disallowedPayers",
"type": "address[]"
},
{
"internalType": "address[]",
"name": "tokenGatedAllowedNftTokens",
"type": "address[]"
},
{
"components": [
{
"internalType": "uint80",
"name": "mintPrice",
"type": "uint80"
},
{
"internalType": "uint16",
"name": "maxTotalMintableByWallet",
"type": "uint16"
},
{
"internalType": "uint48",
"name": "startTime",
"type": "uint48"
},
{
"internalType": "uint48",
"name": "endTime",
"type": "uint48"
},
{
"internalType": "uint8",
"name": "dropStageIndex",
"type": "uint8"
},
{
"internalType": "uint32",
"name": "maxTokenSupplyForStage",
"type": "uint32"
},
{
"internalType": "uint16",
"name": "feeBps",
"type": "uint16"
},
{
"internalType": "bool",
"name": "restrictFeeRecipients",
"type": "bool"
}
],
"internalType": "struct TokenGatedDropStage[]",
"name": "tokenGatedDropStages",
"type": "tuple[]"
},
{
"internalType": "address[]",
"name": "disallowedTokenGatedAllowedNftTokens",
"type": "address[]"
},
{
"internalType": "address[]",
"name": "signedMintValidationParamsSigners",
"type": "address[]"
},
{
"components": [
{
"internalType": "uint80",
"name": "minMintPrice",
"type": "uint80"
},
{
"internalType": "uint24",
"name": "maxMaxTotalMintableByWallet",
"type": "uint24"
},
{
"internalType": "uint40",
"name": "minStartTime",
"type": "uint40"
},
{
"internalType": "uint40",
"name": "maxEndTime",
"type": "uint40"
},
{
"internalType": "uint40",
"name": "maxMaxTokenSupplyForStage",
"type": "uint40"
},
{
"internalType": "uint16",
"name": "minFeeBps",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "maxFeeBps",
"type": "uint16"
}
],
"internalType": "struct SignedMintValidationParams[]",
"name": "signedMintValidationParams",
"type": "tuple[]"
},
{
"internalType": "address[]",
"name": "disallowedSigners",
"type": "address[]"
}
],
"internalType": "struct MultiConfigureStruct",
"name": "config",
"type": "tuple"
}
],
"name": "multiConfigure",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "numMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "count",
"type": "uint256"
}
],
"name": "ownerMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "provenanceHash",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "id",
"type": "uint256"
}
],
"name": "renderSVG",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renderer",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "royaltyAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "royaltyBps",
"outputs": [
{
"internalType": "uint96",
"name": "",
"type": "uint96"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "salePrice",
"type": "uint256"
}
],
"name": "royaltyInfo",
"outputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint256",
"name": "royaltyAmount",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "royaltyReceiver",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "newBaseURI",
"type": "string"
}
],
"name": "setBaseURI",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "newContractURI",
"type": "string"
}
],
"name": "setContractURI",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newMaxSupply",
"type": "uint256"
}
],
"name": "setMaxSupply",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "mdata",
"type": "address"
}
],
"name": "setMetadata",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "newProvenanceHash",
"type": "bytes32"
}
],
"name": "setProvenanceHash",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "r",
"type": "address"
}
],
"name": "setRenderer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint96",
"name": "feeNumerator",
"type": "uint96"
}
],
"name": "setRoyaltyInfo",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint96",
"name": "bps",
"type": "uint96"
}
],
"internalType": "struct RobinhoodPixies.RoyaltyInfoArg",
"name": "info",
"type": "tuple"
}
],
"name": "setRoyaltyInfo",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "validator",
"type": "address"
}
],
"name": "setTransferValidator",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "transferValidator",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"components": [
{
"internalType": "bytes32",
"name": "merkleRoot",
"type": "bytes32"
},
{
"internalType": "string[]",
"name": "publicKeyURIs",
"type": "string[]"
},
{
"internalType": "string",
"name": "allowListURI",
"type": "string"
}
],
"internalType": "struct AllowListData",
"name": "allowListData",
"type": "tuple"
}
],
"name": "updateAllowList",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"internalType": "address",
"name": "feeRecipient",
"type": "address"
},
{
"internalType": "bool",
"name": "allowed",
"type": "bool"
}
],
"name": "updateAllowedFeeRecipient",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address[]",
"name": "allowedSeaDrop_",
"type": "address[]"
}
],
"name": "updateAllowedSeaDrop",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"internalType": "address",
"name": "payoutAddress",
"type": "address"
}
],
"name": "updateCreatorPayoutAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"internalType": "string",
"name": "dropURI",
"type": "string"
}
],
"name": "updateDropURI",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"internalType": "address",
"name": "payer",
"type": "address"
},
{
"internalType": "bool",
"name": "allowed",
"type": "bool"
}
],
"name": "updatePayer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"components": [
{
"internalType": "uint80",
"name": "mintPrice",
"type": "uint80"
},
{
"internalType": "uint48",
"name": "startTime",
"type": "uint48"
},
{
"internalType": "uint48",
"name": "endTime",
"type": "uint48"
},
{
"internalType": "uint16",
"name": "maxTotalMintableByWallet",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "feeBps",
"type": "uint16"
},
{
"internalType": "bool",
"name": "restrictFeeRecipients",
"type": "bool"
}
],
"internalType": "struct PublicDrop",
"name": "publicDrop",
"type": "tuple"
}
],
"name": "updatePublicDrop",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"internalType": "address",
"name": "signer",
"type": "address"
},
{
"components": [
{
"internalType": "uint80",
"name": "minMintPrice",
"type": "uint80"
},
{
"internalType": "uint24",
"name": "maxMaxTotalMintableByWallet",
"type": "uint24"
},
{
"internalType": "uint40",
"name": "minStartTime",
"type": "uint40"
},
{
"internalType": "uint40",
"name": "maxEndTime",
"type": "uint40"
},
{
"internalType": "uint40",
"name": "maxMaxTokenSupplyForStage",
"type": "uint40"
},
{
"internalType": "uint16",
"name": "minFeeBps",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "maxFeeBps",
"type": "uint16"
}
],
"internalType": "struct SignedMintValidationParams",
"name": "signedMintValidationParams",
"type": "tuple"
}
],
"name": "updateSignedMintValidationParams",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "seaDropImpl",
"type": "address"
},
{
"internalType": "address",
"name": "allowedNftToken",
"type": "address"
},
{
"components": [
{
"internalType": "uint80",
"name": "mintPrice",
"type": "uint80"
},
{
"internalType": "uint16",
"name": "maxTotalMintableByWallet",
"type": "uint16"
},
{
"internalType": "uint48",
"name": "startTime",
"type": "uint48"
},
{
"internalType": "uint48",
"name": "endTime",
"type": "uint48"
},
{
"internalType": "uint8",
"name": "dropStageIndex",
"type": "uint8"
},
{
"internalType": "uint32",
"name": "maxTokenSupplyForStage",
"type": "uint32"
},
{
"internalType": "uint16",
"name": "feeBps",
"type": "uint16"
},
{
"internalType": "bool",
"name": "restrictFeeRecipients",
"type": "bool"
}
],
"internalType": "struct TokenGatedDropStage",
"name": "dropStage",
"type": "tuple"
}
],
"name": "updateTokenGatedDrop",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {PixieTraits} from "./PixieTraits.sol";
import {
INonFungibleSeaDropToken,
ISeaDrop,
PublicDrop,
AllowListData,
TokenGatedDropStage,
SignedMintValidationParams,
MultiConfigureStruct
} from "./ISeaDropInterfaces.sol";
interface IPixieRenderer {
function render(uint256 id, PixieTraits.Traits memory t) external view returns (string memory);
}
interface IPixieMetadata {
function tokenURI(uint256 id, PixieTraits.Traits memory t, address renderer)
external view returns (string memory);
}
/// ERC721-C creator-token transfer validator — the on-chain mechanism OpenSea
/// uses to ENFORCE creator earnings. `validateTransfer` reverts to block a
/// transfer (e.g. by a marketplace that doesn't honour royalties).
interface ITransferValidator {
function validateTransfer(address caller, address from, address to, uint256 tokenId) external;
}
/**
* Robinhood Pixies — a fully on-chain ERC721 forest of 10,000 deterministic
* pixel pixies. tokenId IS the seed: every trait (PixieTraits) and every pixel
* of the artwork (PixieRenderer, via `tokenURI`) is derived from the id and
* rendered in Solidity — no IPFS, no server, no external image. Eight ids
* (625, 1875, … 9375) are the hand-crafted 1/1 legends, exactly where the
* design's generator places them. Same token, same pixie, forever.
*
* SeaDrop-native (managed through OpenSea Studio) — same integration pattern
* as On-Chain Ships / On-Chain Bonsai: the canonical SeaDrop singleton
* 0x00005EA00Ac477B1030CE78506496e8C2dE24bf5 calls `mintSeaDrop` + `getMintStats`,
* and every drop/allowlist/fee/royalty setting is forwarded from Studio.
*/
contract RobinhoodPixies is ERC721, Ownable, INonFungibleSeaDropToken {
uint256 public constant MAX_SUPPLY = 6969;
uint256 public totalSupply;
address public renderer;
address public metadata;
// ───────────────────────── SEADROP ─────────────────────────
/// SeaDrop addresses authorized to call `mintSeaDrop`. Canonical mainnet +
/// testnet SeaDrop is `0x00005EA00Ac477B1030CE78506496e8C2dE24bf5`.
mapping(address => bool) public allowedSeaDrop;
/// Per-minter mint count — drives SeaDrop's per-wallet caps via
/// `getMintStats`. Only `mintSeaDrop` bumps this; `ownerMint` does not.
mapping(address => uint256) public numMinted;
address[] internal _enumeratedAllowedSeaDrop;
// ─────────────────── OPENSEA STUDIO METADATA SURFACE ───────────────────
// Plain storage so Studio's `multiConfigure` bulk-publish doesn't trip on
// missing setters. None of these affect mint logic; the hard cap is
// MAX_SUPPLY regardless of `displayMaxSupply`.
uint256 public displayMaxSupply;
string private _baseURIStorage;
string private _contractURI;
bytes32 public provenanceHash;
// Inline ERC2981 royalty (default royalty only).
address public royaltyReceiver;
uint96 public royaltyBps;
// ── ERC721-C creator-token standard (creator-earnings enforcement) ──
// When set to a real validator contract, EVERY holder-to-holder transfer is
// gated by it — this is what lets OpenSea show/enforce creator earnings.
// Zero address = no validation (mints, burns and transfers pass freely).
address public transferValidator;
event Minted(uint256 indexed tokenId, address indexed to);
event TransferValidatorUpdated(address oldValidator, address newValidator);
event AllowedSeaDropUpdated(address[] allowedSeaDrop);
event RendererUpdated(address indexed renderer);
event MetadataUpdated(address indexed metadata);
event MaxSupplyUpdated(uint256 newMaxSupply);
event BaseURIUpdated(string newBaseURI);
event ContractURIUpdated(string newContractURI);
event ProvenanceHashUpdated(bytes32 previousHash, bytes32 newHash);
event RoyaltyInfoUpdated(address receiver, uint96 bps);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
error SoldOut();
error NonexistentToken(uint256 tokenId);
error OutOfRange();
error ZeroAddress();
error OnlyAllowedSeaDrop();
error LengthMismatch();
error NotOwnerOrSelf();
error ExceedsHardCap();
constructor(
address initialOwner,
address _renderer,
address _metadata,
address[] memory allowedSeaDrop_
)
ERC721("Robinhood Pixies", "PIXIE")
Ownable(initialOwner)
{
if (_renderer == address(0) || _metadata == address(0)) revert ZeroAddress();
renderer = _renderer;
metadata = _metadata;
displayMaxSupply = MAX_SUPPLY;
royaltyReceiver = initialOwner;
royaltyBps = 500; // 5% default creator earnings
emit RendererUpdated(_renderer);
emit MetadataUpdated(_metadata);
emit MaxSupplyUpdated(MAX_SUPPLY);
emit RoyaltyInfoUpdated(initialOwner, 500);
for (uint256 k = 0; k < allowedSeaDrop_.length; k++) {
address sd = allowedSeaDrop_[k];
if (sd == address(0)) revert ZeroAddress();
if (!allowedSeaDrop[sd]) {
allowedSeaDrop[sd] = true;
_enumeratedAllowedSeaDrop.push(sd);
}
}
emit AllowedSeaDropUpdated(allowedSeaDrop_);
}
// ═══════════════════════ MINT ═══════════════════════
/// SeaDrop mint entrypoint — called by the allowlisted SeaDrop singleton
/// AFTER it has taken payment + enforced per-wallet / per-stage / fee splits
/// via `getMintStats`.
function mintSeaDrop(address minter, uint256 quantity) external payable {
if (!allowedSeaDrop[msg.sender]) revert OnlyAllowedSeaDrop();
if (totalSupply + quantity > MAX_SUPPLY) revert SoldOut();
for (uint256 i = 0; i < quantity; i++) {
uint256 id = ++totalSupply;
_safeMint(minter, id);
emit Minted(id, minter);
}
numMinted[minter] += quantity;
}
function ownerMint(address to, uint256 count) external onlyOwner {
for (uint256 i = 0; i < count; i++) {
if (totalSupply >= MAX_SUPPLY) revert SoldOut();
uint256 id = ++totalSupply;
_safeMint(to, id);
emit Minted(id, to);
}
}
// ─────────────────── SEADROP VIEWS + FORWARDERS ───────────────────
function getMintStats(address minter)
external
view
returns (uint256 minterNumMinted, uint256 currentTotalSupply, uint256 maxSupply_)
{
minterNumMinted = numMinted[minter];
currentTotalSupply = totalSupply;
maxSupply_ = displayMaxSupply;
}
function maxSupply() external view returns (uint256) { return displayMaxSupply; }
function getAllowedSeaDrop() external view returns (address[] memory) {
return _enumeratedAllowedSeaDrop;
}
modifier onlyAllowedSeaDrop(address seaDropImpl) {
if (!allowedSeaDrop[seaDropImpl]) revert OnlyAllowedSeaDrop();
_;
}
modifier onlyOwnerOrSelf() {
if (msg.sender != owner() && msg.sender != address(this)) revert NotOwnerOrSelf();
_;
}
function updateAllowedSeaDrop(address[] calldata allowedSeaDrop_) external onlyOwner {
for (uint256 i = 0; i < _enumeratedAllowedSeaDrop.length; i++) {
allowedSeaDrop[_enumeratedAllowedSeaDrop[i]] = false;
}
delete _enumeratedAllowedSeaDrop;
for (uint256 i = 0; i < allowedSeaDrop_.length; i++) {
address sd = allowedSeaDrop_[i];
if (sd == address(0)) revert ZeroAddress();
if (!allowedSeaDrop[sd]) {
allowedSeaDrop[sd] = true;
_enumeratedAllowedSeaDrop.push(sd);
}
}
emit AllowedSeaDropUpdated(allowedSeaDrop_);
}
function updatePublicDrop(address seaDropImpl, PublicDrop calldata publicDrop)
external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl)
{
ISeaDrop(seaDropImpl).updatePublicDrop(publicDrop);
}
function updateAllowList(address seaDropImpl, AllowListData calldata allowListData)
external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl)
{
ISeaDrop(seaDropImpl).updateAllowList(allowListData);
}
function updateTokenGatedDrop(
address seaDropImpl,
address allowedNftToken,
TokenGatedDropStage calldata dropStage
) external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl) {
ISeaDrop(seaDropImpl).updateTokenGatedDrop(allowedNftToken, dropStage);
}
function updateDropURI(address seaDropImpl, string calldata dropURI)
external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl)
{
ISeaDrop(seaDropImpl).updateDropURI(dropURI);
}
function updateCreatorPayoutAddress(address seaDropImpl, address payoutAddress)
external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl)
{
ISeaDrop(seaDropImpl).updateCreatorPayoutAddress(payoutAddress);
}
function updateAllowedFeeRecipient(address seaDropImpl, address feeRecipient, bool allowed)
external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl)
{
ISeaDrop(seaDropImpl).updateAllowedFeeRecipient(feeRecipient, allowed);
}
function updateSignedMintValidationParams(
address seaDropImpl,
address signer,
SignedMintValidationParams calldata signedMintValidationParams
) external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl) {
ISeaDrop(seaDropImpl).updateSignedMintValidationParams(signer, signedMintValidationParams);
}
function updatePayer(address seaDropImpl, address payer, bool allowed)
external onlyOwnerOrSelf onlyAllowedSeaDrop(seaDropImpl)
{
ISeaDrop(seaDropImpl).updatePayer(payer, allowed);
}
// ─────────────────── COLLECTION-METADATA SETTERS ───────────────────
function setMaxSupply(uint256 newMaxSupply) external onlyOwnerOrSelf {
if (newMaxSupply > MAX_SUPPLY) revert ExceedsHardCap();
displayMaxSupply = newMaxSupply;
emit MaxSupplyUpdated(newMaxSupply);
}
function setBaseURI(string calldata newBaseURI) external onlyOwnerOrSelf {
_baseURIStorage = newBaseURI;
emit BaseURIUpdated(newBaseURI);
}
function baseURI() external view returns (string memory) { return _baseURIStorage; }
function setContractURI(string calldata newContractURI) external onlyOwnerOrSelf {
_contractURI = newContractURI;
emit ContractURIUpdated(newContractURI);
}
function contractURI() external view returns (string memory) { return _contractURI; }
function setProvenanceHash(bytes32 newProvenanceHash) external onlyOwnerOrSelf {
bytes32 prev = provenanceHash;
provenanceHash = newProvenanceHash;
emit ProvenanceHashUpdated(prev, newProvenanceHash);
}
function setRoyaltyInfo(address receiver, uint96 feeNumerator) public onlyOwner {
require(feeNumerator <= 10000, "bps>10000");
royaltyReceiver = receiver;
royaltyBps = feeNumerator;
emit RoyaltyInfoUpdated(receiver, feeNumerator);
}
struct RoyaltyInfoArg { address receiver; uint96 bps; }
function setRoyaltyInfo(RoyaltyInfoArg calldata info) external onlyOwner {
setRoyaltyInfo(info.receiver, info.bps);
}
function royaltyAddress() external view returns (address) { return royaltyReceiver; }
function royaltyInfo(uint256, uint256 salePrice)
external view returns (address receiver, uint256 royaltyAmount)
{
receiver = royaltyReceiver;
royaltyAmount = (salePrice * royaltyBps) / 10000;
}
function emitBatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId) external onlyOwner {
emit BatchMetadataUpdate(fromTokenId, toTokenId);
}
// ─────────────────── multiConfigure (0x911f456b) ───────────────────
function multiConfigure(MultiConfigureStruct calldata config) external onlyOwner {
if (config.maxSupply > 0 && config.maxSupply != displayMaxSupply) {
this.setMaxSupply(config.maxSupply);
}
if (bytes(config.baseURI).length != 0) this.setBaseURI(config.baseURI);
if (bytes(config.contractURI).length != 0) this.setContractURI(config.contractURI);
if (config.publicDrop.startTime != 0 || config.publicDrop.endTime != 0) {
this.updatePublicDrop(config.seaDropImpl, config.publicDrop);
}
if (bytes(config.dropURI).length != 0) this.updateDropURI(config.seaDropImpl, config.dropURI);
if (config.allowListData.merkleRoot != bytes32(0)) {
this.updateAllowList(config.seaDropImpl, config.allowListData);
}
if (config.creatorPayoutAddress != address(0)) {
this.updateCreatorPayoutAddress(config.seaDropImpl, config.creatorPayoutAddress);
}
if (config.provenanceHash != bytes32(0)) this.setProvenanceHash(config.provenanceHash);
for (uint256 i = 0; i < config.allowedFeeRecipients.length; i++) {
this.updateAllowedFeeRecipient(config.seaDropImpl, config.allowedFeeRecipients[i], true);
}
for (uint256 i = 0; i < config.disallowedFeeRecipients.length; i++) {
this.updateAllowedFeeRecipient(config.seaDropImpl, config.disallowedFeeRecipients[i], false);
}
for (uint256 i = 0; i < config.allowedPayers.length; i++) {
this.updatePayer(config.seaDropImpl, config.allowedPayers[i], true);
}
for (uint256 i = 0; i < config.disallowedPayers.length; i++) {
this.updatePayer(config.seaDropImpl, config.disallowedPayers[i], false);
}
if (config.tokenGatedAllowedNftTokens.length != config.tokenGatedDropStages.length) {
revert LengthMismatch();
}
for (uint256 i = 0; i < config.tokenGatedAllowedNftTokens.length; i++) {
this.updateTokenGatedDrop(
config.seaDropImpl, config.tokenGatedAllowedNftTokens[i], config.tokenGatedDropStages[i]
);
}
TokenGatedDropStage memory emptyStage;
for (uint256 i = 0; i < config.disallowedTokenGatedAllowedNftTokens.length; i++) {
this.updateTokenGatedDrop(config.seaDropImpl, config.disallowedTokenGatedAllowedNftTokens[i], emptyStage);
}
if (config.signedMintValidationParamsSigners.length != config.signedMintValidationParams.length) {
revert LengthMismatch();
}
for (uint256 i = 0; i < config.signedMintValidationParamsSigners.length; i++) {
this.updateSignedMintValidationParams(
config.seaDropImpl, config.signedMintValidationParamsSigners[i], config.signedMintValidationParams[i]
);
}
SignedMintValidationParams memory emptySigned;
for (uint256 i = 0; i < config.disallowedSigners.length; i++) {
this.updateSignedMintValidationParams(config.seaDropImpl, config.disallowedSigners[i], emptySigned);
}
}
// ═══════════════════════ RENDER / METADATA ═══════════════════════
/// Raw SVG for any id in 1..MAX_SUPPLY — works for un-minted ids too, so
/// front-ends can preview the whole forest deterministically.
function renderSVG(uint256 id) public view returns (string memory) {
if (id == 0 || id > MAX_SUPPLY) revert OutOfRange();
return IPixieRenderer(renderer).render(id, PixieTraits.derive(id));
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
_requireOwned(tokenId);
return IPixieMetadata(metadata).tokenURI(tokenId, PixieTraits.derive(tokenId), renderer);
}
// ═══════════════════════ ERC165 / OWNER ═══════════════════════
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
interfaceId == type(INonFungibleSeaDropToken).interfaceId ||
interfaceId == 0x2a55205a /* IERC2981 */ ||
interfaceId == 0x49064906 /* IERC4906 */ ||
interfaceId == 0xad0d7f6c /* ICreatorToken */ ||
super.supportsInterface(interfaceId);
}
// ─────────────────── ERC721-C: creator-token transfer validator ───────────────────
function getTransferValidator() external view returns (address) {
return transferValidator;
}
/// Tells integrators (OpenSea, Limit Break) which function to call on the
/// validator and that it is a view call.
function getTransferValidationFunction()
external
pure
returns (bytes4 functionSignature, bool isViewFunction)
{
return (ITransferValidator.validateTransfer.selector, true);
}
function setTransferValidator(address validator) external onlyOwner {
address old = transferValidator;
transferValidator = validator;
emit TransferValidatorUpdated(old, validator);
}
/// OZ v5 transfer hook. Mints (from == 0) and burns (to == 0) are never
/// gated; a real holder-to-holder transfer is validated by the configured
/// validator, which reverts to block disallowed operators.
function _update(address to, uint256 tokenId, address auth)
internal
virtual
override
returns (address from)
{
from = super._update(to, tokenId, auth);
address validator = transferValidator;
if (validator != address(0) && from != address(0) && to != address(0)) {
ITransferValidator(validator).validateTransfer(_msgSender(), from, to, tokenId);
}
}
function setRenderer(address r) external onlyOwner {
if (r == address(0)) revert ZeroAddress();
renderer = r;
emit RendererUpdated(r);
}
function setMetadata(address mdata) external onlyOwner {
if (mdata == address(0)) revert ZeroAddress();
metadata = mdata;
emit MetadataUpdated(mdata);
}
}
Chain explorer3615msChain node86ms