Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7930: Interoperable Addresses

An extensible binary format to refer to an address specific to one chain.

Authors Teddy (@0xteddybear), Joxes (@0xJoxess), Nick Johnson (@Arachnid), Francisco Giordano (@frangio), Skeletor Spaceman (@skeletor-spaceman), Racu (@0xRacoon), TiTi (@0xtiti), Gori (@0xGorilla), Ardy (@0xArdy), Onizuka (@onizuka-wl), Sam Kaufman (@SampkaML), Marco Stronati (@paracetamolo), Yuliya Alexiev (@yuliyaalexiev), Jeff Lau (@jefflau), Sam Wilson (@samwilsn), Vitalik Buterin (@vbuterin)
Created 2025-02-02
Discussion Link https://ethereum-magicians.org/t/erc-7930-interoperable-addresses/23365

Abstract

Interoperable Addresses is a binary format to describe an address specific to one chain with a companion ‘Interoperable Names’ specification for human-readable display.

This is achieved through a versioned, length-prefixed binary envelope that supports arbitrary-length data. The interpretation and serialization rules for the data within this envelope are defined by companion standards, which provide profiles for each chain type.

Motivation

Current Ethereum addresses (ERC-55) lack chain specificity and have optional checksums, creating several challenges:

  • Optional checksum validation allows mistyped addresses to be accepted without user awareness.
  • Addresses do not include any indication of the chain to which the address applies. This means chain information must be expressed out of band, and introduces the risk of an address being mistakenly used on a chain it is not valid for. This risk is particularly pronounced for addresses that represent smart contracts.
  • The existing address format provides no mechanism for extension, meaning that there is no natural method to add these features to the existing address format.

Interoperable Addresses build on insights from , CAIP-10 and CAIP-50, offering a unified format which combines:

  • Binding chain specificity (via explicit chain identifiers) to the raw address.
  • Compact & canonical binary format for use on cross-chain message passing and intent declaration.
  • Checksums for name collision mitigation & user error prevention.

Furthermore, this proposal adds a few features to make addresses interoperable with infrastructure at the edges of and beyond the ethereum ecosystem, by supporting the representation of addresses of non-evm chains as well, for the benefit of cross-chain liquidity movements and cross-chain message passing.

Guarantees this standard aims to provide

  • Any future Interoperable Address will be trivially convertible to Interoperable Address v1 (specified below), which, together with the point below, makes them a canonical representation for users who need to treat them opaquely.
  • Two Interoperable Addresses, converted to this canonical version, will be bitwise-equal if and only if they represent the same target address.
  • Checksums are short enough to be compared by humans, and allow for easy differentiation of target addresses independently of any extra data the Interoperable Address may contain.

Comparisons with other standards

CAIP-10

CAIP-10 proposes a standard text format to represent what in this document is defined as target addresses. Since it’s a text-only standard, it does not concern itself with the serialization/deserialization of the various chains’ address formats, simply using the text representation of addresses already defined by the respective chains. This means it is trivial to add support for chains to CAIP-10, while doing so with this standard involves defining a serialization scheme.

The above has the drawback of not being able to guarantee canonicity. That is, there could be multiple valid CAIP-10 addresses pointing to the same target address.

Also, the text format is of little use for smart contracts involved with cross-chain liquidity transfers and message passing due to its reduced data efficiency and lack of canonicity.

Interoperable Names are convertible to CAIP-10 without even going through the binary representation, so backwards-compatibility with actors expecting CAIP-10 identifiers should not be an issue.

The interop roadmap is better served by having a standardized binary format for addresses first, which allows the message passing and intents verticals to move forward on a common interface, with a good-enough text representation which is familiar to users and useful for developers, and as a next step develop a chain & address name resolving standard on top of it, leveraging its uniformity and extensibility.

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.

Concepts

Interoperable Address
A binary payload which unambiguously identifies a target address and allows conversion to a human-readable name.
Interoperable Name
A string representation of an interoperable address, meant to be used by humans.
Target address
The (address, chain ID) pair a particular Interoperable Address points to.

Interoperable Address V1 binary format definition

In binary format, addresses MUST have the following encoding:

┌─────────┬───────────┬──────────────────────┬────────────────┬───────────────┬─────────┐
│ Version │ ChainType │ ChainReferenceLength │ ChainReference │ AddressLength │ Address │
└─────────┴───────────┴──────────────────────┴────────────────┴───────────────┴─────────┘

Where:

Version
A 2-byte version identifier. For version 1, this must be 0x0001 (big-endian). Future versions SHOULD be standardized in separate ERCs.
ChainType
A 2-byte value as defined in CAIP-350, corresponding to a CAIP-2 namespace, which allows users to know how to interpret & display the other two fields.
ChainReferenceLength
A 1-byte integer encoding the length of ChainReference in bytes. Note that it MAY be zero, in which the Interoperable Address will not include a chain reference.
ChainReference
Variable length, binary representation of CAIP-2 chain namespace & reference serialized as explained in the CAIP-350 profile for the chain type, encoding the chain ID.
AddressLength
1-byte integer encoding the length of Address in bytes. Note that it MAY be zero, in which the Interoperable Address will not include an address. It MUST NOT be zero if ChainReferenceLength is also zero.
Address
Variable length field containing the binary format of the address component. For serialization details of different types of addresses see the CAIP-350 profile for the chain type.

Version Compatibility

These rules ensure that future versions of Interoperable Addresses maintain backwards compatibility and consistent behavior across implementations:

  • Future versions incompatible with v1 parsing MUST set the most significant bit of the version field to 1
  • All versions MUST support both address and chain specification simultaneously
  • All versions MUST serialize to v1 format for checksum calculation, excluding the version field from the hash input
  • Interoperable Address versions MAY only be able to represent a subset of the CAIP namespaces.
  • Interoperable Address versions MAY assign extra syntactic restrictions on the associated Interoperable Name, coupled to novel semantic meaning (e.g. use of ENS or other naming registries)
  • Interoperable Address versions MAY define extra fields for purposes such as storing information on how to display the addresses.

Interoperable Name format definition

Syntax

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

Where:

Chain
String representation of CAIP-2 blockchain identifier, recovered from the binary representation described in the CAIP-350 profile for the chain type. In the case where ChainReferenceLength is zero, it should be the CAIP namespace alone, and no trailing colon. Note that it’s not possible to specify a reference without a namespace.
Address
Chain namespace specific text representation of the address from the binary representation. Mapping between the two described in the CAIP-350 profile for the chain type. In the case where AddressLength is zero, it should be the empty string.
Checksum
4-byte checksum calculated by computing the keccak256 hash of the concatenated ChainType, ChainReferenceLength, ChainReference, AddressLength and Address fields of the binary representation (that is, the v1 binary representation skipping the Version field), and truncating all but the first 4 bytes of the output. Represented as a base16 string as defined in RFC 4648.

Rationale

  • Chain and address fields’ syntax is deliberately chosen to be able to express CAIP-2 namespaces (by using the @ symbol for the separator, freeing up :) and CAIP-10 account IDs, with the caveat that no length restriction is placed, so chains with longer address formats or full 256-bit EVM chainids can be represented.
  • Similarly, the address field includes % as a valid character to allow for url-encoding of any other characters.
  • While a fresh start on text-encoding schemes could e.g. make use of more characters with base58 or base64 to achieve greater information efficiency and/or abstract which chain the address exists on as an implementation detail, a more familiar approach was chosen since:
    • It makes the Interoperable Address <-> raw address relationship evident to the user, which will make the cases where the former are not (yet) supported by a dapp or hardware wallet easier to reason with, as users will evidently see the address is the same, but it’s the chain&checksum that is being trimmed.
    • Its extra human-readability will make it more useful as a a stopgap solution until a standard focused on chain and address names is finalized.
  • We chose to support zero-length addresses and chainids to be able to use just one standard to represent both potentially foreign target addresses (e.g. the recipient of a cross-chain message) and also plain addresses or chainids (e.g. to specify the origin-chain hook address of a cross-chain message), for greater uniformity across implementations.

Test Cases

Example 1: Ethereum mainnet address

Chain: Ethereum Mainnet Address: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Interoperable Name: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@eip155:1#4CA88C9C

Interoperable Address:

0x00010000010114D8DA6BF26964AF9D7EED9E03E53415D37AA96045
  ^^^^-------------------------------------------------- Version:              decimal 1
      ^^^^---------------------------------------------- ChainType:            2 bytes of CAIP namespace
          ^^-------------------------------------------- ChainReferenceLength: decimal 1
            ^^------------------------------------------ ChainReference:       1 byte to store uint8(1)
              ^^---------------------------------------- AddressLength:        decimal 20
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Address:              20 bytes of ethereum address

keccak256 input for checksum: 0x0000010114D8DA6BF26964AF9D7EED9E03E53415D37AA96045 note the version field is removed before hashing

Example 2: Solana mainnet address

Chain: Solana Mainnet

Address: MJKqp326RZCHnAAbew9MDdui3iCKWco7fsK9sVuZTX2

Interoperable Name: MJKqp326RZCHnAAbew9MDdui3iCKWco7fsK9sVuZTX2@solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d#88835C11

Interoperable Address:

0x000100022045296998a6f8e2a784db5d9f95e18fc23f70441a1039446801089879b08c7ef02005333498d5aea4ae009585c43f7b8c30df8e70187d4a713d134f977fc8dfe0b5
  ^^^^---------------------------------------------------------------------------------------------------------------------------------------- Version:              decimal 1
      ^^^^------------------------------------------------------------------------------------------------------------------------------------ ChainType:            2 bytes of CAIP namespace
          ^^---------------------------------------------------------------------------------------------------------------------------------- ChainReferenceLength: decimal 32
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------------------------------------ ChainReference:       32 bytes of solana genesis block
                                                                            ^^---------------------------------------------------------------- AddressLength:        decimal 32
                                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- Address:              32 bytes of solana address

keccak256 input for checksum: 0x00022045296998a6f8e2a784db5d9f95e18fc23f70441a1039446801089879b08c7ef02005333498d5aea4ae009585c43f7b8c30df8e70187d4a713d134f977fc8dfe0b5. Note the version field is removed before hashing.

Example 3: EVM address without chainid

Chain: eip155 namespace, chainid not specified. Address: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 Interoperable Name: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@eip155#B26DB7CB

Interoperable Address:

0x000100000014D8DA6BF26964AF9D7EED9E03E53415D37AA96045
  ^^^^------------------------------------------------ Version:              decimal 1
      ^^^^-------------------------------------------- ChainType:            2 bytes of CAIP namespace
          ^^------------------------------------------ ChainReferenceLength: zero, indicating no chainid
            ^^---------------------------------------- AddressLength:        decimal 20
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Address:              20 bytes of ethereum address

keccak256 input for checksum: 0x00000014D8DA6BF26964AF9D7EED9E03E53415D37AA96045 Note the version field is removed before hashing.

Example 4: Solana mainnet network, no address

Chain: Solana Mainnet.

Address: Not specified.

Interoperable Name: @solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d#2EB18670

Interoperable Address:

0x000100022045296998a6f8e2a784db5d9f95e18fc23f70441a1039446801089879b08c7ef000
  ^^^^------------------------------------------------------------------------ Version:              decimal 1
      ^^^^-------------------------------------------------------------------- ChainType:            2 bytes of CAIP namespace
          ^^------------------------------------------------------------------ ChainReferenceLength: decimal 32
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- ChainReference:       32 bytes of solana genesis block
                                                                            ^^ AddressLength:        zero, indicating no address

keccak256 input for checksum: 0x00022045296998a6f8e2a784db5d9f95e18fc23f70441a1039446801089879b08c7ef000. Note the version field is removed before hashing.

Security Considerations

While this standard aims to be a foundation to be able to canonically refer to addresses on different chains, that guarantee is going to be a leaky abstraction in the real world, given that e.g. a particular chain namespace might define a serialization scheme that can’t guarantee canonicity of addresses, or a given network might have two valid CAIP-2 ids referring to it.

It is therefore advised for implementers requiring canonicity of addresses (e.g by using them as keys in smart contract mappings or other key-value stores), to thoroughly review the CAIP-350 profile of a chain namespace for the possibility of a lack of canonicity of addresses (which should be noted in the profile’s ‘Extra Considerations’ section) as well as collisions with other already-supported namespaces.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Teddy (@0xteddybear), Joxes (@0xJoxess), Nick Johnson (@Arachnid), Francisco Giordano (@frangio), Skeletor Spaceman (@skeletor-spaceman), Racu (@0xRacoon), TiTi (@0xtiti), Gori (@0xGorilla), Ardy (@0xArdy), Onizuka (@onizuka-wl), Sam Kaufman (@SampkaML), Marco Stronati (@paracetamolo), Yuliya Alexiev (@yuliyaalexiev), Jeff Lau (@jefflau), Sam Wilson (@samwilsn), Vitalik Buterin (@vbuterin), "ERC-7930: Interoperable Addresses [DRAFT]," Ethereum Improvement Proposals, no. 7930, February 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7930.