diff --git a/ERCS/erc-7828.md b/ERCS/erc-7828.md new file mode 100644 index 00000000000..511914f6028 --- /dev/null +++ b/ERCS/erc-7828.md @@ -0,0 +1,293 @@ +--- +eip: 7828 +title: Human readable names for Interoperable Addresses +description: An iteration of Interoperable Address' format that allows resolution to shorter, hierarchical strings using naming registries +author: 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) +discussions-to: https://ethereum-magicians.org/t/erc-7828-chain-specific-addresses-using-ens/21930 +status: Draft +type: Standards Track +category: ERC +created: 2024-11-27 +requires: 55, 137, 155, 7785 +--- + +## Abstract +This proposal builds off of [ERC-7930] (Interoperable Addresses & Names) to provide a standard and human-readable format for chain-specific addresses which provides: +- A unified format for accounts that specifies, together with the address, the chain where the address lives. +- The use of human-readable chain names and how they can be resolved to chain identifiers. +- The use of human-readable account names and how they can be resolved to addresses. +- A centralized index of chain and account resolution methods, way smaller in scope than ethereum-lists/chains + +## Motivation +The current Ethereum address landscape is leading to an ecosystem that will have hundreds and eventually thousands of L2s that use the same address format as Ethereum mainnet. This means an address by itself is not enough information to know which chain the address is related to. This can be problematic if funds are sent to an unreachable address on the incorrect chain. From the user account it should be possible to obtain the right chain identifier (chainID) to include in a transaction. + +The mapping from chain names to identifiers has, since [EIP-155](./eip-155.md), been maintained off chain using a centralized list. This solution has a few shortcomings: +- It does not scale with the growing number of L2s. +- The list maintainer is a trusted centralized entity. +- It does not (currently) support non-EVM chains, even when naming systems (such as ENS) do. + +Instead of using chain identifiers, which are not human readable, the address could be extended with a human-readable chain name, which can then be resolved to a chain identifier. +The mapping from chain names to identifiers can be resolved via a variety of methods which are coupled to the name's TLD. + +In the same spirit, the address could be a human-readable name as well, which is already a use case for ENS. By coupling the TLD to the resolving method used, this standard could leverage current and future features of ENS and other naming registries. + +Moreover, the above can be leveraged to allow for a name to represent the same entity corresponding to different addresses on different chains, mitigating the risk of sending funds to an address the intended recipient doesn't actually control. + +Desired properties: +- A unified format to represent any address on L1, L2 or beyond. +- The chain portion can be an ERC-7785 domain name when that standard is ready, or use solutions similar to ethereum-lists/chains in the immediate future. +- The address portion can be either the appropriate type of address for the chain, or a domain name. +- The address portion and the chain portion should be resolved separately. +- Checksum hash goes over the entire address & chain, so users can't just replace a component and expect it to stay valid. +- Addresses can be serialized to binary and then de-serialized back to text retaining the same human-readable name, even if serialization and de-serialization happen on different wallets. + +## 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. + +### Format +This standard defines a sub-syntax with extra semantics on top of the syntax defined in [ERC-7930]. + +``` +: :=
"<>" "#" +
: := | +: := | +: := [0-9A-F]{8} + +: := [.-:_%a-zA-Z0-9]* +: := [.-:_a-zA-Z0-9]* +: := . +: := [a-zA-Z][-a-zA-Z0-9]{1,9} +: := ( . ) ? + := [a-zA-Z][-a-zA-Z0-9]+ +``` + +Where: + +- `` : Corresponds to a full, resolvable name on the resolver defined by its `L0-TLD`. +- ``, `` and `` are defined to maintain backwards compatibility with [ERC-7930], and their semantics remain the same. +- ``: Corresponds to an entry in the centralized [^name resolver registry] + +Note the difference between ``, which is a fully qualified name, and `subdomain` that is just a segment of a name between dots. E.g. `user.app.eth` is a scoped name, `user` and `app` are subdomains. + +This allows for Interoperable Addresses' text representation to mix and match 'resolved' and 'unresolved' usages in both the chain and address parts. + +A few examples below: +``` +Mainnet +- 0x12345...6789<>eip155:1#FFFFFFFF +- 0x12345...6789<>eth.short#FFFFFFFF +- alice.eth<>eth.short#FFFFFFFF + +Testnet (Sepolia) +- 0x12345...6789<>eip155:11155111#00000000 +- alice.testeth<>sep.short#00000000 + +Rollup +- 0x12345...6789<>eip155:4270#AAAAAAAA +- 0x12345...6789<>arb-nova.short#AAAAAAAA +- alice.eth<>arb-nova.short#AAAAAAAA + +Assuming ERC-7785 starts listing chains at l2.eth +- alice.eth<>arb-nova.l2.eth#AAAAAAAA + +My ENS name is registered on rollup1 (via ENSIP-10 & ENSIP-16), but I want to receive funds on rollup2 +- alice.rollup1.eth<>rollup2.short#BBBBBBBB + +Non-evm chain +- bc1..23<>bip122:000000000019d6689c085ae165831e93#CCCCCCCC +- alice.eth<>bip122:000000000019d6689c085ae165831e93#CCCCCCCC + +Assuming the shortcode list adds a few other CAIP namespaces +- alice.eth<>btc.short#CCCCCCCC +``` + +> [!NOTE] +> This standard does not explicitly define a hierarchical name structure for anything other than the top level domain, however it allows the underlying naming scheme to be hierarchical as in the ENS-in-rollup example. + +### Checksum +Addresses must be serialized to the `ChainType, ChainReferenceLength, ChainReference, AddressLength, Address` format proposed in [ERC-7930] as Interoperable Addresses v1, and the 4-byte checksum MUST be displayed as part of the address as described in the syntax above. + +This ensures that the checksum changes if any part of the address or chain ID is modified, turning dangerous manual edits into detectable errors for wallet users. + +### The Name Resolver Registry +We propose for this ERC to strive to reach Final status instead of becoming a Living document, and maintain a separate dictionary for the different name resolving protocols or methods, similar to ethereum-lists/chains. + +The keys of this list will be ``s, and their associated values should be: +- 2-byte binary id, for storing intended registry in Interoperable Addresses v2 (defined below) +- Chain naming section + - The set of CASA namespaces on which the registry can provide names for chains. + - An unambiguously implementable specification of how to obtain a name for a chain id. + - An unambiguously implementable specification of how to obtain a chain id, given a network name. + - The sources of truth the algorithms above should use. +- Address naming section + - The set of CASA namespaces on which the registry can provide names for addresses + - An unambiguously implementable specification of how to obtain a name for an address. + - An unambiguously implementable specification of how to obtain a machine address, given a name. + - The sources of truth the algorithms above should use. + + +It is worth noting that: +- The same `` can map to different algorithms and/or data for chains and addresses. e.g. if ERC-7785 is published as an ENS product, using `.eth` on a chain name will use a different algorithm for resolution than if the same TLD were used on an address. +- A given protocol may have more than one TLD assigned to it, to avoid having to store the chainid & address of the name resolver on the Interoperable Address itself. An example of this would be to use different addresses for the testnet & mainnet ENS deployments. + +This is an easier list to maintain than ethereum-lists/chains, since it does not have to list every single chain, and the problem of knowing which contracts are trustworthy as naming registries is one wallets would have to tackle anyway. + +### Example entries for the `L0-TLD` list + +#### No resolution +Binary id: `0x0000` + +To be used in v2 Interoperable Addresses to indicate that no resolution is desired, and the 7930-style raw chain identifier used in the Interoperable Name instead. + +> [!NOTE] +> In the case where both `ChainResolver` and `AddressResolver` are set to this value, the resulting Interoperable Name would match an Interoperable Name from ERC-7930 + +#### `.short` +Binary id: `0x0001` + +##### Chain naming + +###### Supported CASA namespaces +Only those explicitly listed here + +###### Resolution algorithm +Simply refer to the table below + +| shortname | CAIP-2 namespace | CAIP-2 reference (text) | +| :-- | :--: | :--: | +| `eth` | `eip155` | `1` | +| `oeth` | `eip155` | `10` | +| `arb-nova` | `eip155` | `4270` | +| `btc` | `bip122` | `000000000019d6689c085ae165831e93` | +| `solana` | `solana` | `5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | + + + +##### Address naming +Not supported + +#### `.eth` +Binary id: `0x0002` + +###### Supported CASA namespaces +`eip155` and anything supported by SLIP-0044 for forward resolution (Interoperable Address -> human-readable name) + +`eip155` chains explicitly supported by ENS by deployment of `L2ReverseRegistrar` and registration on ENS registry for reverse resolution (human-readable name -> Interoperable Address) + +##### Chain naming +Not currently supported, TBD in ERC-7785 + +##### Address naming + +Resolution and reverse-resolution of chain names is to be executed as defined in ENSIP-19, ENSIP-16, ENSIP-11 and ENSIP-10. + +Some caveats for ENS support are: +- ENSIP-6 and ENSIP-17 are explicitly not supported, as they define names on different TLDs. +- While ENS could add support for other TLDs for forward resolution, this standard would require another entry on this list to support them. This does not apply to _reverse_, resolution, since those names are not ever displayed. +- For addresses on chains that are both supported by SLIP-0044 and the special scheme for the eip155 namespace defined in ENSIP-11, the latter should be used. + + +### Interoperable Address v2 definition +To allow for addresses to be serialized from human-readable names to an Interoperable Address, and then back to _the same_ human-readable name we define a new version of Interoperable Addresses which includes information on the desired naming registry. + +Note that this is OPTIONAL, and wallets MAY disregard the extra information and use the registries they prefer instead, and/or serialize to Interoperable Addresses version 1. +``` +┌─────────┬───────────┬──────────────────────┬────────────────┬───────────────┬─────────┬───────────────┬─────────────────┐ +│ Version │ ChainType │ ChainReferenceLength │ ChainReference │ AddressLength │ Address │ ChainResolver │ AddressResolver │ +└─────────┴───────────┴──────────────────────┴────────────────┴───────────────┴─────────┴───────────────┴─────────────────┘ +``` + +Where: + +- `Version` : A 2-byte version identifier. must be big-endian unsigned integer `2`. +- `ChainType`, `ChainReferenceLength`, `ChainReference`, `AddressLength`, `Address`: Same as in [ERC-7930] +- `ChainResolver`: 2-byte identifier of the method used to resolve the chain to a human-readable string, from the [^name resolver registry]. +- `AddressResolver`: 2-byte identifier of the method used to resolve the address to a human-readable string, from the [^name resolver registry]. + + +### 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 `oeth.short` +3. Look up the TLD (characters from the last dot up to the end of the string) of the result of step 2. For this example it's `.short`. +4. Look up the result from the step above on the [^name resolver registry] to know what to do with the entirety of the result from step 2. In this case, the hardcoded table says it corresponds to + - chain namespace: `eip155` + - chain reference: `10` (chainid of OP Mainnet) +5. Look up the TLD (characters from the last dot up to the end of the string) of the result of step 1. For this example it's `.eth`, meaning we should attempt resolution via ENS. +6. As per ENSIP-11, convert the eip155 chainid into an ENSIP-11-specific `coinType`: `0x80000000 & 0x0000000A == 0x8000000A` [^1] +7. Compute the namehash of the result of step 1, according to ENSIP-1. +8. Query the ENS registry for the appropiate 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 7 and 6, 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 cant be finished. +10. Begin serialization into an Interoperable Address v2 by appending the version: `[0002]` +11. Serialize `ChainType`, `ChainReferenceLength`, `ChainReference`, `AddressLength` and `Address` according to [ERC-7930]: `[ 0002 0000 01 0A 14 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ]` +12. Append the binary id for the `ChainResolver` and `AddressResolver` from the Name Resolver Registry: `[ 0002 0000 01 0A 14 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0000 0001]` +13. Interoperable Address is complete: `0x00020000010A14AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00000002` +14. Compute the checksum as described in [ERC-7930]: `0xC69BEB13` and display it to the user. + +[^1]: While this sees production usage, it is not consistent with the design principles behind [ERC-7930] and assumes 32-bit chainids, which are not compatible with an [ERC-7785] future. We recommend using something closer to what is described in footnote 2. + +### Reverse Resolution step-by-step example +Starting from the Interoperable Address serialized above: `0x00020000010A14AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00010002` + +1. Pick the first two bytes corresponding to the version: `0x0002`. 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 (OP Mainnet) + 4. `AddressLength`: `0x14` -> 20 bytes, consistent with `eip155` + 4. `Address`: `0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa` -> alice's address +3. Since we know the address to be v2, defined above, pick the next two bytes as the `ChainResolver`: `0x0001` -> shortname list. Remaining payload: `0002` +4. Pick the next two bytes as `AddressResolver`: `0x0002` -> ENS. No remaining payload, parsing finished. +5. Look up the output of step 3 in the [^name resolver registry]. It instructs to use the hard-coded shortcode list, with TLD `.short` +6. Serialize the chain type (2.1) and chain reference (2.3) to CAIP-2 following [ERC-7930]: `eip155:10` +7. Look up the type reference on the shortcode list, and obtain the full name to use: `oeth.short` +8. Look up the output of step 4 in the [^name resolver registry]. It instructs to use ENS. +9. Convert the output from steps 2.1 and 2.3 to a reverse lookup string of the form `
..reverse`: `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.0000010A.reverse` + - `` is the RFC-4648 base16 representation of the concatenated `ChainType`, `ChainReferenceLength` and `ChainReference` [^2] + - `
` is the RFC-4648 base16 representation of the `Address` [^2] +10. Compute the namehash of the result of the step above. +11. Perform ENSIP-10 resolution of the name above in the Ethereum Mainnet ENS registry to find the address of the `L2ReverseRegistrar`. + 1. Call `resolver(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.0000010A.reverse)` on the mainnet ENS registry. It'll return the zero address, since there is no resovler registered on that address specifically. + 2. Call `resolver(0000010A.reverse)` on the mainnet ENS registry. It'll return `0x00000beef055f7934784d6d81b6bc86665630dba`, the address of the `L2ReverseRegistrar` *on network `0000010A`* +12. Verify the return of the `coinType` method of the `L2ReverseRegistrar` matches the coinType as serialized in step 9. [^2] + +13. Call `nameForAddr(bytes address)` [^2] with the address as serialized in step 9. This will return the human-readable name `alice.eth`. +14. 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 it resolves to a different address, including an empty bytes array, display the address raw and optionally show a warning to the user. +15. Compute the checksum as described in [ERC-7930]: `0xC69BEB13`. +16. Format the address in the format `
<>#` and display it to the user: `alice.eth<>oeth.short#C69BEB13` + +[^2]: This is a clarification & recommendation on top of ENSIP-19, which is in Draft status and is somewhat ambiguous. + +## Rationale +- We chose to use a centralized list of name registries, aka a [^name resolver registry], since mapping of chain names to chain ids, aka on-chain configs (as proposed in [ERC-7785]) are not yet a solved problem. Therefore there is a need to maintain a list of possible implementations, including stopgap solutions such as relying on ethereum-lists/chains. + +## Open Discussions +- Further constrain the syntax of human-readable names to minimize: + - Collisions on names by e.g. UTS46 case folding + - Addresses that are valid ERC-7828 but cant be squeezed into ENS or comparable standards +- Conflicts with existing standards: + - ENSIP-11 defines custom serialization logic for a few address types and it'd be very convenient if it used the same CASA profile as [ERC-7930] + - ENSIP-11 defines the bitmask to use for `eip155` `coinType` assuming chainids are 31 bits or shorter, which is in conflict with ERC-7785 and the addresses representable in [ERC-7930]. + - ENSIP-19 does not extensively define address or name serialization for the reverse registrar node name + +## Backwards Compatibility +The naming scheme herein defined can represent all names supported by [ERC-7930] by displaying raw addresses without resolution + +## Security Considerations +- By coupling the domain's TLD to a known resolution method, we avoid the case where the same human-readable name is registered on different naming registries pointing to different addresses, which would only have the address' 4-byte checksum as a mitigation on users sending funds to unintended addresses. +- Maintaining a list of chain/name registries instead of a list of chains means it'd have to be updated less frequently, allowing for more extensive review of new entries. +- 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.short#00112233`: + - Mine an address on `chain.short` 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. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). + + +[^name resolver registry]: Defined in github's ethereum-lists/chains repository as a living document. + +[ERC-7930]: ./ERC-7930.md +[ERC-7785]: ./ERC-7785.md