ERC-8407: Extensible Contract Metadata

We’d like to gather feedback on a draft ERC, Extensible Contract Metadata, before opening a PR to ethereum/ERCs.

The problem

Onchain metadata is conventionally exposed through purpose-built functions — one function per piece of metadata, each returning a specific value. Adopting a new piece of metadata therefore means adding a new function, i.e. changing the contract’s code. For already-deployed contracts that’s an upgrade, and upgrades are frequently impractical: many contracts are non-upgradeable by design, have no privileged owner, or are too widely integrated to migrate safely. Useful metadata conventions stall because the contracts that would carry them can’t economically adopt them.

The idea

Standardize a single generic key→value string surface that a contract exposes once. From then on, adopting any new metadata convention is a matter of writing a value at a new key — no new function, no new code, no upgrade. The convention that gives a key its meaning can be defined independently and after the contract was deployed.

This ERC deliberately standardizes only the transport — how an entry is read, written, observed, and discovered. It does not define any particular key or the value expected at it. The intent is that subsequent ERCs build on this one by enshrining specific keys and their expected values; those definitions are out of scope here.

Interfaces

A read interface consumers depend on, and an optional writable extension. Support is advertised via ERC-165.

interface IExtraMetadata /* is IERC165 */ {
    event ExtraMetadataUpdated(string key, string value); // empty value = removal
    function extraMetadata(string calldata key) external view returns (string memory value);
}

interface IExtraMetadataWritable /* is IExtraMetadata */ {
    function updateExtraMetadata(string calldata key, string calldata value) external;
}

Key rules:

  • extraMetadata(key) returns the value or the empty string if unset. The empty string is the single canonical “unset”; setting an empty value removes the entry.
  • updateExtraMetadata reverts on an empty key and emits ExtraMetadataUpdated on every change. Write authorization is implementation-defined (implementations should restrict it).
  • ERC-165 ids: 0x4ddf9da0 (read), 0xb2851ef5 (writable).

The pattern is already in production in a deployed token implementation; the ERC generalizes it to any contract.

Design decisions we’d like input on

  1. Split read/write interfaces with separate ERC-165 ids — so a contract with immutable, read-only metadata can be fully conformant without exposing a public writer. Is the split worth the extra id, or would a single interface be preferable?
  2. Empty string = unset = removal. Simple and cheap, but a key can’t hold a legitimately-empty value. Acceptable, or should removal be a distinct operation?
  3. Contract-level (no token id). Keeps it universal; a token-scoped variant would be a separate ERC. Agree?
  4. Strings for keys and values (a governing convention may define an encoding like a URI or JSON within the string). Any case for bytes?
  5. Namespacing. The ERC doesn’t enforce a key namespace and leaves collision-avoidance to the conventions built on top. Should it recommend a namespacing scheme?

Full draft (interfaces, rationale, reference implementation, security considerations) is in the PR we’ll open once this thread has some discussion. Feedback welcome — especially from anyone who has hit the “can’t-upgrade-to-adopt-metadata” wall.

Authors: Conner Swenberg (@ilikesymmetry), Steve Katzman (@stevieraykatz)

From a wallet user’s perspective, having more useful contract information available sounds helpful. My main concern would be how wallets know which metadata keys are recognized and safe to display, especially if anyone can create new conventions. Would there eventually be a trusted list or registry of commonly supported keys?