Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7828: Interoperable Names

Defines a human readable chain-specific address format that allows for chain discovery using ENS.

Authors Sam Kaufman (@SampkaML), Marco Stronati (@paracetamolo), Yuliya Alexiev (@yuliyaalexiev), Jeff Lau (@jefflau), Sam Wilson (@samwilsn), Vitalik Buterin (@vbuterin), Teddy (@0xteddybear), Joxes (@Joxess), Racu (@0xRacoon), Skeletor Spaceman (@0xskeletor-spaceman), TiTi (@0xtiti), Gori (@0xGorilla), Ardy (@0xArdy), Onizuka (@onizuka-wl), Lumi (@oxlumi), Moebius (@0xmoebius), Thomas Clowes (@clowestab), Prem Makeig (@nxt3d), Mono (@0xMonoAx), Orca (@0xrcinus)
Created 2024-11-27
Discussion Link https://ethereum-magicians.org/t/erc-7828-chain-specific-addresses-using-ens/21930
Requires EIP-155, EIP-7930

Abstract

This proposal defines an Interoperable Name, a human-readable chain-specific address format that MAY represent the target address as an ENS name.

Additionally, the target chain component of an Interoperable Name may be expressed as a human-readable label. This specification defines how such labels can be resolved, via the Ethereum Name Service (ENS), to chain-specific metadata.

The result is chain-specific addresses such as wallet.ensdao.eth@eip155:1, 0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@eip155:1 or the maximally readable example.eth@base.

Motivation

The core motivation for introducing the Interoperable Name standard is to provide maximally readable, chain-specific addresses for user-facing interactions.

ERC-7930 introduced a binary format for representing a target address on a specific blockchain. While this binary data is well suited for low-level usage (e.g. in smart contracts), its meaning is semantically opaque to human users.

A foundational text representation (e.g. 0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@eip155:1) enables a significantly more readable chain-specific address format. An expanded form that leverages the name resolution capabilities of the Ethereum Name Service (ENS) further improves readability, allowing addresses to be expressed in a maximally human-friendly form (e.g. wallet.ensdao.eth@ethereum).

An on-chain registry provides a canonical source of truth for mapping human-readable chain labels to the metadata associated with each chain. Today, chains are identified using a variety of specifications (e.g. [CAIP 2] and EIP-155 for EVM-compatible networks), whose formats are not necessarily semantically clear to human users. By introducing an on-chain registry, applications can refer to a chain using a readable identifier such as base, rather than an opaque identifier like eip155:8543 or 8543.

Historically, the mapping from chain names to identifiers has, since EIP-155, been maintained off-chain using a centralized list.

This approach has several shortcomings:

  • It does not scale with the growing number of blockchains
  • It relies on a trusted centralized maintainer
  • It does not support non-EVM chains

This specification defines an architecture that enables chain operators to take ownership of their chain-specific data, thereby reducing reliance on a single centralized entity and ensuring data integrity.

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.

Terminology

This section builds upon the Terminology defined in ERC-7930.

Interoperable Name
A human-readable chain-specific address format meant to be used by humans for user-facing interactions. e.g. 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@eip155:1#4CA88C9C

Interoperable Name Definition

The format of an Interoperable Name is <address> @ <chain> # <checksum> where the components match the following regular expressions:

Syntax

<address>             ::= [.-:_%a-zA-Z0-9]*
<chain>               ::= [.-:_a-zA-Z0-9]*
<checksum>            ::= [0-9A-F]{8}

These components have the following meanings:

  • <address> can either be:

    • A target address as defined in ERC-7930.
    • An Ethereum Name Service (ENS) name. e.g, example.eth
  • <chain> can either be:

    • The string representation of a specific blockchain as defined in CAIP-350. For example eip155:1 for Ethereum Mainnet, or solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d for Solana Mainnet.
    • A human-readable label identifier for a specific chain, defined and registered as a subdomain of the on.eth ENS name. An on-chain registry-resolver maps these labels to their corresponding canonical ERC-7930 chain identifiers, and exposes additional chain metadata.
    • When a target address is used directly within the <address> component, a CASA namespace, with no trailing colon can be used - for example, eip155 or solana. When an ENS name is used you MUST specify both the namespace and reference elements of the CAIP-2 identifier as ENS resolves addresses on a chain-specific basis.
  • <checksum> is defined as the first 4 bytes (8 characters) of the Keccak-256 hash, represented as a hexadecimal string (Base16, as specified in RFC 4648). The hash is computed over the concatenation of the following binary fields from the canonical ERC-7930 Interoperable Address:

    • ChainType
    • ChainReferenceLength
    • ChainReference
    • AddressLength
    • Address

Note: The Version field MUST NOT be included in the hashed data.

Checksums

  • Clients MAY include the checksum when displaying an Interoperable Name within their interface.
  • The checksum MUST be computed and included when sharing an Interoperable Name.
  • Clients MAY accept Interoperable Name inputs without a checksum.

When a user-provided Interoperable Name is inputted with a checksum, clients MUST derive the underlying Interoperable Address, recalculate the checksum, and compare it to the provided value. In case of a mismatch, clients MUST warn the user and require explicit user input to continue with the operation.

It is not guaranteed that an ENS name defined within the <address> component will always resolve to the same address. In some cases resolvers return a new address on each resolution. In this scenario the validation of a previously generated checksum will always fail.

Parsing and Serialization:

If an ENS name is used within the <address> component it should be resolved to a target address subject to the ENS protocol specifications, giving consideration to the target chain defined in the <chain> component.

Once both target address and target chain have been determined, the binary Interoperable Address can be generated as outlined in ERC-7930.

When parsing an Interoperable Name to generate its binary Interoperable Address, clients MUST follow the normalization and serialization rules defined in the relevant CAIP-350 profile for the given <chain> and <address>. This ensures that different valid text representations (e.g., case variations in an address) resolve to a single, canonical binary form, which is essential for consistent checksum calculation and data integrity.

Target Address Examples

Ethereum Mainnet

The address 0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7 on Ethereum Mainnet could be represented as either of the following:

0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@eip155:1#80B12379
0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@ethereum#80B12379

Note: In the second example ethereum is the chain label for Ethereum mainnet in the on-chain ENS Registry-Resolver (see below).

Non-EVM chains

The address bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk on Bitcoin Mainnet could be represented as:

bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk@bip122:000000000019d6689c085ae165831e93#597D21A1
bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk@bitcoin#597D21A1

Note: In the second example bitcoin is the chain label for Bitcoin mainnet in the on-chain ENS Registry-Resolver (see below).

ENS <address> Examples

ENS resolves addresses on a chain-specific basis, as outlined in ENSIP-9 and ENSIP-11.

Ethereum Mainnet

Assuming that example.eth resolves to 0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7 for Ethereum mainnet either of the following could be used to represent the same target address:

example.eth@eip155:1#80B12379
example.eth@ethereum#80B12379

Non-EVM chains

Assuming that example.eth resolves to bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk for Bitcoin mainnet either of the following could be used to represent the same target address:

example.eth@bip122:000000000019d6689c085ae165831e93#597D21A1
example.eth@bitcoin#597D21A1

Resolving chain names

Chain names without a dot (.) are interpreted as labels under a reserved ENS second-level domain .eth and resolved via a wildcard resolver contract. This resolver acts as a single source of truth for mapping human-readable chain names to their corresponding chain identifiers encoded in the [ERC-7930] binary format.

To enable onchain resolution between chain names and chain identifiers, a minimal L2Resolver contract SHOULD implement the following methods. The examples below assume the <namespace>.eth name to be l2.eth.

  • function chainId(bytes32 _node) returns (bytes memory _chainBytes) which resolves a chain l2.eth name to its ERC-7930 chain identifier representation.
  • function chainName(bytes calldata _chainIdBytes) returns (string memory _chainName) which resolves an ERC-7930 chain identifier to a human-readable chain name.

To obtain the human-readable chain name corresponding to a [CAIP 2] chain identifier, clients SHALL:

  1. Encode the [CAIP 2] identifier in ERC-7930 v1 binary form (AddressLength = 0); name the result chainBytes.
  2. Build resolver calldata: callData = abi.encodeWithSelector(IL2Resolver.chainName.selector, chainBytes).
  3. Query the Universal Resolver: result = UniversalResolver.resolve(dnsEncode("l2.eth"), calldata).
  4. ABI-decode result as (string fullName).
  5. Verify fullName ends with .l2.eth.
  6. Strip the suffix and apply UTS #46 lower-case normalisation. • Use the remaining label (e.g. “arbitrum” instead of “arbitrum.l2.eth”).

To obtain the chain identifier corresponding to a human-readable chain name, clients SHALL:

  1. Apply UTS #46 lower-case normalisation to the chain name.
  2. Append the reserved suffix: full = "arbitrum" + ".l2.eth".
  3. Compute node = namehash(full) as per ENSIP-1.
  4. Build resolver calldata: callData = abi.encodeWithSelector(IL2Resolver.chainId.selector, node).
  5. Query the Universal Resolver: result = UniversalResolver.resolve(dnsEncode(full), callData).
  6. ABI-decode result as (bytes chainBytes). • If chainBytes is empty → no mapping exists; treat the label as unknown.

Supported CASA namespaces

While currently only eip155 chains are supported, the on-chain registry could start listing other chains in order to make human-readable names for non-evm chains possible.

Resolving address names

The entirety of address name resolving of all TLDs is delegated to ENS, as specified in current & future ENSIPs.

Some caveats for ENS support are:

  • For addresses on chains that are both supported by BIP 44 registered coin type identifiers and the special scheme for the eip155 namespace defined in ENSIP-11, the latter should be used.

Supported CASA namespaces

Forward resolution (Interoperable Address -> Interoperable Name): Supported via the multichain address resolution standard defined in ERC-2304, which uses BIP 44 registered coin type identifiers to resolve names for various chains, including the eip155 namespace.

Reverse resolution (Interoperable Name -> Interoperable Address): EIP-155 chains explicitly supported by ENS by deployment of L2ReverseRegistrar on them and registration of that contract’s address on the ENS registry.

Rationale

  • Using ENS as the only resolving method means it’s enough to use the same Interoperable Addresses v1 for this standard, without extending it to also store the name resolver used. This means however that wallets are free to show users both resolved and unresolved (raw) Interoperable Names.

Backwards Compatibility

The naming scheme herein defined can represent all names supported by ERC-7930 by displaying raw addresses without resolution

Reference Implementation

This section is non-normative, as future ENSIPs can modify the way in which ENS is used. Its purpose is to demonstrate how human-readable interoperable names are resolved to the ERC-7930 binary format used at the protocol level. The following examples assume that chain names are registered as subdomains under l2.eth, and that resolution is performed via L2Resolver capable of mapping those subdomains to ERC-7930 compliant chain identifiers.

Forward resolution step-by-step example

  1. Let the user input an address name. Assume it’s alice.eth.
  2. Let the user select a chain. Assume it’s optimism. The l2.eth suffix is implicit and hidden from end users.
  3. Append l2.eth and compute the ENS namehash as per ENSIP-1: namehash("optimism.l2.eth").
  4. Call L2Resolver.chainId(bytes32 _node) with the result of step 3 as input, which returns the chain ID in ERC-7930 byte format.
  5. Convert the returned chain identifier into the CAIP-2 format, as specified by ERC-7930.
  6. As per ENSIP-11, convert the EIP-155 chainId into an ENSIP-11-specific coinType: 0x80000000 & 0x0000000A == 0x8000000A.
  7. Compute the namehash of the result of step 1, according to ENSIP-1.
  8. Query the ENS registry for the appropriate resolver by calling resolver(bytes32 node) with the result of the step above.
  9. Call addr(bytes32 node, uint256 coinType) on the contract returned on the step above with the results of steps 6 and 5, respectively. This will return the 20 bytes of alice’s OP Mainnet address, assume it’s 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa
    • Failure mode: if result is address zero, that means the name is not registered and resolution can’t be finished.
  10. Serialize ChainType, ChainReferenceLength, ChainReference, AddressLength and Address according to ERC-7930 (Interoperable Address v1): [ 0002 0000 01 0A 14 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ]
  11. Interoperable Address is complete: 0x00020000010A14AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  12. Compute the checksum as described in ERC-7930: 0xC69BEB13 and display it to the user.

Reverse Resolution step-by-step example

Starting from the Interoperable Address serialized above: 0x00010000010A14AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

  1. Pick the first two bytes corresponding to the version: 0x0001. Remaining payload: 0000010A14AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00010002
  2. Parse the ChainType, ChainReferenceLength, ChainReference, AddressLength and Address according to ERC-7930. Remaining payload 00010002
    1. ChainType: 0x0000 -> eip155
    2. ChainReferenceLength: 0x01 -> 1
    3. ChainReference: 0x0A -> 10 (optimism)
    4. AddressLength: 0x14 -> 20 bytes, consistent with eip155
    5. Address: 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa -> alice’s address
  3. Call L2Resolver.chainName(bytes calldata _chainIdBytes) with 0x00000000010A00 as the input. The resolver will return the corresponding ENS name, in this case optimism.l2.eth.
  4. Compute coinTypeAsHex for ENSIP-19:
    • Check if ChainType == 0x0000, as ENSIP-19 does not support non-EVM chains.
    • Check if ChainReference & 0xFFFFFFFF == ChainReference, meaning, all 28 most significant bytes are zero. If this is not the case, fail resolution as ENSIP-19 does not support chainids larger than 4 bytes.
    • Truncate the ChainReference to its 4 least significant bytes: 0x000000A
    • Set the ChainReference’s MSB to 1: 0x000000A | 0x8000000: 0x8000000A
    • Convert to a lowercase-hexadecimal string without 0x prefix: 8000000a
  5. Compute the address as ENSIP-19 expects it, by producing the lowercase-hexadecimal string without 0x prefix of Address: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
  6. Convert the output from two steps above to a reverse lookup string of the form <address>.<coinType>.reverse for ENSIP-19: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.8000000a.reverse
  7. Find resolver to use for address according to ENS wildcard resolution.
    1. Call resolver(namehash(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.8000000a.reverse)) on the mainnet ENS registry. It’ll return the zero address, since there is no resolver registered on that address specifically.
    2. Call resolver(namehash(8000000a.reverse)) on the mainnet ENS registry. It’ll return 0x00000beef055f7934784d6d81b6bc86665630dba, the address of the L2ReverseRegistrar on the network with chainid 10.
  8. Verify the return of the coinType method of the L2ReverseRegistrar matches the coinType as serialized in step 7.
  9. Call nameForAddr(bytes address) with the address as serialized in step 8. This will return the human-readable name alice.eth.
  10. Check forward resolution of the name as described in ENSIP-11 and repeated in the section above. - If it resolves to the same address, then proceed normally. - If forward resolution of the ENS name returns an address different from the original, or returns an empty byte array, the wallet MUST display the raw, human-readable ERC-7930 serialized address, indicating the address is unresolved. The wallet SHOULD also warn the user of the mismatch to prevent potential spoofing or confusion.
  11. Compute the checksum as described in ERC-7930: 0xC69BEB13.
  12. Format the address in the format <address>@<chain>#<checksum> by removing l2.eth from step 3 and display it to the user: alice.eth@optimism#C69BEB13

Security Considerations

  • Wallet developers should be aware of possible unicode glyph collisions in resolved names and warn users about them in order to keep checksums effective, since an attacker could, in order to impersonate alice.eth@chain.<<namespace>.eth#00112233:
    • Mine an address on chain.<namespace>.eth such that the checksum of the Interoperable Address is 00112233.
    • Register аlice.eth (using the russian vowel а instead of the latin a), and point it to the address above.
  • ENSIP-19 introduces trust assumptions when resolving reverse records offchain:
    • ZK-rollups may offer trust-minimized resolution via on-chain proofs.
    • Sidechains may rely on centralized CCIP-read gateways or signature authorities.

    Wallets MUST surface whether reverse resolution was trust-minimized or trusted.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Sam Kaufman (@SampkaML), Marco Stronati (@paracetamolo), Yuliya Alexiev (@yuliyaalexiev), Jeff Lau (@jefflau), Sam Wilson (@samwilsn), Vitalik Buterin (@vbuterin), Teddy (@0xteddybear), Joxes (@Joxess), Racu (@0xRacoon), Skeletor Spaceman (@0xskeletor-spaceman), TiTi (@0xtiti), Gori (@0xGorilla), Ardy (@0xArdy), Onizuka (@onizuka-wl), Lumi (@oxlumi), Moebius (@0xmoebius), Thomas Clowes (@clowestab), Prem Makeig (@nxt3d), Mono (@0xMonoAx), Orca (@0xrcinus), "ERC-7828: Interoperable Names [DRAFT]," Ethereum Improvement Proposals, no. 7828, November 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7828.