What is ERC-1155?
The multi-token standard that compressed assets into IDs — and pushed semantics into every integration.
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
- What is ERC-1155?
- At a glance
- Origin story
- The spec
- What's broken
- Token IDs hide asset semantics
- Metadata is one URI template
- setApprovalForAll is contract-wide
- receiver surface is still asset-specific
- One contract becomes one product boundary
- LUKSO alternative
- ERC-1155 vs LSP7+LSP8
- When to use which
- FAQ
- Sources
- Keep reading
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
- Canonical spec
- eips.ethereum.org / EIP-1155
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.
- Jun 2018 ERC-1155 is created as a multi-token standard for contracts that need many token types and batch transfers. ↗
- 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.
- 2023 LUKSO mainnet ships the LSP asset stack, splitting fungible and identifiable assets into LSP7 and LSP8 while sharing metadata and receiver hooks.
What ERC-1155 actually is.#
// 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);
balanceOf · balanceOfBatch · isApprovedForAll · uri safeTransferFrom · safeBatchTransferFrom · setApprovalForAll TransferSingle · TransferBatch · ApprovalForAll · URI 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.
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.
-
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-1155balanceOf(owner, id)LSP7 + LSP8standard chosen by asset shapeworkarounds tried- type-bit token IDs
- off-chain collection manifests
- custom indexer adapters
- per-game metadata registries
-
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-1155uri(id) returns (string)LSP4 + ERC-725Ytyped asset + per-token data keysworkarounds tried- centralized metadata APIs
- IPFS JSON by token ID
- OpenSea-style attributes
- ERC-4906-style refetch events
-
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-1155setApprovalForAll(operator, true)LSP6AllowedCalls + controller permissionsworkarounds tried- per-id escrow contracts
- marketplace allowlists
- custom transfer validators
- separate ERC-1155 contracts per asset family
-
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-1155onERC1155Received / onERC1155BatchReceivedLSP1universalReceiver(typeId, data)workarounds tried- holder mixins
- adapter contracts
- rescue functions
- asset-specific receiver interfaces
-
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-1155one contract, many meaningsLSP7 + LSP8split contracts by semanticsworkarounds tried- new contract versions
- collection registries
- proxy upgrades
- per-id branching
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.
- LSP7 Digital Asset The fungible side of the split: balances, amount-scoped operators, transfer data, and LSP1 notifications.
- LSP8 Identifiable Digital Asset The identifiable side: bytes32 token IDs, per-token ERC-725Y data, and the same receiver-aware transfer model.
- LSP4 Digital Asset Metadata Typed metadata for both LSP7 and LSP8 assets, including VerifiableURI references and extensible ERC-725Y keys.
- LSP1 Universal Receiver One receiver hook for every asset family instead of ERC-721 and ERC-1155-specific callback shapes.
- LSP6 Key Manager Move broad operator authority from token contracts to a standard account permission layer.
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
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.