← Protocols
ERC-4906 — NFT Metadata Update Event
Standard / EIP·EVM

ERC-4906 — NFT Metadata Update Event

01Description

Final ERC standard. Extends ERC-721 with two events — `MetadataUpdate(uint256 tokenId)` and `BatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId)` — so marketplaces and indexers know to refresh `tokenURI` without polling.

02Best for
  • 01dynamic / on-chain generative NFTs
  • 02reveal mechanics after mint
  • 03evolving game items and SBTs
  • 04metadata-as-state collections
  • 05any project where `tokenURI` changes after mint
03Install
  • pnpm add @openzeppelin/contracts
05Prompt snippet
Add ERC-4906 to an ERC-721 by extending `ERC721URIStorage` from `@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol` (which already declares the events) or by emitting them yourself: `emit MetadataUpdate(tokenId)` after any change to a single token's metadata, and `emit BatchMetadataUpdate(fromTokenId, toTokenId)` after a range update. The interface ID is `0x49064906`; advertise it via `supportsInterface`. ERC-4906 layers on top of ERC-721 and ERC-1155 (community-extended) — it never changes transfer semantics, only telegraphs metadata invalidation.
06Gotchas
  • Indexers and marketplaces (OpenSea, Reservoir, Alchemy) refresh on a best-effort basis — emitting the event does not guarantee fast or universal refresh.
  • `BatchMetadataUpdate(0, type(uint256).max)` is the convention for 'invalidate everything' but very expensive for indexers — prefer tight ranges where possible.
  • The event must be emitted AFTER the metadata-affecting state change, otherwise refreshers may re-cache stale data.
  • ERC-4906 only signals invalidation — it does not version, sign, or commit to the new metadata. Off-chain `tokenURI` mutability concerns still apply.
  • Some implementations forget to update `supportsInterface` to include `0x49064906`, causing aware indexers to skip the collection entirely.
07Alternatives