ERC-7572: Contract-level metadata via `contractURI()`

This specification standardizes contractURI() to return contract-level metadata. This is useful for dapps and offchain indexers to show rich information about a contract, such as its name, description and image, without specifying it manually or individually for each dapp.

interface IERC7572 {
  function contractURI() external view returns (string memory);

  event ContractURIUpdated();
1 Like

Should “featured image” be part of the payload as well?

I feel like OpenSea has three possible images that could be powered by contract-level metadata:

  • Banner Image (banner_image)
  • Collection Image (image)
  • Featured Image (???)

nice suggestion, i think it is a good idea can call it featured_image. however it might be hard to define just one aspect ratio for all types of websites and apps. square (1:1) would likely be the most practical?

Yeah, I think 1:1 would be the most practical.

Potentially you could have a nested JSON structure with different URLs for different aspect ratios??? But that seems unnecessarily convoluted.

agreed keeping it 1:1 would be more simple for people to adopt and use. added! thanks again for the suggestion.

edit: reconsidering omitting a suggested aspect ratio: ERC-7572: Contract-level metadata via `contractURI()` - #14 by ryanio

Strong +1 on Adding Banner / Collection images, this is something we typically have to fetch from marketplaces that store this off-chain.

1 Like

yes, banner and collection images are present :slight_smile: images defined are now: image, banner, and featured_image

Should there be a way for off-chain indexers to determine if ContractURIUpdated will be emitted? Could use ERC-165 or maybe something in the metadata itself?

Thanks for reviewing the ERC! I’m not sure if it’s necessary since offchain indexers will watch to see if ContractURIUpdated is emitted from any contract, the contract doesn’t necessarily have to implement ERC-165 to be added to some kind of “watch list”. I’m not opposed to adding it but don’t see much benefit. What do others think?

Contracts that implement contractURI() today obviously don’t implement IERC7572 and won’t return true from their supportsInterface() implementation.

An indexer can therefore use supportsInterface() to determine if they need to use an “low-efficiency” cache invalidation implementation (eg. polling), or a higher-efficiency one (watching for ContractURIUpdated.)

You’re suggesting indexers use the low-efficiency method for all contracts, until they receive the event, and then switching to event watching? Wouldn’t that mean indexers waste resources for contracts that never get a URI update?

1 Like

Our chain watchers are designed to get and filter logs based on event topic, so we just watch for any logs that come in with the topic0 for ContractURIUpdated(). We don’t have to further scope by contract address. This is easy and doesn’t require any use of supportsInterface(), which is why I didn’t see a need to implement it, but if other watcher systems would benefit from this then I’m not opposed to adding, it’s just not something we would use so didn’t see an immediate need for it. And as you suggest, contracts that have already been deployed won’t have the supportsInterface so it wouldn’t be a foolproof method for detecting if a contract supports the event anyhow. Thanks for continuing the discussion!

I had assumed you have a list of contracts that you need to watch, some of which emit ContractURIUpdated when the URI changes. I guess that’s incorrect, but since you explicitly call out backwards compatibility in your proposal, I still this this is worth discussing.

Imagine the following scenario:

Someone like OpenSea who has to support a wide range of contracts.

Some of those contracts would’ve existed before ERC-7572, and some will have come after.

For contracts predating ERC-7572, the only way to detect a changed contract URI is to poll the contract periodically.

Contracts supporting ERC-7572 will emit an event when their contract URI changes.

Now, if this OpenSea-like platform wants to actually cut their server bill, they’ll want to reduce the amount of useless eth_calls they have to do polling for new URIs. As far as I can see it, the only way (without receiving an event) to determine if a contract requires polling or supports events is with supportsInterface.

I think just adding 165 to requires and a note that implementations SHOULD return true from supportsInterface with the correct id would be sufficient.


Good idea. Dapps can easily integrate this ERC, streamlining the process of displaying rich contract information.

I think I will remove the 1:1 aspect ratio suggestion, since we cannot propose a format that makes everyone happy, and also feels weird to suggest a aspect ratio just for one of the image fields. I think dapps can just process the image however they’d like to fit into their design.


That happens to every “adoption then standardization” behaviors, including ERC-20. I think it’s fine. Retroactively how to identify if a contract support certain behavior we can come up with more ideas.

Ryan, as a standard I think it’s ok to suggest a aspect ratio, as long as we don’t decline other aspect ratios.

Uses “SHOULD” for strong recommendation

Image aspect ratio SHOULD be 1:1 

means it’s highly recommended (but not required) for the NFT issuer to set aspect ratio to 1:1.
it means reader of NFT metadata should assume marjority of image of aspect ratio tobe 1:1 but expect exceptions.

Or use “MAY” for enablement

Image aspect ratio MAY be 1:1 

means it’s ok for the NFT issuer to set aspect ratio to 1:1.
it would be assumed to be supported by reader of the metadata, such as NFT marketplace, dApps or Wallet.

1 Like