CCFF00
0x505a22ffed8d37ebe580ffd98d2cdb0021189146
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
11,810 bytes
ABI entries
95
49 read · 14 write
License
none
Contract information
- Address
- 0x505a22ffed8d37ebe580ffd98d2cdb0021189146
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0x08d022730e…90122cfEad
- Creation tx
- 0x46b097f55f…f401a5c96b
Token
- Name
- CCFF00
- Symbol
- CCFF00
- Decimals
- —
- Holders
- 21
- Market
- View token page →
Read contract (49)
FOUNDER_RESERVE() → uint256
FOUNDER_START_ID() → uint256
MAX_PER_MINT() → uint256
MAX_RESERVE_BATCH() → uint256
MAX_SUPPLY() → uint256
MINT_PRICE() → uint256
PROJECT_RESERVE() → uint256
PROJECT_START_ID() → uint256
PUBLIC_START_ID() → uint256
PUBLIC_SUPPLY() → uint256
TOKENS_PER_NFT() → uint256
TOTAL_RESERVE() → uint256
accountChainId() → uint256
balanceOf(address) → uint256
ccff00Token() → address
erc6551Implementation() → address
erc6551Registry() → address
erc6551Salt() → bytes32
founderPaymentWallet() → address
founderReserveRecipient() → address
getApproved(uint256) → address
getTokenBoundAccount(uint256) → address
isApprovedForAll(address, address) → bool
isProtectedPaymentToken(address) → bool
isReserveComplete() → bool
liquidityFundingWallet() → address
name() → string
owner() → address
ownerOf(uint256) → address
payee(uint256) → address
pendingOwner() → address
projectReserveRecipient() → address
projectTreasury() → address
publicMinted() → uint256
publicSaleOpen() → bool
releasable(address) → uint256
releasable(address, address) → uint256
released(address, address) → uint256
released(address) → uint256
reserveMinted() → uint256
shares(address) → uint256
supportsInterface(bytes4) → bool
symbol() → string
tokenURI(uint256) → string
totalReleased(address) → uint256
totalReleased() → uint256
totalShares() → uint256
totalSupply() → uint256
tradingActivated() → bool
Events (14)
ApprovalApprovalForAllERC20PaymentReleasedOwnershipTransferStartedOwnershipTransferredPayeeAddedPaymentReceivedPaymentReleasedPublicMintPublicSaleOpenedReserveBatchInitializedTokenBoundAccountFundedTradingActivatedTransfer
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "initialOwner",
"type": "address"
},
{
"internalType": "address",
"name": "_founderReserveRecipient",
"type": "address"
},
{
"internalType": "address",
"name": "_projectReserveRecipient",
"type": "address"
},
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "registry",
"type": "address"
},
{
"internalType": "address",
"name": "accountImplementation",
"type": "address"
},
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
},
{
"internalType": "address[]",
"name": "paymentPayees",
"type": "address[]"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "DirectSelfOwnershipCycle",
"type": "error"
},
{
"inputs": [],
"name": "IncorrectETHAmount",
"type": "error"
},
{
"inputs": [],
"name": "InvalidAccountAddress",
"type": "error"
},
{
"inputs": [],
"name": "InvalidAddress",
"type": "error"
},
{
"inputs": [],
"name": "InvalidQuantity",
"type": "error"
},
{
"inputs": [],
"name": "LaunchIncomplete",
"type": "error"
},
{
"inputs": [],
"name": "NotContract",
"type": "error"
},
{
"inputs": [],
"name": "ProtectedDistributionToken",
"type": "error"
},
{
"inputs": [],
"name": "PublicSupplyExhausted",
"type": "error"
},
{
"inputs": [],
"name": "ReserveComplete",
"type": "error"
},
{
"inputs": [],
"name": "ReserveIncomplete",
"type": "error"
},
{
"inputs": [],
"name": "SaleAlreadyOpen",
"type": "error"
},
{
"inputs": [],
"name": "SaleNotOpen",
"type": "error"
},
{
"inputs": [],
"name": "TradingAlreadyActivated",
"type": "error"
},
{
"inputs": [],
"name": "TradingNotReady",
"type": "error"
},
{
"inputs": [],
"name": "UnsupportedChain",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "contract IERC20",
"name": "token",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "ERC20PaymentReleased",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferStarted",
"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": "account",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "shares",
"type": "uint256"
}
],
"name": "PayeeAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "PaymentReceived",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "PaymentReleased",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "minter",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "firstTokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "paid",
"type": "uint256"
}
],
"name": "PublicMint",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "PublicSaleOpened",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "firstTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "uint256",
"name": "lastTokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
}
],
"name": "ReserveBatchInitialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "TokenBoundAccountFunded",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "TradingActivated",
"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"
},
{
"inputs": [],
"name": "FOUNDER_RESERVE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "FOUNDER_START_ID",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_PER_MINT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_RESERVE_BATCH",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MINT_PRICE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PROJECT_RESERVE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PROJECT_START_ID",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PUBLIC_START_ID",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PUBLIC_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TOKENS_PER_NFT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TOTAL_RESERVE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "acceptOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "accountChainId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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": "ccff00Token",
"outputs": [
{
"internalType": "contract ICCFF00Token",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "enableTrading",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "erc6551Implementation",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "erc6551Registry",
"outputs": [
{
"internalType": "contract IERC6551Registry",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "erc6551Salt",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "founderPaymentWallet",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "founderReserveRecipient",
"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": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getTokenBoundAccount",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
}
],
"name": "initializeReserveBatch",
"outputs": [],
"stateMutability": "nonpayable",
"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": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "isProtectedPaymentToken",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isReserveComplete",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "liquidityFundingWallet",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "openPublicSale",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "payee",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pendingOwner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "projectReserveRecipient",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "projectTreasury",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "publicMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "publicSaleOpen",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "releasable",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IERC20",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "releasable",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "account",
"type": "address"
}
],
"name": "release",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IERC20",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "release",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IERC20",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "released",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "released",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "reserveMinted",
"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": "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": "address",
"name": "account",
"type": "address"
}
],
"name": "shares",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IERC20",
"name": "token",
"type": "address"
}
],
"name": "totalReleased",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalReleased",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalShares",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tradingActivated",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"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"
},
{
"stateMutability": "payable",
"type": "receive"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { PaymentSplitter } from "@openzeppelin/contracts/finance/PaymentSplitter.sol";
import { Base64 } from "@openzeppelin/contracts/utils/Base64.sol";
import { IERC6551Registry } from "erc6551/src/interfaces/IERC6551Registry.sol";
interface ICCFF00Token is IERC20 {
function enableTrading() external;
function tradingEnabled() external view returns (bool);
}
library CCFF00PaymentConfig {
function shares() internal pure returns (uint256[] memory values) {
values = new uint256[](3);
values[0] = 50;
values[1] = 25;
values[2] = 25;
}
}
/// @title CCFF00
/// @notice Ten thousand identical, fully onchain Robin Neon badges with deterministic ERC-6551 accounts.
/// @dev Intentional onchain dependencies are the CCFF00 token, canonical ERC-6551 registry, and immutable account implementation.
contract CCFF00 is ERC721, Ownable2Step, ReentrancyGuard, PaymentSplitter {
using SafeERC20 for IERC20;
uint256 public constant MAX_SUPPLY = 10_000;
uint256 public constant PUBLIC_SUPPLY = 9_750;
uint256 public constant FOUNDER_RESERVE = 20;
uint256 public constant PROJECT_RESERVE = 230;
uint256 public constant TOTAL_RESERVE = 250;
uint256 public constant PUBLIC_START_ID = 1;
uint256 public constant FOUNDER_START_ID = 9_751;
uint256 public constant PROJECT_START_ID = 9_771;
uint256 public constant MAX_PER_MINT = 3;
uint256 public constant MAX_RESERVE_BATCH = 25;
uint256 public constant MINT_PRICE = 0.003 ether;
uint256 public constant TOKENS_PER_NFT = 10_000 ether;
address public immutable founderReserveRecipient;
address public immutable projectReserveRecipient;
address public immutable founderPaymentWallet;
address public immutable liquidityFundingWallet;
address public immutable projectTreasury;
ICCFF00Token public immutable ccff00Token;
IERC6551Registry public immutable erc6551Registry;
address public immutable erc6551Implementation;
bytes32 public immutable erc6551Salt;
uint256 public immutable accountChainId;
uint256 public publicMinted;
uint256 public reserveMinted;
bool public publicSaleOpen;
bool public tradingActivated;
error InvalidAddress();
error NotContract();
error UnsupportedChain();
error InvalidQuantity();
error ReserveIncomplete();
error ReserveComplete();
error SaleAlreadyOpen();
error SaleNotOpen();
error IncorrectETHAmount();
error PublicSupplyExhausted();
error InvalidAccountAddress();
error DirectSelfOwnershipCycle();
error TradingNotReady();
error TradingAlreadyActivated();
error LaunchIncomplete();
error ProtectedDistributionToken();
event ReserveBatchInitialized(uint256 indexed firstTokenId, uint256 indexed lastTokenId, uint256 quantity);
event PublicSaleOpened();
event PublicMint(address indexed minter, uint256 indexed firstTokenId, uint256 quantity, uint256 paid);
event TokenBoundAccountFunded(uint256 indexed tokenId, address indexed account, uint256 amount);
event TradingActivated();
constructor(
address initialOwner,
address _founderReserveRecipient,
address _projectReserveRecipient,
address token,
address registry,
address accountImplementation,
bytes32 salt,
address[] memory paymentPayees
) ERC721("CCFF00", "CCFF00") PaymentSplitter(paymentPayees, CCFF00PaymentConfig.shares()) {
if (block.chainid != 4_663 && block.chainid != 46_630) revert UnsupportedChain();
if (
initialOwner == address(0) || _founderReserveRecipient == address(0)
|| _projectReserveRecipient == address(0) || token == address(0) || registry == address(0)
|| accountImplementation == address(0)
) revert InvalidAddress();
if (paymentPayees.length != 3) revert InvalidAddress();
if (token.code.length == 0 || registry.code.length == 0 || accountImplementation.code.length == 0) {
revert NotContract();
}
founderReserveRecipient = _founderReserveRecipient;
projectReserveRecipient = _projectReserveRecipient;
founderPaymentWallet = paymentPayees[0];
liquidityFundingWallet = paymentPayees[1];
projectTreasury = paymentPayees[2];
ccff00Token = ICCFF00Token(token);
erc6551Registry = IERC6551Registry(registry);
erc6551Implementation = accountImplementation;
erc6551Salt = salt;
accountChainId = block.chainid;
address probe = IERC6551Registry(registry)
.account(accountImplementation, salt, block.chainid, address(this), PUBLIC_START_ID);
if (probe == address(0)) revert InvalidAccountAddress();
_transferOwnership(initialOwner);
}
/// @notice Initializes up to 25 reserved NFTs, filling founder IDs before project IDs.
function initializeReserveBatch(uint256 quantity) external onlyOwner nonReentrant {
if (publicSaleOpen) revert SaleAlreadyOpen();
if (reserveMinted == TOTAL_RESERVE) revert ReserveComplete();
if (quantity == 0 || quantity > MAX_RESERVE_BATCH || reserveMinted + quantity > TOTAL_RESERVE) {
revert InvalidQuantity();
}
uint256 firstTokenId = 0;
uint256 lastTokenId = 0;
for (uint256 i; i < quantity; ++i) {
uint256 reserveIndex = reserveMinted;
address recipient;
uint256 tokenId;
if (reserveIndex < FOUNDER_RESERVE) {
recipient = founderReserveRecipient;
tokenId = FOUNDER_START_ID + reserveIndex;
} else {
recipient = projectReserveRecipient;
tokenId = PROJECT_START_ID + (reserveIndex - FOUNDER_RESERVE);
}
if (i == 0) firstTokenId = tokenId;
lastTokenId = tokenId;
++reserveMinted;
_safeMint(recipient, tokenId);
_fundTokenBoundAccount(tokenId);
}
emit ReserveBatchInitialized(firstTokenId, lastTokenId, quantity);
}
/// @notice Permanently opens the public mint after all reserve NFTs are initialized.
function openPublicSale() external onlyOwner {
if (publicSaleOpen) revert SaleAlreadyOpen();
if (reserveMinted != TOTAL_RESERVE) revert ReserveIncomplete();
publicSaleOpen = true;
emit PublicSaleOpened();
}
/// @notice Mints one to three public NFTs with atomic token-bound-account funding.
function mint(uint256 quantity) external payable nonReentrant {
if (!publicSaleOpen) revert SaleNotOpen();
if (quantity == 0 || quantity > MAX_PER_MINT) revert InvalidQuantity();
if (publicMinted + quantity > PUBLIC_SUPPLY) revert PublicSupplyExhausted();
if (msg.value != MINT_PRICE * quantity) revert IncorrectETHAmount();
uint256 firstTokenId = PUBLIC_START_ID + publicMinted;
publicMinted += quantity;
for (uint256 i; i < quantity; ++i) {
uint256 tokenId = firstTokenId + i;
_safeMint(msg.sender, tokenId);
_fundTokenBoundAccount(tokenId);
}
emit PublicMint(msg.sender, firstTokenId, quantity, msg.value);
}
/// @notice Activates unrestricted CCFF00 token transfers after all public NFTs mint.
function enableTrading() external onlyOwner nonReentrant {
if (tradingActivated) revert TradingAlreadyActivated();
if (publicMinted != PUBLIC_SUPPLY) revert TradingNotReady();
tradingActivated = true;
ccff00Token.enableTrading();
if (!ccff00Token.tradingEnabled()) revert TradingNotReady();
emit TradingActivated();
}
function getTokenBoundAccount(uint256 tokenId) public view returns (address) {
return erc6551Registry.account(erc6551Implementation, erc6551Salt, accountChainId, address(this), tokenId);
}
function isReserveComplete() external view returns (bool) {
return reserveMinted == TOTAL_RESERVE;
}
function totalSupply() public view returns (uint256) {
return publicMinted + reserveMinted;
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
_requireMinted(tokenId);
string memory svg =
'<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000"><rect width="1000" height="1000" fill="#CCFF00"/></svg>';
string memory image = string.concat("data:image/svg+xml;base64,", Base64.encode(bytes(svg)));
string memory json = string.concat(
'{"name":"#CCFF00","description":"This is Robin Neon.","image":"',
image,
'","attributes":[{"trait_type":"Color","value":"#CCFF00"}]}'
);
return string.concat("data:application/json;base64,", Base64.encode(bytes(json)));
}
/// @dev Covers every ERC-721 transfer entry point because all route through this v4.9.6 hook.
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal override {
if (from != address(0)) {
for (uint256 i; i < batchSize; ++i) {
uint256 tokenId = firstTokenId + i;
if (to == getTokenBoundAccount(tokenId)) revert DirectSelfOwnershipCycle();
}
}
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
}
function _fundTokenBoundAccount(uint256 tokenId) internal {
address account = getTokenBoundAccount(tokenId);
if (account == address(0)) revert InvalidAccountAddress();
IERC20(address(ccff00Token)).safeTransfer(account, TOKENS_PER_NFT);
emit TokenBoundAccountFunded(tokenId, account, TOKENS_PER_NFT);
}
/// @notice Identifies the ERC-20 reserved for NFT distribution and excluded from splitter releases.
/// @dev PaymentSplitter.releasable(IERC20, address) is non-virtual and will still report this
/// balance as accounting revenue; integrations must check this indicator first.
function isProtectedPaymentToken(address token) public view returns (bool) {
return token == address(ccff00Token);
}
/// @notice Prevents PaymentSplitter's generic ERC-20 release path from treating the
/// dedicated NFT reward allocation as payment revenue.
function release(IERC20 token, address account) public override {
if (address(token) == address(ccff00Token)) revert ProtectedDistributionToken();
super.release(token, account);
}
/// @notice Ownership cannot be renounced while reserve, sellout, or activation authority is still required.
function renounceOwnership() public override onlyOwner {
if (reserveMinted != TOTAL_RESERVE || publicMinted != PUBLIC_SUPPLY || !tradingActivated) {
revert LaunchIncomplete();
}
super.renounceOwnership();
}
}
Chain explorer4912msChain node89ms