Introduces a new standard for storing arbitrary metadata directly onchain for ERC-721, ERC-1155, ERC-6909, and ERC-8004 registries.
Key features:
Key-value pair interface: string keys mapped to bytes values for each token
Required metadata() function and MetadataSet event
Backwards compatible with existing token standards
Enables trustless AI agents, proof of personhood, and custom metadata
This addresses the long-felt need for uniform onchain metadata storage while avoiding gas inefficiencies.
Note on Standard History:
This onchain metadata standard was originally introduced as part of ERC-8041 on September 30, 2025 (commit 13f11f2). ERC-8041 later pivoted to focus on fixed-supply agent collections, so this core metadata functionality is being reintroduced as a standalone standard.
This ERC is extremely useful, in my opinion, for anything involving tokenized assets, onchain collectibles, and agents.
I suggest changing the name of the getter function to justmetadata(). This is because, across the most prominent EIPs, none of the getter functions use the get prefix to indicate that it is indeed a getter.
For example, ERC-20 doesn’t have getName() or getDecimals(); it is just name() and decimals(). This should follow the same principles
Regarding what you said about the two topics having a purpose, I don’t see it, maybe I’m not looking in the right place, but what would be the scenario where a user might want to used indexedKey instead of key, why not just indexed the key, and call it a day?
Also I’ve foud it extremy useful having a keys() so entities interacting with the smart contract know what keys are stored in the the metadadata mapping, but I dont think it should be attached to ERC, what do you think? @nxt3d
The reason for having the indexed key and the non-indexed key is that for new key values that are unknown, we need to have the unhashed name of the key.
Hi there, we’d like to use the ERC-8048 standard with our existing NFT project, Normies. Since the project is already deployed, we can’t modify the core contract to utilize it directly. However, we do have an external renderer contract where we’ve forwarded the tokenURI function. Is it possible to add an optional extension that allows us to implement this standard via our renderer contract instead? Thanks.
Hey! I just added an optional Onchain Metadata Contract Reference extension to solve this issue. You can keep your deployed contract as-is and add a top-level “metadata_contract” field to the JSON your renderer returns, pointing to an external contract that implements metadata(uint256, string). Clients that don’t know about it just ignore the field, so nothing breaks.
I think the ERC is becoming too opinionated, shouldn’t we strive to keep it as minimal as possible. For example there is no mint implementation on the ERC20 that was the right call because it allowed anyone to implement mint however they wanted, bringing this up for discussion
The Onchain Metadata Contract Reference is an optional extension, so it might not affect the core ERC? However, it could be split into a new ERC to make this one more compact.