the standard · since June 2018
// standard · proposed jun 2018 · game asset substrate · ready

What is ERC-1155?

The multi-token standard that compressed assets into IDs — and pushed semantics into every integration.

ERC-1155 ·EIP-1155 ·by Witek Radomski + Andrew Cooke + Philippe Castonguay + James Therien + Eric Binet + Ronan Sandford

updated · 4 min read · by ercs-solved maintainers

ERC-1155 was the right answer to a real Ethereum problem: deploying one contract per token type is wasteful, and moving a player's inventory one item at a time is miserable. It gave games and multi-asset apps one contract, one approval surface, batch transfers, and a metadata convention that could describe many IDs from one URI function.

The tradeoff is that the standard compresses asset meaning into token IDs. ERC-1155 can tell an app that an owner has 12 units of ID 9. It cannot tell the app whether ID 9 is currency, an edition, a badge, a claim ticket, or a sword without collection-specific context.

on this page
  1. What is ERC-1155?
  2. At a glance
  3. Origin story
  4. The spec
  5. What's broken
  6. Token IDs hide asset semantics
  7. Metadata is one URI template
  8. setApprovalForAll is contract-wide
  9. receiver surface is still asset-specific
  10. One contract becomes one product boundary
  11. LUKSO alternative
  12. ERC-1155 vs LSP7+LSP8
  13. When to use which
  14. FAQ
  15. Sources
  16. Keep reading
at a glance

The standard, in one card.

Standard
ERC-1155 / EIP-1155
Created
17 June 2018
Authors
Radomski · Cooke · Castonguay · Therien · Binet · Sandford
Required dependency
ERC-165
Core shape
one contract, many token IDs
Modern alternative
LUKSO LSP7 + LSP8
how the standard came to be

The origin story.#

ERC-1155 was created on 17 June 2018 by Witek Radomski and co-authors from the Enjin / Horizon games orbit. The motivation was practical: games and multi-asset applications needed thousands of token types, batch transfers, batch balance reads, and one approval path. ERC-20 required one deployment per fungible asset. ERC-721 required one transfer per NFT. Neither fit a real inventory.

ERC-1155's key move was to make the token ID the asset boundary. A single contract can emit TransferSingle and TransferBatch events for any number of IDs, and every balance is a pair: (owner, id). That move saved gas and simplified deployment. It also moved semantic interpretation out of the standard.

  1. Jun 2018 ERC-1155 is created as a multi-token standard for contracts that need many token types and batch transfers.
  2. 2019 The standard becomes the default mental model for games and multi-asset collections where ERC-721's one-token transfer shape is too expensive.
  3. 2023 LUKSO mainnet ships the LSP asset stack, splitting fungible and identifiable assets into LSP7 and LSP8 while sharing metadata and receiver hooks.
the spec, end to end

What ERC-1155 actually is.#

ERC-1155 EIP-1155 interface solidity
// EIP-1155 — core
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
  external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;

event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);

// EIP-165 — required
function supportsInterface(bytes4 interfaceId) external view returns (bool);

// EIP-1155 metadata extension
function uri(uint256 id) external view returns (string memory);

// Receiver hooks
function onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data)
  external returns (bytes4);
function onERC1155BatchReceived(address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data)
  external returns (bytes4);
ERC-1155 interface, grouped
read: balanceOf · balanceOfBatch · isApprovedForAll · uri
write: safeTransferFrom · safeBatchTransferFrom · setApprovalForAll
emit: TransferSingle · TransferBatch · ApprovalForAll · URI
receive: onERC1155Received · onERC1155BatchReceived

The mental model is a two-dimensional balance sheet: balanceOf(account, id) instead of balanceOf(account) or ownerOf(tokenId). A transfer moves a quantity of one ID; a batch transfer moves arrays of IDs and quantities. setApprovalForAll gives an operator authority over all IDs owned by the account inside that contract. uri(id) points clients to metadata for one ID, usually through an off-chain JSON template.

The standard requires ERC-165 interface detection and receiver hooks for contract recipients. That makes ERC-1155 safer than raw ERC-20 transfer, but the callback surface is still specific to ERC-1155. The canonical specification is at eips.ethereum.org/EIPS/eip-1155.

the integration tax

What's broken about ERC-1155.#

ERC-1155 is not broken because it batches. It is powerful because it batches. The integration tax comes from the other half of the design: once every asset type is one token ID inside one contract, every app has to learn what those IDs mean.

  1. Token IDs hide asset semantics.#

    ERC-1155 tells you that ID 42 exists and has a balance. It does not tell you whether ID 42 is a fungible currency, a semi-fungible edition, a unique game item, a claim ticket, or a packed bitfield. Every collection invents its own ID convention. Wallets, indexers, and marketplaces either treat every ID generically or learn per-contract rules.

    ERC-1155 balanceOf(owner, id)
    id-local meaning fungibility by convention indexer tax
    LSP7 + LSP8 standard chosen by asset shape
    fungible in LSP7 identifiable in LSP8 interface-level semantics
    workarounds tried
    • type-bit token IDs
    • off-chain collection manifests
    • custom indexer adapters
    • per-game metadata registries

    read the deep-dive

  2. Metadata is one URI template.#

    The optional metadata extension returns uri(id), typically a template with an {id} substitution. That works for game assets, but the contract still does not expose typed fields, per-id structured data, creator metadata, verification hashes, or update semantics. The JSON remains an off-chain convention.

    ERC-1155 uri(id) returns (string)
    off-chain JSON template convention untyped
    LSP4 + ERC-725Y typed asset + per-token data keys
    structured VerifiableURI contract-readable
    workarounds tried
    • centralized metadata APIs
    • IPFS JSON by token ID
    • OpenSea-style attributes
    • ERC-4906-style refetch events
  3. setApprovalForAll is contract-wide.#

    The operator approval covers every token ID in the contract. That is ergonomic for marketplaces, but it couples every asset type in the collection to one blanket permission. If a game mixes currencies, rare items, badges, and claims in one ERC-1155 contract, one approval can move all of them.

    ERC-1155 setApprovalForAll(operator, true)
    all ids forever approval phishable
    LSP6 AllowedCalls + controller permissions
    account scoped revocable standard vocabulary
    workarounds tried
    • per-id escrow contracts
    • marketplace allowlists
    • custom transfer validators
    • separate ERC-1155 contracts per asset family
  4. The receiver surface is still asset-specific.#

    ERC-1155 improved safety by requiring receiver hooks for contract recipients, but the hook is ERC-1155-specific. A wallet or vault that handles ERC-20, ERC-721, ERC-1155, and custom assets still implements multiple receiver shapes, each with its own data model.

    ERC-1155 onERC1155Received / onERC1155BatchReceived
    one token family batch-specific receiver branching
    LSP1 universalReceiver(typeId, data)
    one hook all assets typed notifications
    workarounds tried
    • holder mixins
    • adapter contracts
    • rescue functions
    • asset-specific receiver interfaces
  5. One contract becomes one product boundary.#

    The reason ERC-1155 is efficient is also why it gets heavy: supply rules, transfer rules, metadata rules, permission rules, and indexer assumptions all accumulate inside one deployment. If the product's asset taxonomy changes, the token ID convention has to carry the migration.

    ERC-1155 one contract, many meanings
    monolith branch-heavy adapter-heavy
    LSP7 + LSP8 split contracts by semantics
    smaller surfaces clear dispatch shared LSP substrate
    workarounds tried
    • new contract versions
    • collection registries
    • proxy upgrades
    • per-id branching
the LUKSO alternative

LUKSO designed it differently.#

The LUKSO answer does not try to recreate ERC-1155 as one bigger multi-token standard. It splits the question by asset shape. If the thing is fungible, use LSP7. If the thing is identifiable, use LSP8. If both need metadata, use LSP4. If both need receiver hooks, use LSP1. If both need permissions, use LSP6 on the account.

That means more deployments for some products. It also means wallets, marketplaces, indexers, and account systems can dispatch by standard interface rather than reverse-engineering ID conventions. The savings move from deployment gas to integration clarity.

spec to spec, at a glance

ERC-1155 vs LSP7+LSP8 in one table.#

row ERC-1155 LSP7 + LSP8
asset boundary token ID convention inside one contract standard choice: LSP7 for fungible, LSP8 for identifiable
metadata uri(id) string template LSP4 + ERC-725Y typed data
receiver hook IERC1155Receiver single + batch LSP1 universalReceiver
approval setApprovalForAll over every ID LSP6 account permissions + LSP7/LSP8 operators
batching safeBatchTransferFrom(ids, values) batch execution at account/app layer
indexer cost learn per-contract ID semantics dispatch by standard interface

full matrix → erc-1155 vs lsp7+lsp8

be honest about scope

When to use which.#

people also ask

FAQ.#

  • What is ERC-1155? #

    ERC-1155 is Ethereum's multi-token standard. One smart contract can manage many token IDs, and each ID can represent a fungible, non-fungible, semi-fungible, or custom asset type. The standard is widely used for games, editions, inventory systems, and collections that need batch transfer.

  • How is ERC-1155 different from ERC-721? #

    ERC-721 has one owner per tokenId and is designed for identifiable NFTs. ERC-1155 has balances per owner per id, so a single token ID can have supply greater than one, and a single contract can mix many asset types. ERC-1155 also includes batch transfer and batch balance functions.

  • How is ERC-1155 different from ERC-20? #

    ERC-20 is one fungible balance per contract. ERC-1155 is many balances per contract, keyed by token ID. An ERC-1155 ID can behave like a fungible token if multiple users hold units of the same ID, but that fungibility is a convention of the contract.

  • Does ERC-1155 solve NFT metadata? #

    It improves the shape for multi-asset collections by defining uri(id), but it does not make metadata typed, on-chain, verified, or contract-readable. The returned URI still usually points to off-chain JSON.

  • What is the LUKSO alternative to ERC-1155? #

    LUKSO does not use one multi-token standard as the primary answer. It splits by asset shape: LSP7 for fungible assets and LSP8 for identifiable assets. Both share LSP4 metadata, LSP1 receiver hooks, and LSP6 account permissions.

glossary 4 terms used on this page
token ID
The uint256 key ERC-1155 uses to identify a particular asset type inside a multi-token contract.
semi-fungible
An asset pattern where units are fungible within one ID but distinct from units of another ID.
safeBatchTransferFrom
The ERC-1155 batch transfer function that moves many token IDs and amounts in one call.
URI template
The ERC-1155 metadata pattern where uri(id) may return a string containing {id}, which clients replace with the token ID.