ERC-20 vs ERC-721 vs ERC-1155 Token Standards

ERC-20 vs ERC-721 vs ERC-1155: Token Standards

Beginner
Smart Contracts
• ~12 min read
• Updated: 08/08/2025


1) Why token standards exist

Before standards, every token contract exposed its own custom functions and events. Wallets and exchanges had to ship bespoke adapters for each new project, which meant broken UX (tokens not showing up, transfers not indexed, approvals failing). ERC (Ethereum Request for Comments) standards fix this by declaring a minimal, shared interface that anyone can implement and everyone else can reliably integrate with.

  • Interoperability: Tokens “just work” in wallets, DEXs, lending protocols, bridges, explorers, and analytics tools without one-off code.
  • Security leverage: Standardized patterns let the ecosystem harden attack surfaces with audited libraries.
  • Indexability: Consistent events (e.g., Transfer) let indexers track balances, mints, and burns at scale.
  • Composability: Shared ABIs enable Lego-like assembly: vault shares (ERC-4626), marketplaces for ERC-721, games batching ERC-1155, etc.
  • ERC-165 interface detection: Contracts advertise which interfaces they implement so others can verify capabilities quickly.
  • Backward-compatible extensions: Projects often add features (royalties, permits) while preserving the base surface for ecosystem support.

2) ERC-20 — fungible tokens

ERC-20 models a ledger of interchangeable units: balances per address and an allowance system for third-party spenders. It’s the backbone for currencies, points, and governance.

  • Core functions: totalSupply, balanceOf, transfer, approve, allowance, transferFrom. Mints show as transfers from address(0); burns transfer to address(0).
  • Events: Transfer and Approval; many indexers depend on correct emissions.
  • Optional metadata: name, symbol, decimals (often 18; USDC frequently uses 6). Apps must read decimals, not assume.
  • Allowance UX: Unlimited approvals lower friction but increase risk if an operator is compromised.
  • Permit (EIP-2612): Off-chain signatures set allowances (gasless for the user). Handle nonces, deadlines, and replay protection.
  • Approve race mitigation: Set allowance to zero before raising it on non-standard tokens.
  • Fee-on-transfer / rebasing: Can break AMM/accounting assumptions; document caveats or wrap.
  • Bridged variants: Publish canonical addresses per chain to avoid ticker confusion.
  • Permit2-style flows: Centralized signature approvals exist; keep revoke paths obvious.
// Minimal ERC-20 interface (subset)
interface IERC20 {
  function totalSupply() external view returns (uint256);
  function balanceOf(address) external view returns (uint256);
  function transfer(address to, uint256 amount) external returns (bool);
  function approve(address spender, uint256 amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint256);
  function transferFrom(address from, address to, uint256 amount) external returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}

3) ERC-721 — non-fungible tokens (NFTs)

ERC-721 represents unique items: each tokenId maps to a single owner and optional metadata. Typical uses include art, identity, tickets, access passes, and domain names.

  • Ownership & transfers: ownerOf, transferFrom, safeTransferFrom. Safe transfers verify onERC721Received on recipient contracts.
  • Approvals: approve/getApproved (single token) and setApprovalForAll (operator for collection). Beware phishing prompting for global approvals.
  • Metadata: tokenURI JSON (image, attributes, animation). Prefer IPFS/Arweave with content hashes.
  • Royalties: EIP-2981 signals royalty info; enforcement is marketplace policy.
  • Permit: EIP-4494 adds signature approvals per token (adoption varies).
  • Enumeration trade-off: Full on-chain enumeration costs gas; rely on indexers when possible.
  • Batch minting: ERC-721A optimizes large mints; consider EIP-2309 consecutive mint events.
  • Dynamic metadata: Emit EIP-4906 events to trigger marketplace refreshes.

4) ERC-1155 — multi-token standard

ERC-1155 generalizes tokens: a single contract manages many types (IDs). Each ID can be fungible (supply > 1) or non-fungible (supply = 1), dramatically reducing deployment and transaction costs for catalogs (games, editions, tickets).

  • Batching: safeBatchTransferFrom moves multiple IDs/amounts in one tx; balanceOfBatch queries many balances at once.
  • Approvals: setApprovalForAll operator model (per contract for all IDs).
  • Receiver checks: onERC1155Received/onERC1155BatchReceived must return selectors or the transfer reverts.
  • URI pattern: uri() returns a template containing {id}; clients substitute hex-padded IDs for per-type metadata.
  • Royalties & extras: Add EIP-2981 as needed; permit-style flows are project-specific.

When you’d otherwise deploy many ERC-721/20 contracts, ERC-1155 consolidates storage, cuts bytecode size, and enables atomic bundles (e.g., sell a “Starter Pack” of multiple IDs in one transfer).

5) Feature comparison table

Feature ERC-20 ERC-721 ERC-1155
Fungible Yes No Per-ID
Non-fungible No Yes Per-ID
Batch transfers No No Yes
Metadata Symbol/decimals (UI) Per-token tokenURI uri() with {id} substitution
Approvals model approve per spender Per-token + setApprovalForAll setApprovalForAll per operator
Permit (sig approvals) Optional (EIP-2612) EIP-4494 (optional) Project-specific
Gas efficiency Standard Standard High (batching)
Typical use Currencies, governance, points Collectibles, tickets, identity Games, editions, marketplaces

6) When to use which

Picking a standard is both a product and integration decision.

  • Use ERC-20 if every unit is interchangeable and you need DeFi integrations (AMMs, lending, bridges). Examples: currencies, reward points, governance voting weight, vault shares (via ERC-4626).
  • Use ERC-721 if each item is unique and needs the widest NFT wallet/marketplace support. Examples: membership passes, 1/1 art, unique tickets/seats, domain names, identity artifacts.
  • Use ERC-1155 if you manage a catalog of items (mix of fungible + non-fungible) and care about batch operations and deployment cost. Examples: game items, editions, loot boxes, merch with sizes.

Operational considerations:

  • Indexing/analytics: ERC-1155 compresses activity into fewer transactions; ensure your analytics stack handles TransferSingle/TransferBatch semantics.
  • Metadata strategy: Plan permanence (IPFS/Arweave + content hashes). For dynamic traits, use EIP-4906 to nudge refreshes.
  • Legal & royalties: Implement EIP-2981 if you promise payouts, but document marketplace behavior (royalties may be optional).
  • Cross-chain story: Publish canonical addresses per chain, and clarify bridging/wrapping behavior to avoid user confusion.

7) Developer notes

  • Leverage audited libs: Start with OpenZeppelin for ERC-20/721/1155. Favor minimal overrides; add roles (AccessControl) for minting/pausing if needed.
  • Approvals & safety: Prefer safeTransferFrom for NFTs/1155. Be wary of hooks (external calls) and follow checks-effects-interactions with reentrancy guards where appropriate.
  • Metadata hosting: Use IPFS CIDs (pin via multiple pinning services) or Arweave. If you host off-chain, document a freeze policy and emit events on updates.
  • Upgradeability: If using proxies, lock initializers, protect upgradeTo with multisig + timelock, and publish admin addresses. If trustless is a goal, prefer immutable deployments.
  • Testing: Unit test transfers/approvals and event emissions; fuzz for invariants (no double-spend, supply accounting); simulate marketplace/DEX flows; test permit signatures for expiry/replay.
  • Gas hygiene: Batch where possible (ERC-1155), pack storage (e.g., uint128 where safe), and avoid redundant SSTOREs. Large airdrops? Consider Merkle claims or EIP-712 signed mints.
  • Adjacent standards: ERC-4626 for vault shares (yield-bearing ERC-20s), and consider semi-fungible ERC-3525 if you need “value slots”.
// Example: cautious ERC-721 safe mint (pseudo)
function safeMint(address to, uint256 tokenId, string memory uri)
  external onlyRole(MINTER_ROLE)
{
    _safeMint(to, tokenId);
    _setTokenURI(tokenId, uri); // or baseURI + tokenId pattern
    // If metadata can change later, emit EIP-4906 events on updates
}
Design checklist: Supply model (fixed/capped/infinite), minting rights (roles/allowlists), metadata permanence, royalty policy (and enforcement reality), cross-chain canonical list, allowance/permit UX, operator revocation path, incident response (pause? revoke? rotate multisig?).

8) Further learning & resources

9) Further lectures (go deeper)

Ready to level up? Here’s a structured path of deeper lectures that build on this page.

  1. Permits in the wild: Implementing EIP-2612 (ERC-20) and EIP-4494 (ERC-721), signature domain separation, nonces, revocation UX. Compare native permits with consolidated “Permit2” style systems.
  2. Metadata permanence & reveals: IPFS/Arweave strategies, content addressing with CIDs, freeze policies, and emitting EIP-4906 for dynamic traits.
  3. NFT drop engineering: ERC-721A vs vanilla 721, EIP-2309 consecutive mints, Merkle allowlists, VRF randomness for fair distribution, and gas profiling for large mints.
  4. ERC-1155 catalogs: Designing ID schemas, batch trading, crafting multi-item “packs,” and building indexers for TransferBatch semantics.
  5. Advanced token types: ERC-4626 vault shares (yield-bearing ERC-20s), semi-fungible value slots (ERC-3525), and design trade-offs vs wrapping patterns.
  6. Security case files: Approval phishing (operator drains), reentrancy via receiver hooks, allowance griefing, fee-on-transfer pitfalls in AMMs, and incident response with pausability and timelocks.
  7. Cross-chain canonicals: Bridging models (lock-mint vs burn-mint), canonical lists per chain, symbol collisions, and user-facing warnings in UIs.

← Intro to Multi-Sig & Smart Wallets
Anatomy of an Ethereum Transaction →