ERC-721 vs ERC-1155

ERC-721 vs ERC-1155: What’s the Difference & When to Use Each

Understand token models, supply, transfers, metadata, gas efficiency, and real-world trade-offs
so you can pick the right standard for art, collectibles, gaming items, memberships, and beyond.

TL;DR: ERC-721 = 1 token ID ↔ 1 unique item (classic PFPs, 1/1 art).
ERC-1155 = 1 token ID ↔ fungible or semi-fungible supply (editions, stackable game items) and supports batch mints/transfers.
1155 wins on scale and flexibility; 721 wins on simplicity and broad marketplace/tooling familiarity.

1) Token Model & Supply

  • ERC-721 (non-fungible): Every tokenId represents exactly one unique item. Supply per ID is 1. Ownership is tracked by a simple mapping tokenId ⇒ owner plus per-owner holdings.
  • ERC-1155 (multi-token): Each id has a balance per account (balances[id][owner]). An ID can behave like a 1/1 or like an edition of N, or even like a fungible token. Same contract can host many item classes.

Think of 1155 as a “collection of collections” under one address. That makes it ideal for game inventories and editions where many holders share identical metadata but different quantities. Conversely, 721’s mental model, every ID is its own snowflake maps cleanly to art/PFPs and is what most wallets and explorers optimized for first.

Design tip: If each piece truly needs distinct traits, rarity, and bespoke provenance, 721 keeps things straightforward. If your items come in types (Sword v1, Potion, Ticket Tier A) with quantities, 1155 reduces contract sprawl and simplifies supply accounting.

2) Transfers & Batch Operations

  • ERC-721: safeTransferFrom(from, to, tokenId) moves one NFT at a time. Receivers that are contracts must implement onERC721Received to avoid lockups.
  • ERC-1155: safeTransferFrom(..., id, amount) and safeBatchTransferFrom(..., ids[], amounts[]) support multi-ID moves and bulk amounts. Contract receivers must implement onERC1155Received/onERC1155BatchReceived.
// ERC-1155 batch transfer (conceptual)
uint256[] ids = [1, 2, 3];
uint256[] amounts = [5, 1, 10];
safeBatchTransferFrom(alice, bob, ids, amounts, "0x");

Batch ops matter for gas and UX in games/editions: moving 20 items as one transaction can be order-of-magnitude cheaper and avoids “click fatigue.” 1155 also emits TransferSingle / TransferBatch events that indexers use to track balances efficiently.

3) Metadata & Editions

  • ERC-721: Per-token tokenURI(tokenId). Editions often mint different IDs that share the same metadata; you track “edition number” in metadata fields.
  • ERC-1155: A single uri() with the special {id} placeholder that clients replace with the lowercase, zero-padded 64-hex ID. Ideal for N-editions where all holders share the same JSON/media per ID.
// 1155 base URI pattern (illustrative)
function uri(uint256 id) public view returns (string memory) {
  return string.concat("ipfs://<CID>/", toLowerHex64(id), ".json");
}
// Clients will request .../0000000000000000000000000000000000000000000000000000000000000001.json

For long-lived collections, prefer content-addressed URIs (IPFS/Arweave) and include integrity hints (e.g., SHA-256) in your JSON. If you plan a “reveal,” implement a baseURI switch and lock/freeze policy so collectors know when traits are final. For dynamic items (e.g., leveling gear), consider on-chain metadata or a transparent, rate-limited metadata server with signed responses.

4) Gas & Storage Efficiency

Gas is mostly about state writes. With thousands of mints or transfers:

  • ERC-721: Each new token requires writing owner mappings and emitting one Transfer event. Enumeration add-ons (ERC721Enumerable) can be expensive on large drops.
  • ERC-1155: Batch mint/transfer amortizes overhead across many IDs/amounts, reducing per-item cost. Great for airdrops and game loot distributions.

If you’re minting pure 1/1s only, 721 is competitive and simpler. If you mint thousands of identical items or move many IDs frequently, 1155’s batch primitives can save substantial gas and simplify indexing.

5) Royalties (EIP-2981) Overview

EIP-2981 provides a standard interface for contracts to report royalty info (receiver + amount) given a sale price. Both 721 and 1155 can implement 2981 with per-token or global logic.
Remember: 2981 does not enforce payment; marketplaces decide whether to honor it. For multi-creator projects, route the receiver to a splitter contract so collaborators are paid programmatically.

6) Choosing 721 vs 1155

Consideration ERC-721 ERC-1155
Item types Unique 1/1s, PFPs, bespoke traits Editions, stackables, consumables, mixed (fungible + NFT)
Batch efficiency Single-item ops Native batch mint/transfer
Marketplace/tooling maturity Very high (historically first-class) High; some older tools are 721-centric
Metadata pattern Per-token tokenURI uri() + {id} substitution
Best for Art/PFP, certificates, unique collectibles Games, tickets/passes by tier, airdrops, large-scale editions
Quick decision tree:
If your collection needs both a fungible utility token and multiple NFT item classes under one address → 1155.
If your main value is per-item uniqueness, provenance stories, and the broadest marketplace compatibility → 721.

7) Pitfalls & Edge Cases

  • Receiver hooks: Sending to contracts that lack onERC721Received or onERC1155Received reverts (for safe transfers) or risks lockups (for non-safe). Always prefer safe* methods.
  • Enumeration costs: 721 “enumerable” extensions can be gas-heavy on big drops. Consider off-chain indexing instead of on-chain enumeration.
  • 1155 ID formatting: Clients expect {id} substituted as lowercase 0x-stripped 64-hex. If your server paths don’t match, images/metadata won’t load.
  • Approvals & drainers: Both standards use setApprovalForAll. Educate users and consider operator allowlists for safer defaults.
  • Bridging: Mirrored contracts on L2/other L1s may not preserve your royalty/metadata policies. Coordinate official bridges and verify addresses publicly.
  • Upgrades: If you use proxies to change baseURI/logic, protect with timelocks and transparent governance to avoid trust shocks.

8) Developer Patterns & Snippets

  • Editions with 1155: One ID per edition; mint different amounts to different wallets. Great for allowlists with per-wallet caps.
  • Editions with 721: One ID per token; include editionNumber/editionSize in JSON. Simpler for 721-first tooling.
  • Access control: Use roles (e.g., MINTER_ROLE) and separate admin vs. operator keys. Pausable guards help during incidents.
  • Provenance: Publish a provenance hash for art reveals; store on-chain if feasible so the reveal order can be audited.
// 721 per-token URI (illustrative)
mapping(uint256 => string) private _tokenURIs;

function _setTokenURI(uint256 tokenId, string memory u) internal {
  require(_exists(tokenId), "no token");
  _tokenURIs[tokenId] = u;
}

function tokenURI(uint256 tokenId) public view returns (string memory) {
  string memory u = _tokenURIs[tokenId];
  return bytes(u).length > 0 ? u : baseURI; // fallback if unrevealed
}

Quick check

  1. Which standard models balances per id and supports batch transfers natively?
  2. Why is ERC-1155 a natural fit for editions and game items?
  3. How is metadata typically served for 1155 vs 721?
  4. What does EIP-2981 do, and what does it not do?
Show answers
  • ERC-1155.
  • One id can represent many identical items with quantities; batch ops make large mints/transfers efficient.
  • 1155 uses a base uri() with {id} hex substitution; 721 typically returns a per-token tokenURI.
  • 2981 standardizes reporting (receiver + amount) for a sale price; it does not enforce payment, marketplaces handle that.

Go deeper

Next up: how royalties work in practice across marketplaces.


Next: Royalties & Marketplaces →