ERC Token Standard Guidelines
When to Apply
- Implementing a new token (Fungible, NFT, Multi-token, or Vault).
- Reviewing existing token implementations for standard compliance.
- Integrating with external tokens (e.g., DeFi protocols, marketplaces).
- Extending standards with custom logic (e.g., Permit, Votes, Enumerable).
ERC20: Fungible Tokens
- Required:
totalSupply,balanceOf,transfer,allowance,approve,transferFrom. - SafeERC20: ALWAYS wrap external ERC20 calls (
transfer,transferFrom,approve) using OpenZeppelin'sSafeERC20to handle tokens that returnfalseinstead of reverting. - Race Condition: The
approvefunction has a known race condition. UseincreaseAllowanceanddecreaseAllowance(OpenZeppelin) orERC20Permitto mitigate. - ERC20Permit (EIP-2612): Use for gasless approvals via signatures (
permitfunction). - ERC20Votes: Use for governance tokens to enable delegation and checkpointing.
- Common Pitfall: Some tokens (like USDT) do not return a boolean on
transfer, causing calls to revert if the interface expects a return value.
ERC721: Non-Fungible Tokens
- Required:
balanceOf,ownerOf,safeTransferFrom,transferFrom,approve,setApprovalForAll,getApproved,isApprovedForAll. - safeTransferFrom: Always prefer
safeTransferFromovertransferFromto ensure the recipient can handle NFTs (viaonERC721Received). - ERC721Enumerable: Provides on-chain tracking of all tokens. High gas cost for transfers; avoid unless necessary for on-chain discovery.
- Metadata: Use
tokenURIto link to JSON metadata. Off-chain (IPFS/Arweave) is standard; on-chain (Base64) is used for "fully on-chain" NFTs. - Common Pitfall: Reentrancy via
onERC721Receivedcallback duringsafeTransferFrom. UsenonReentrantor follow Checks-Effects-Interactions (SCWE-046, SCWE-138).
ERC1155: Multi-Token
- When to use: When managing multiple token types (fungible and non-fungible) in a single contract. More gas-efficient for batch operations.
- Batch Operations: Use
safeBatchTransferFromandbalanceOfBatchto reduce gas for multiple transfers. - URI Pattern: Use a single URI with the
{id}substitution string (e.g.,https://api.com/{id}.json). - Common Pitfall: Forgetting to implement
balanceOfBatchor incorrect implementation of the receiver callback.
ERC4626: Tokenized Vault
- Calculations:
convertToShares(assets to shares) andconvertToAssets(shares to assets). - Rounding: Favor the vault. Round DOWN on
deposit/mint(fewer shares for assets) and round UP onwithdraw/redeem(more shares for assets). - Inflation Attack: First depositor can manipulate share price. Prevent by minting "dead shares" to
address(0)on the first deposit (SCWE-049). - Common Pitfall: Incorrect rounding direction leading to "free" shares or assets over time.
Implementation Choice
| OpenZeppelin | Solady | |
|---|---|---|
| Gas | Higher | Lower |
| Readability | More readable | More optimized |
| Extensions | Many available | Fewer but efficient |
| When to use | Most projects | Gas-critical applications |
Testing Strategies
- ERC20: Test
transfer(balance changes),approve/transferFrom(allowance logic), and edge cases (0 amount,type(uint256).max). - ERC721: Test
mint,transfer,approval, andERC721Enumerable(if used). VerifyonERC721Receivedtriggers. - ERC1155: Test batch transfers, URI substitution, and receiver callbacks.
- ERC4626: Test deposit/withdraw symmetry (1:1 if no yield), share calculations, and rounding edge cases.
Enhanced with MCP
When the solidity-agent-toolkit is available, leverage these tools for ERC implementation:
Interface Lookup:
erc://{standard}: Full interface definition, required functions, events, and extension list for ERC20, ERC721, ERC1155, ERC4626
Implementation Verification:
check_vulnerability: Verify code against known ERC-specific vulnerabilitiesmatch_vulnerability_patterns: Detect missing SafeERC20, approval race conditions, reentrancy in callbackssearch_vulnerabilities: Look up SCWE entries related to token standards (e.g., "ERC20", "reentrancy")get_remediation: Get fix guidance for specific SCWE IDs found during review
Code Generation:
- Use the
generate_ercprompt for scaffolding compliant token implementations