erc-721
ERC-721 NFT Integration for Scaffold-ETH 2
Prerequisites
Check if ./packages/nextjs/scaffold.config.ts exists directly in the current working directory (do not search subdirectories). If it doesn't exist, this is not a Scaffold-ETH 2 project. Follow the instructions at https://docs.scaffoldeth.io/SKILL.md to scaffold it first. If it exists, continue directly with building.
Also read .agents/skills/openzeppelin/SKILL.md since ERC-721 contracts use OpenZeppelin, and that skill has critical guidance on reading the installed source for correct import syntax, override points, and constructor patterns.
Gotchas
Key pitfalls and gotchas to watch for when working with ERC-721.
1. _safeMint Reentrancy
_safeMint and safeTransferFrom invoke onERC721Received() on the recipient if it's a contract. This is an external call after the token has been minted, creating a reentrancy vector.
Real exploit (HypeBears, Feb 2022): State updated after _safeMint allowed attacker to re-enter and bypass per-address minting limits.
// VULNERABLE: state update after _safeMint
function mintNFT() public {
require(!addressMinted[msg.sender], "Already minted");
_safeMint(msg.sender, tokenId);
addressMinted[msg.sender] = true; // too late
}
// SAFE: state update before _safeMint
function mintNFT() public {
require(!addressMinted[msg.sender], "Already minted");
addressMinted[msg.sender] = true; // update first
_safeMint(msg.sender, tokenId);
}
2. On-Chain SVG Stack-Too-Deep
When generating SVG on-chain, the tokenURI or generateSVG function easily hits Solidity's 16-local-variable stack limit. Split SVG generation into multiple helper functions (e.g., _svgBackground, _svgShapes, _svgText) rather than building the entire SVG in one function.
3. Marketplace Metadata attributes Array
The attributes array in NFT metadata JSON is not in the ERC-721 EIP but is the de facto standard used by OpenSea, Blur, and every marketplace. Without it, traits won't display:
{
"name": "My NFT #1",
"description": "...",
"image": "data:image/svg+xml;base64,...",
"attributes": [
{ "trait_type": "Color", "value": "Blue" },
{ "trait_type": "Rarity", "value": "Rare" }
]
}
4. Required Overrides with ERC721Enumerable
When combining ERC721 + ERC721Enumerable, both define _update and _increaseBalance. You must explicitly override them or the contract won't compile:
function _update(address to, uint256 tokenId, address auth) internal override(ERC721, ERC721Enumerable) returns (address) {
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 amount) internal override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, amount);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
5. IPFS Base URI Trailing Slash
OpenZeppelin's tokenURI() concatenates _baseURI() + tokenId.toString(). If the base URI is ipfs://QmCID without a trailing slash, token 42 becomes ipfs://QmCID42 instead of ipfs://QmCID/42.
More from scaffold-eth/scaffold-eth-2
solidity-security
Master smart contract security best practices to prevent common vulnerabilities and implement secure Solidity patterns. Use when writing smart contracts, auditing existing contracts, or implementing security measures for blockchain applications.
10defi-protocol-templates
Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and lending systems. Use when building decentralized finance applications or smart contract protocols.
10ponder
Integrate Ponder into a Scaffold-ETH 2 project for blockchain event indexing. Use when the user wants to: index contract events, add a blockchain backend, set up GraphQL for onchain data, use Ponder with SE-2, or build an indexer for their dApp.
7erc-20
Add an ERC-20 token contract to a Scaffold-ETH 2 project. Use when the user wants to: create a fungible token, deploy an ERC-20, add token minting, build a token transfer UI, or work with ERC-20 tokens in SE-2.
6siwe
Add Sign-In with Ethereum (SIWE) authentication to a Scaffold-ETH 2 project. Use when the user wants to: add wallet-based login, implement SIWE, authenticate users with their Ethereum wallet, add session management with wallet signing, build sign-in with Ethereum, or add Web3 authentication.
5eip-5792
Add EIP-5792 batched transaction support to a Scaffold-ETH 2 project. Use when the user wants to: batch multiple contract calls, use wallet_sendCalls, add EIP-5792 wallet integration, batch onchain transactions, or use wagmi's experimental batch hooks.
4