NFT Development
Build NFT collections with ERC-721 and ERC-1155 standards, on-chain metadata, allowlists, reveal mechanics, and royalty enforcement.
NFTs (Non-Fungible Tokens) represent unique digital ownership on the blockchain. Building an NFT collection requires knowledge of ERC-721/1155 standards, gas optimization (ERC-721A), secure minting mechanics, reveal patterns, and royalty standards.
Use ERC-721A for large collections (saves 60%+ gas on batch mints). Use Merkle trees for allowlists. Implement commit-reveal for fair reveals. Set royalties via ERC-2981. Test all mint scenarios before deploying.
Workflow
- Choose ERC-721 vs ERC-721A vs ERC-1155Wrong standard wastes gas or limits functionality for your collection type.
- Implement allowlist with Merkle treesStoring allowlist on-chain costs thousands in gas; Merkle proofs verify off-chain list with minimal on-chain state.
- Build mint mechanics: phases and pricingMost collections have multiple mint phases (OG allowlist → public); managing them in one contract reduces deployment complexity.
- Implement reveal mechanicsUnrevealed collections prevent sniping (buying rares before reveal); fair reveal requires on-chain randomness commitment.
- Set royalties with ERC-2981ERC-2981 is the standard royalty interface; marketplaces that respect it will route royalties to your contract.
Output Format
ERC-721A contract with Merkle allowlist, phase management, Chainlink VRF reveal, ERC-2981 royalties, Hardhat tests for all mint scenarios.
Examples
ERC-721A with allowlist: `function allowlistMint(uint256 qty, bytes32[] calldata proof) external payable { require(phase == Phase.ALLOWLIST); require(MerkleProof.verify(proof, merkleRoot, keccak256(abi.encodePacked(msg.sender)))); require(msg.value >= qty * PRICE); _mint(msg.sender, qty); }`Royalty setup: `constructor() ERC721A("Collection", "COLL") { _setDefaultRoyalty(msg.sender, 500); }`Reveal URI: `function tokenURI(uint256 id) public view override returns (string memory) { return revealed ? string.concat(baseURI, ((id + offset) % MAX_SUPPLY).toString(), ".json") : preRevealURI; }`Edge Cases & Gotchas
- Marketplace royalty enforcement: OpenSea moved to voluntary royalties; consider on-chain enforcement via operator filtering (ClosedSea or custom blocklist)
- Mint bot attacks: add per-tx limits and require proofs; bots can still operate at scale if mint is profitable enough
- ERC-721A token ID shifting: token IDs start at 0 by default; override `_startTokenId()` to return 1 if your frontend expects 1-indexed IDs
When to Break These Rules
- For small 1:1 art collections (<100 pieces), simple ERC-721 is cleaner than ERC-721A; the gas optimization only matters at scale.
Reference Files
ERC-721A: https://www.erc721a.org/OpenZeppelin ERC-721: https://docs.openzeppelin.com/contracts/4.x/erc721Chainlink VRF: https://docs.chain.link/vrf/ERC-2981 Royalties: https://eips.ethereum.org/EIPS/eip-2981