Skip to content

ENSIP-16: Metadata Event Discovery

Authors: jefflau, matoken.eth

Created: September 22, 2022

Status: draft

Abstract

This ENSIP specifies APIs for querying metadata directly on the resolver for EIP-3668 (CCIP Read: Secure offchain data retrieval) enabled names. EIP-3668 will power many domains in the future, however since the retrieval mechanism uses wildcard + offchain resolver, there is no standardised way to retrieve important metadata information such as which L2/offchain database the records are stored on and where JSON RPC endpoint is to find event log information.

Motivation

With EIP-3668 subdomains already starting to see wide adoption, it is important that there is a standardised way to discover and access metadata about offchain names.

This ENSIP allows third-party indexing services to listen to the MetadataChanged event to automatically discover and index metadata from different chains and smart contracts, without relying on centralised RPC endpoint repositories.

Specification

Compliant resolvers MUST implement the following interface:

// To be included in
// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/resolvers/Resolver.sol
interface IOffchainResolverMetadataProvider {
 
    /**
     * @dev Returns metadata for discovering the location of offchain name data
     * @param name DNS-encoded name to query
     * @return rpcURLs The JSON RPC endpoint for querying offchain data (optional, may be empty array)
     * @return chainId The chain ID where the data is stored (format for non-EVM systems to be determined)
     * @return baseRegistry The base registry address on the target chain that emits events (optional, may be zero address)
     */
    function metadata(bytes calldata name)
        external
        view
        returns (
            string[] memory rpcURLs,
            uint256 chainId,
            address baseRegistry
        );
 
    event MetadataChanged(
        bytes name,              // DNS-encoded name
        string[] rpcURLs,        // JSON RPC endpoint (optional, may be empty array)
        uint256 chainId,         // Chain identifier (format for non-EVM systems to be determined)
        address baseRegistry     // Base registry address (optional, may be zero address)
    );
}
Requirements:
  • name must be provided to call metadata function. When indexing MetadataChanged event, indexers MUST apply the name to all names that have the suffixes of the name.
  • chainId must be provided. For EVM-compatible chains, chainId SHOULD match the chain's EIP-155 identifier. A chainId of 0 means a non-EVM chain or off-chain database.
  • rpcURLs is optional and may be an empty array.
  • baseRegistry is optional and may be the zero address. If a non-zero address is specified, events will be emitted from this address. The interface of this contract is yet to be determined.

metadata function

The metadata function allows resolvers to dynamically provide information about where offchain data for a given name can be queried. This function returns the same information as would be emitted in a MetadataChanged event: the JSON RPC endpoint URLs, the chain ID where the data resides, and the base registry address on the target chain.

MetadataChanged Event

The MetadataChanged event emits the same information the metadata function returns so that indexers can subscribe to the event as the details change rather than periodically querying the function.

Key Terminology:
  • registry = A contract that manages name ownership and hierarchical relationships for a set of subnames. The base registry manages top-level domains (also known as root registry within the v2 contract), while subregistries manage names under a specific parent
  • subregistry = A registry contract that manages subnames under a parent name. Linked from a parent registry via SubregistryUpdate events
  • registry id/tokenId = The unique identifier for a name NFT, derived from the labelhash and version id that increments every time the permission of the name changes effectively invalidating any permissions or approvals tied to the old token ID.
  • EAC(Enhanced Access Control) = a general-purpose access control base class. resource is a unique key to manage the resource which changes every time tokenId changes. For more detail, read the namechain README. EAC may not be the only way to manage access control and other events may be added in future.
  • node = In v1, node is a unique identifier of the name derived by a namehash logic. In ENS v2, node is a placeholder node for compatibility with standard resolver behavior and always set to 0. The full ENS name attached to the resolver needs to be reconstructed by traversing registry hierarchy set by SubregistryUpdate.

rpcUrls Events

rpcUrls url endpoint emits the following jsonrpc events when chainId is not 0. When chainId is 0 it may emit custom events yet to be determined.

Registry Events

// Emitted when a new subname is registered. 
// A subname without expiration should set type(uint256).max
// Context can attach any arbitrary data, such as resource id to keep track of EAC
event NameRegistered(
    uint256 indexed tokenId,
    string label,
    uint64 expiration,
    address registeredBy,
    uint256 context
);
 
// Emitted when a new token id is generated
event TokenRegenerated(
    uint256 oldTokenId,
    uint256 newTokenId,
    uint256 context
);
 
// Standard ERC1155 transfer event for name ownership changes
event TransferSingle(
    address indexed operator,
    address indexed from,
    address indexed to,
    uint256 id,
    uint256 value // must always be 1
);
 
// Standard ERC1155 transfer event for multiple name ownership changes
event TransferBatch(
   address indexed operator,
   address indexed from,
   address indexed to,
   uint256[] ids,
   uint256[] values
);
 
// Emitted when a name is renewed
 
event ExpiryUpdated(
    uint256 indexed tokenId,
    uint64 newExpiration
);
 
// Emitted when subregistry is updated
event SubregistryUpdated(
    uint256 indexed id,
    address subregistry
);
 
// Emitted when resolver is updated
event ResolverUpdated(
    uint256 indexed id,
    address resolver
);

Resolver Events

event AddressChanged(
    bytes32 indexed node,
    uint256 coinType,
    bytes newAddress
);
 
event AddrChanged(
    bytes32 indexed node,
    address a
);
 
event TextChanged(
    bytes32 indexed node,
    string indexed indexedKey,
    string key,
    string value
);
 
event ContenthashChanged(
    bytes32 indexed node,
    bytes hash
);
 
event NameChanged(
    bytes32 indexed node,
    string name)
;

Rationale

This ENSIP addresses a key limitation of EIP-3668: while it enables offchain data retrieval, it provides no standardized way for third parties to discover where that data lives or how to index it.

By providing metadata at the resolver level, this ENSIP enables:

  1. Automatic indexer discovery - Indexers can discover new L2/offchain data sources by listening to events, without requiring manual configuration or centralized registries of RPC endpoints.

  2. Flexible data sources - The optional nature of rpcURLs and baseRegistry accommodates different deployment patterns: from fully decentralized L2 registries that emit events, to custom databases that may emit APIs yet to be determined that are more suitable to index non-EVM chains or offchain database names.

  3. Future extensibility - By requiring chainId but leaving the non-EVM format undefined, this ENSIP establishes the pattern while remaining open to future non-EVM integrations.

Copyright

Copyright and related rights waived via CC0.