This ERC defines a standard for storing contract-level metadata onchain. It extends ERC-7572’s contract-level metadata concept by providing onchain storage. Contracts MAY optionally use ERC-8042’s Diamond Storage pattern for predictable storage locations, enabling cross-chain compatibility and supporting upgradable contracts.
Motivation
Contract metadata today typically relies on offchain storage such as URLs or IPFS, creating trust and availability risks—servers go down, domains expire, and malicious actors can modify data without onchain record. Storing metadata onchain makes contract identity censorship-resistant and enables wallets and block explorers to display verifiable information without trusting external services.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Required Metadata Function and Event
Contracts implementing this ERC MUST implement the following interface:
interfaceIERC8049{/// @notice Get contract metadata value for a key.
functiongetContractMetadata(stringcalldatakey)externalviewreturns(bytesmemory);/// @notice Emitted when contract metadata is updated.
eventContractMetadataUpdated(stringindexedindexedKey,stringkey,bytesvalue);}
Contracts implementing this ERC MAY also expose a setContractMetadata(string calldata key, bytes calldata value) function to allow metadata updates, with write policy determined by the contract.
Contracts implementing this ERC MUST emit the following event when metadata is set:
This ERC specifies that the key is a string type and the value is bytes type. This provides flexibility for storing any type of data while maintaining an intuitive string-based key interface.
Optional Key Parameters
Keys MAY include parameters to represent variations or instances of a metadata type, such as "registration: 1" or "name: Maria"; see ERC-8119: Key Parameters.
Optional Diamond Storage
Contracts implementing this ERC MAY use Diamond Storage pattern for predictable storage locations. If implemented, contracts MUST use the namespace ID "erc8049.contract.metadata.storage".
The Diamond Storage pattern provides predictable storage locations for data, which is useful for cross-chain applications using inclusion proofs and for upgradable contracts. For more details on Diamond Storage, see ERC-8042.
Value Interpretation
If no standard is specified for a metadata value, clients MAY assume the value is a UTF-8 encoded string (bytes(string)) unless otherwise specified by the implementing contract or protocol.
Examples
Example: Basic Contract Information
A contract can store basic information about itself:
A contract can specify its ENS name using this standard:
Key: "ens_name" → Value: bytes("mycontract.eth")
This allows clients to discover the contract’s ENS name and resolve it to get additional information about the contract.
Optional Metadata Hooks
Contracts implementing this ERC MAY use hooks to redirect metadata resolution to a different contract. For the full specification, see ERC-8121. When using hooks with contract metadata, the target function MUST be getContractMetadata(string) returning bytes. The hook selector is 0x9e574b14.
Rationale
This design prioritizes simplicity and flexibility by using a string-key, bytes-value store that provides an intuitive interface for any type of contract metadata. The minimal interface with a single getContractMetadata function provides all necessary functionality. The optional setContractMetadata function enables flexible access control for metadata updates. The required ContractMetadataUpdated event provides transparent audit trails with indexed key for efficient filtering. Contracts that need predictable storage locations can optionally use Diamond Storage pattern. This makes the standard suitable for diverse use cases including contract identification, collaboration tracking, and custom metadata storage.
Backwards Compatibility
Fully compatible with existing smart contracts.
Non-supporting clients can ignore the scheme.
Reference Implementation
The interface is defined in the Required Metadata Function and Event section above. Here are reference implementations:
Basic Implementation
pragmasolidity^0.8.25;import"./IERC8049.sol";contractBasicContractMetadataisIERC8049{// Simple mapping for contract-level metadata
mapping(stringkey=>bytesvalue)private_metadata;functiongetContractMetadata(stringcalldatakey)externalviewoverridereturns(bytesmemory){return_metadata[key];}functionsetContractMetadata(stringcalldatakey,bytescalldatavalue)external{_metadata[key]=value;emitContractMetadataUpdated(key,key,value);}}