Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evm reverse resolution #157

Merged
merged 42 commits into from
Jul 17, 2024
Merged
Changes from 34 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
2739178
First draft of evm-chain reverse resolution
jefflau Mar 14, 2023
6a043e0
Expand upon the spec
jefflau Jul 28, 2023
7abd935
Add a point about keeping a default resolver
jefflau Aug 9, 2023
53b4a1c
Add line about DAO/multisig owning the subnames controlling ccip-read
jefflau Aug 9, 2023
0a6fb2d
Add extension to ENSIP-12 for avatar resolution
jefflau Aug 18, 2023
bd38f8b
Add in reasoning for deprecating use of mainnet reverse record on evm…
jefflau Aug 24, 2023
45d2cbd
Merge branch 'master' of github.com:ensdomains/docs into ensip-16
jefflau Aug 24, 2023
d3a0c48
Change ensip number to 17
jefflau Aug 24, 2023
5341063
Add a default setup process
jefflau Nov 21, 2023
f71d920
Fix typo
makoto Feb 6, 2024
1b13e44
Updates from feedback
jefflau Mar 20, 2024
00d9d74
Add link to avatar resolution ensip in evm example
jefflau Mar 20, 2024
2f35f9b
Add link to avatar resolution ensip in evm example
jefflau Mar 20, 2024
f184b0b
Update to use evm chain id vs cointype
jefflau Mar 20, 2024
ec8da79
Add examples of L2 reverse resolution
jefflau Mar 22, 2024
57b220c
Resolve conflict
jefflau Mar 22, 2024
95d8bc9
resolve conflict
jefflau Mar 22, 2024
41b35c1
Update ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
jefflau Mar 28, 2024
acbe22e
Update ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
jefflau Mar 28, 2024
89c4259
Update ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
jefflau Mar 28, 2024
b478b82
additions from feedback
jefflau May 2, 2024
95343d4
tMerge branch 'evm-reverse-resolution' of github.com:ensdomains/docs …
jefflau May 2, 2024
c0ad9cb
Create more detail for the new L2 reverse resolution process
jefflau May 2, 2024
d51d156
Update ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
jefflau May 6, 2024
4609d17
Adjust vocabulary to be EVM rather than L2
jefflau May 6, 2024
8fa5b3c
Merge branch 'evm-reverse-resolution' of github.com:ensdomains/docs i…
jefflau May 6, 2024
7253c72
Update ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
jefflau May 31, 2024
1026228
Add glossary of terms, fix resolution process with mainnet resolution
jefflau Jun 3, 2024
75ffb3d
Change forward resolution to use ENSIP-10
jefflau Jun 3, 2024
93694c1
Change resolve to a function
jefflau Jun 3, 2024
0facf11
Add legacy addr() into resolution process
jefflau Jun 3, 2024
c1fedb3
Change decimal cointypes to hex
jefflau Jun 3, 2024
43234f1
Change address representation to lowercase
jefflau Jun 3, 2024
9b0589c
Remove note
jefflau Jun 3, 2024
b63cce9
Update ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
jefflau Jun 19, 2024
e435268
Update resolution process
jefflau Jun 19, 2024
4c9c2f7
Remove default section
jefflau Jun 19, 2024
de73a71
Adjust the avatar resolution process to be less duplicative
jefflau Jun 19, 2024
1c8d5f2
Adjust avatar resolution process
jefflau Jun 24, 2024
928164f
Introduce ENSIP-19
lucemans Jun 26, 2024
71c2fd7
Merge branch 'ensip/reverse-multichain' into evm-reverse-resolution
lucemans Jun 26, 2024
5c45407
Update Index to include ENSIP-19
lucemans Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions ens-improvement-proposals/ensip-17-evmchain-reverse-resolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
description: >-
Specifies reverse resolution in a cross-chain context
---

# ENSIP-XX: EVM-chain Reverse Resolution

| **Author** | Jeff Lau \<[email protected]> |
| ------------- | ---------------------------- |
| **Status** | Draft |
| **Submitted** | 2023-03-14 |

## Abstract

This ENSIP specifies a way for reverse resolution to be used on other EVM chains. This allows setting primary names on L2s, as well as resolving any other records set on this specific reverse record, such as the avatar.

## Motivation

Reverse resolution has been in use since ENS's inception, however at the time Ethereum had no concrete scaling plans. In the past 5 years, we've seen layer 2s and sidechains become more prevalent and we first allowed support for these with ENSIP-9 (formerly EIP-2304) to allow addresses from other chains to be stored on ENS. To complete support for other EVM chains, reverse resolution needs to be expanded to allow reverse resolution to also exist.

## Specification

### Overview

* Reverse registrars will be setup on each EVM-chain, with a corresponding registry
* Reverse registrar will only allow setting the name and text record without resolver customisability. This is to allow a consistent storage slot that can be checked on L1.
* User can now claim their reverse on this chain and set it to their ENS name
* Their ENS name will need to set their record for the same EVM-cointype as the network, which is specified in [ENSIP-11](https://docs.ens.domains/ensip/11).
* A dapp can then detect the chainID that a user is on, convert that into coinType in hexadecimal and resolve their primary ens name by resolving the name record at [userAddress].[coinTypeAsHex].reverse. This will be resolved via a CCIP-read gateway and look up the reverse record on the corresponding EVM-chain. Depending on if the chain is an L2 that has state roots on L1 or sidechain, verification can be done with trusted signatures or trustlessly on Ethereum mainnet.
* Dapps will then resolve this name via ENS on L1 to check if the forward resolution matches. This forward resolution can be on L1, or the user can set up a CCIP-read resolver and records for each network and put those addresses wherever they want (such as on another L2)
* Once matched, the dapp can then also resolve any text records on the primary ENS name, such as avatar.
* Discovery of the reverse registrar on each chain will be done by looking up the `addr()` of [coinTypeAsHex].reverse.
* coinType in all instances will be the hex representation to reduce the length of the name

### Deployment and discovery of EVM Reverse registrars

When a new EVM reverse registrar is deployed, it will need to be setup by the owner of the `reverse` node, to setup a subdomain [coinTypeAsHex].reverse. It must then be setup with an Offchain resolver that has an onchain L1 address record that return the contract address of the reverse registrar for that chain. The Offchain resolver will also support wildcard of all the address subdomains with the format [address].[coinTypeAsHex].reverse. Additionally there must be a new EVM gateway setup to handle the CCIP-read revert errors that will go to the corresponding network to gather the chain-specific reverse record and verify this data on L1.

### Resolving Primary ENS Names by a dapp

Below is a step-by-step resolution process of ENS reverse resolution. A dapp must adhere to these rules to be compliant with the reverse resolution process. This reverse resolution process adds on to ENSIP-3's original reverse resolution process and will act as a replacement for applications that support Primary ENS names on multiple chains.

#### Glossary of terms

* `[address]` is the lowercase hexadecimal representation of an Ethereum address with prefix `0x` removed.

* `coinType` for chain ids is derived using [ENSIP-11](https://docs.ens.domains/ensip/11) by ORing the chainId with `0x80000000`

* `coinTypeAsHex` is the cointype converted to hexadecimal.

* Registry refers to the ENS registry on Ethereum L1

* Resolver refers to the resolver of the Reverse node whether on L1 or another chain

* Primary Name is the common name use for the reverse node's record `name`

#### Resolution process

1) If a dapp has a connected user it SHOULD first check the chainId of the user.
jefflau marked this conversation as resolved.
Show resolved Hide resolved
2) It will then construct the cointype using ENSIP-11: `coinType = 0x80000000 | chainId`, which must be converted to lower-case hexadecimal representation.
3) If the chainId is 1, it should call `[address].addr.reverse`, then skip to step 5.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean to "call" an ENS name?

4) If the chainId is not 1, it should then construct the ENS node representing the reverse node on that network using the coinType and the user's connected `address`: `node = namehash([address].[coinTypeAsHex].reverse)`
5) Call the registry with the namehash to retrieve the resolver `resolver = registry.resolver(node)`
6) Call name on the resolver `name = resolver.name(node)`
7) If a string is found, skip to step 13
8) If `name` is an empty string, it will check the default primary name for all EVM chains by constructing its node as follows: `node = namehash([address].default.reverse)`.
9) Call the registry with the namehash to retrieve the resolver `resolver = registry.resolver(node)`
10) Call name on the resolver `name = resolver.name(node)`
11) If a string is found, skip to step 13
12) If `name` is an empty string, the dapp assumes that a primary name does not exist and instead show the address instead. The name resolution process ends here.
13) If the dapp finds an ENS name, it first checks the forward resolution. This can be done by using the resolution processs in [ENSIP-10](https://docs.ens.domains/ensip/10)
14) In constructing the ENSIP-10 `resolve()` calldata it will construct the addr function with the appropriate coinType. If the chainId was 1, it uses chainId 60 (mainnet) without converting or using the legacy `addr(bytes32 node)` function without an additional cointype argument. If a name was found on step 7, it must use the `coinType` from the chainId of the user. If a name was found at step 10, which is the default Primary name for EoAs, it must check the coinType of chainId 0, which represents [an EoA across all EVM chains](https://namespaces.chainagnostic.org/eip155/caip10). `resolvedAddress = resolver.addr(coinType)`
15) If `resolvedAddress == address`, the dapp considers the Primary Name verified, and can now show this instead of the address within the application.
16) If `resolvedAddress != address` the dapp considers the Primary Name unverified and shows the address instead.
jefflau marked this conversation as resolved.
Show resolved Hide resolved

Note: The dapp MUST NOT use the reverse record set for Ethereum mainnet ([address].addr.reverse) even if the Primary ENS name has not been set on the target chain, and must treat this identically to an address with no primary name set.

### Resolving an avatar by a dapp on another EVM chain

ENSIP-12 was concieved before the ENS L2 reverse resolution specification and therefore should be updated to reflect the current state of ENS primary name resolution. This means that all avatar records are able to be updated on a per-chain basis by updating the avatar record on their reverse node.
jefflau marked this conversation as resolved.
Show resolved Hide resolved

#### Example of resolving an avatar on an L2 or EVM chain
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is titled "example" but seems to describe a mandatory process for resolving avatars. It also duplicates much of the functionality of the above section. Can we reformulate it to be clearer as a standard, and less duplicative?


To determine the avatar URI for a specific EVM chain address, the client MUST reverse-resolve the address by querying the ENS registry on Ethereum for the resolver of `<address>.<coinTypeAsHex>.reverse`, where `<address>` is the lowercase hex-encoded Ethereum address, without leading '0x'. Then, the client SHOULD call `.text(namehash('<address>.<coinType>.reverse'), 'avatar')` to retrieve the avatar URI for the address.

If a resolver is returned for the reverse record, but calling `text` causes a revert or returns an empty string, the client CAN call `.name(namehash('<address>.<coinType>.reverse'))`. If this method returns a valid ENS name, the client MUST:

1. Validate that the reverse record is valid, by resolving the returned name and calling `addr` on the resolver, checking it matches the original evmChainId (converted to cointype) address.
2. Perform [ENSIP-12 Avatar text record resolution](https://docs.ens.domains/ensip/12) on the primary name.

A failure at any step of this process MUST be treated by the client identically as a failure to find a valid avatar URI.

### Examples of valid L2 reverse resolution

* Arbitrum: 0f32b753afc8abad9ca6fe589f707755f4df2353.8000A4B1.reverse
* Optimism:
0f32b753afc8abad9ca6fe589f707755f4df2353.8000000A.reverse
* Base: 0f32b753afc8abad9ca6fe589f707755f4df2353.80002105.reverse
* Polygon ZKEVM: 0f32b753afc8abad9ca6fe589f707755f4df2353.8000044D.reverse
* ZKSync Era: 0f32b753afc8abad9ca6fe589f707755f4df2353.80000144.reverse

### Deprecating use of mainnet primary ENS name on other chains

ENS has not been explicit about how to use the mainnet `addr()` record and it is often used as a backup to a user not having an address record set. The mainnet reverse record has also historically been used on other EVM chains due to no alternative on that specific chain. There are a few reasons why it would undesirable to encourage use of mainnet primary name and/or `addr(node, 60)` record as a backup for it not being set on another EVM chain.

An example of why this could be confusing:

Dapp is on Arbitrum and uses mainnet primary ENS name. It resolves the ENS name's mainnet address and uses that to verify the reverse record is correct. It also uses the mainnet address to allow in-app transfers.

Mainnet primary ENS name that has an `addr(node, 60)` that is a smart contract wallet. The smart contract wallet is only on Ethereum and the user is unable to use `CREATE2` to deploy the same smart contract wallet on arbitrum. User 2 sees this Primary ENS name and wants to send funds to User 1. User 2 resolves the `addr()` of the ENS name and sends the funds to an address that doesn't exist on arbitrum and User 1 has no way to access the counterfactual address on that chain.

If we mandated that the address cannot use `addr(node, 60)`, but only the address of the chain in question, it would be possible to use mainnet as a backup. However the fact remains that you would still need to claim and set your Primary ENS name on mainnet, and the possibility for confusion seem to outweigh the benefits of using mainnet (high gas) as a catch-all back up for other L2 EVM chains (low gas). Additionally this would only be useful for EVM-compatible chains and would not benefit non-EVM L2s that have a different address format.

## Being explicit about default Primary ENS Name

To make things explicit we will require the signing of a message to confirm that the address in question would like to use mainnet or another network as fallback. This would either resolve directly on mainnet. Defaults would only be applicable to EoAs that can sign a message. This is because smart contract accounts would not be able to reliably set a default on all chains.

### Setting default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite vague. Is it worth including at all?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean removing everything related to defaults?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; it seems incomplete.


1) Sign a message to set a default record
2) call `setName()` on the default registrar on L1

### Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
Loading