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

Add ERC: Onchain registration of chain identifiers #669

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
107 changes: 107 additions & 0 deletions ERCS/erc-7785.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
eip: 7785
title: Onchain registration of chain identifiers
description: Derive chain identifiers by hashing their chain name and use ENS to map chain names to these identifiers
author: Marco Stronati (@paracetamolo), Jeff Lau (@jefflau)
discussions-to: https://ethereum-magicians.org/t/on-chain-registration-of-chain-identifiers/21299
status: Draft
type: Standards Track
category: ERC
created: 2024-09-26
---

## Abstract

This ERC proposes to derive chain identifiers as a digest of their chain name (and other information) and to use ENS to map chain names to identifiers in place of the centralized list on GitHub.
A solution to support existing chain identifiers that were not derived following this ERC is also proposed.

## Motivation

The mapping between chain names and identifiers, such as `Mainnet -> 0x1`, is currently maintained in a centralized list on GitHub (see ```ethereum-lists/chains``` repo).
However this solution has two main shortcomings:
- It does not scale with the growing number of L2s.
- The list maintainers are a single point of failure.

Desired properties:
- the ability to register new chain names and identifiers in a censorship-resistant way
- the ability to resolve chain names and identifiers in a trustless way
- maintain a unique mapping between names and identifiers

### Chain Identifier Spoofing and Replay Attacks

An important property of the centralized list is that it keeps a one-to-one correspondence between names and indentifiers.

Without this property, an attacker could register a fresh name pointing to an existing identifier. For example `my-testnet` could point to mainnet `0x1`. A user could be tricked into signing a transaction for the innocent looking `my-testnet` while actually signing a transaction for mainnet, a transaction that we attacker can then replay.

## 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.

### Extending chain identifiers

Current chain identifiers are usually chosen arbitrarily to be short. While these identifiers are convenient on a small scale, as their number increases it is more desirable to draw them from a larger space.

We propose to extend the size of identifiers to 32 bytes and to derive them using a cryptographic hash function.

Choose a reason for hiding this comment

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

Are there any chain_ids registered in eth-lists/chains of this size already? if all keccak chain_id's generated this way have the same length, should eth-lists/chains STOP allowing registrations of that length to prevent [malicious] collisions?

Choose a reason for hiding this comment

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

i like the idea of L2s and L3s using this mechanism and reducing traffic/burden on eth-lists/chains, but eth-lists/chains will still be needed for lots of non-L2 use-cases, so I think the smooth continued operation of eth-lists/chains should be in-scope for this ERC!

Copy link
Author

Choose a reason for hiding this comment

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

@sampkaML - what are your thoughts on this?

Choose a reason for hiding this comment

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

I agree with preventing eth-lists/chains from allowing registrations of this length due to your stated reason of avoiding [malicious] collisions.

However, regarding the continued use of existing eth-lists/chains and their inclusion within the scope of this ERC, I'm not sure I agree. What would be the downside of allowing the current ones to continue but stopping new registrations unless they follow this new format?

Copy link

@bumblefudge bumblefudge Oct 29, 2024

Choose a reason for hiding this comment

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

Simple: not every Eth transaction that needs replay protection is settling on an L2 anchored to mainnet (or to any other EVM chain), and those chains can't use this new registry. Private networks, permissioned networks, EVM-mode L2s of other L1s, all need chainIds (and can't be accessed via a contract that they anchor to on mainnet).

Choose a reason for hiding this comment

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

While I understand the concerns about private networks and other unique use cases, these issues aren't addressed by the current ENS implementation either. Our goal with this ERC isn't to solve every possible problem but to apply the 80/20 rule—improving the system for the vast majority of users. By focusing on the common scenarios where this solution will have the most impact, we can make meaningful progress now and address the remaining specialized cases with tailored solutions in the future.

Copy link
Author

Choose a reason for hiding this comment

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

@bumblefudge, which chains specifically will be adversely impacted by this change now?

Copy link

Choose a reason for hiding this comment

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

Hi, I would suggest to think about this EIP as a solution for any EVM, even outside the L1+L2s ecosystem. Some reasons:

  • chain teams already submit their info (name, chainID, etc.) to ethereum-lists/chains because that’s the ultimate source of truth for the list of all EVMs, so asking them to submit a transaction in order to do the same thing they would do already seems like a reasonable compromise
  • From our research (I work at routescan.io) there are currently roughly 1200 chains live at the moment, of which roughly 85% is EVM, and even though the pace of growth has increased, we don’t forecast millions of chains within the foreseeable future, so increasing the size of the identifiers to 32 bytes may not be needed.

The input to the function MUST contain the chain name and MAY contain additional information.

An example for a L2:
```
chain_id = Keccak-256(CHAIN_NAME, SETTLEMENT_CHAIN_ID, VERSION, DEPLOYER_CONTRACT_ADDRESS, SALT)
Copy link

@iJaack iJaack Nov 12, 2024

Choose a reason for hiding this comment

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

I would suggest allowing null or 0 input for the SETTLEMENT_CHAIN_ID and DEPLOYER_CONTRACT_ADDRESS, so as to allow non-L2 use cases as well.

Also, I believe another input should be the chainID of the DA its posting data to, since it’s becoming very frequent to see chains not posting data to blobs on L1 but to DAs on other EVMs or even on other VMs (see NEAR or Avail).

This new onchain registry could help a lot block explorer providers like us because it tells us immediately how to index the chain, and if there’s some extra indexing to add to scan the chain properly.

Another useful field could be the ‘stack’ the chain is using: OP Stack, ZK Stack, etc. Again, it helps with identification and categorization. These may be a lot of fields, but as we saw in some cases, chains change their nature: changing stack, posting to a different DA layer, etc. If the chain changes his nature, it needs to change chainID.

We found out that a lot of our customers often re-deploy their testnet chains multiple times under the same chainID, and they have no clue that this is actually a bad idea: a lot of tools use the chainID as the unique identifier for a chain, so if a chain has changed significantly (not referring to an upgrade, but a significant shift like, for example Lisk or Celo moving from L1 to L2), this can lead to tools having to reset their data about that specific chain, when they could simply add a new database / bucket / collection for the new chain, if the chainID were changed.

Some of these fields need to be in the input, so that changing those will change the chainID directly, but some can just be linked to attestations that provide useful information for all infra providers.

Choose a reason for hiding this comment

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

Thank you for your insightful suggestions. I agree that allowing null or zero inputs for SETTLEMENT_CHAIN_ID and DEPLOYER_CONTRACT_ADDRESS would accommodate non-L2 use cases and enhance the versatility of the registry.

However, my main concern is that I prefer not to dictate which inputs are required or optional within this ERC itself. I believe our primary goal should be to offer a flexible framework that includes all these options, allowing future ERCs—such as those focusing on interoperability—to specify the requirements for these variables, including which can be null or zero. This approach ensures that the ERC remains adaptable to a variety of use cases and can evolve with the ecosystem's needs.

Copy link

Choose a reason for hiding this comment

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

I understand, and I believe this needs to become an ERC as quick as possible so that the conversation with the wide community can start. Let's make it as flexible as possible so that future work can address extensions for interoperability.

@sampkaML So you think other info, like DA layer, tech stack and others could be part of a new attestation-based spec / ERC?

Copy link

Choose a reason for hiding this comment

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

What is DEPLOYER_CONTRACT_ADDRESS? It's not defined below

Copy link

Choose a reason for hiding this comment

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

I believe this is equal to the genesis contract address, it's for L2s/L3s. If it's not intended like this, then further specifications are needed.

Copy link

Choose a reason for hiding this comment

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

Is VERSION arbitrarily specified by the rollup, i.e. it refers to the rollup's version, or does it refer to the version of this ERC to support updates to the scheme defined here?

```
where:
- `L1_CHAIN_ID` is the id of the L1 where the L2 settles, it could be Mainnet or a testnet.
yuliyaalexiev marked this conversation as resolved.
Show resolved Hide resolved
- `VERSION` is to separate the domain of the hash function with an arbitrary string
- `BRIDGE` is the address of the L2 on the L1

### Chain name resolution

Any ENS name can resolve to a chain identifier as specified in ENSIP-11. The name should resolve to a record containing not only the chain identifier, but also all the optional information necessary to verify the identifier.
Copy link

Choose a reason for hiding this comment

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

How does resolution work? I have not used ENS for resolving anything other than addresses. Do we need to specify custom resolvers, or certain records to store data in?


For example the chain name `rollup` can be converted to a chain identifier on Mainnet by resolving:
```
rollup.eth -> {version : uint, bridge : address, chain_id : chain_id}
Copy link

Choose a reason for hiding this comment

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

How are testnets handed, are they also registed as e.g. rollup-sepolia.eth on mainnet, or are they be registered in the Sepolia or Holesky ENS deployments?

```
and then verified using:
```
chain_id == hash("rollup", 0x1, version, bridge)
```

## Rationale

<!--

Check warning on line 71 in ERCS/erc-7785.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

HTML comments are only allowed while `status` is one of: `Draft`, `Withdrawn`

warning[markdown-html-comments]: HTML comments are only allowed while `status` is one of: `Draft`, `Withdrawn` --> ERCS/erc-7785.md | 71 | <!-- | = help: see https://ethereum.github.io/eipw/markdown-html-comments/
The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages.

The current placeholder is acceptable for a draft.

TODO: Remove this comment before submitting
-->

TBD
Copy link

Choose a reason for hiding this comment

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

When will the rationale section be filled in? I have some questions around the rationale (see other comments) for certain decisions that I suspect would be covered here


## Backwards Compatibility

Existing identifiers, that were not derived using the scheme above, can be supported using a reverse mapping from chain identifiers to chain names, so that one can check for uniqueness.

For example the chain name `legacy-rollup.eth` can be resolved to the chain identifier `0x123`.
Then `0x123` can be resolved in the `chainid.reverse` domain to a `chain_name`.
If `chain_name == legacy-rollup` then the mapping is valid.
yuliyaalexiev marked this conversation as resolved.
Show resolved Hide resolved

### Bootstrapping and handover

In order to bootstrap the handling of legacy chain identifiers, we imagine the EF populating the `chainid.reverse` domain, a temporary `l2.eth` for names and then handing them over.

- EF populates two subdomains `l2.eth` and `chainid.reverse` using Ethereum lists.
- A rollup registers a `rollup.eth` and points it to their `chain_id.
- EF hands over to the rollup `rollup.l2.eth` and `chain_id.chainid.reverse`
- The rollup updates `chain_id.chainid.reverse` to return `rollup.eth`
Comment on lines +89 to +96
Copy link

Choose a reason for hiding this comment

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

What stops a chain from always using the legacy process and getting whatever chain ID they want? Is this a one time migration somehow? I don't fully understand the EF's role here

Copy link

Choose a reason for hiding this comment

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

I can tell that a lot of chains use random chainID and don’t care about collision until they reach Mainnet (or a bit after that, unfortunately). Chains that don’t adhere to this registry will always be there, but I guess new ERCs could be implemented that design an ‘enforcement plan’ within and outside the Ethereum ecosystem.



## Security Considerations
Copy link

Choose a reason for hiding this comment

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

A lot of tooling currently doesn't support uint256 chain IDs, e.g. see MetaMask: https://github.com/MetaMask/metamask-extension/blob/39528b02100a6003f412bbef5e0b560002c945bc/shared/constants/network.ts#L229-L233

Part of this ERC will require an effort to ensure various tooling developers support uint256 chain IDs

Copy link

@Eikix Eikix Nov 26, 2024

Choose a reason for hiding this comment

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

Ledger only supports up to 4 bytes chainIDs for clear signing!

For ledger it's harder to implement because it's at the level of their hardware/firmware

Copy link

Choose a reason for hiding this comment

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

What happens when an ENS name expires and has a new owner? The new owner can change data, what problems will this cause for users? We may want to consider a way to freeze or lock the data so only a specific address can update it


Domain spoofing can lead to replay attacks as described above and can be eliminated by deriving new identifiers using a hash function and by checking the reverse mapping for legacy identifiers.

Domain squatting, the practice of ammassing a large number of domains in the hope to selling them later to legitimate users, is a possibility but with an increasing number of L2 registrations we can expect the same problem to appear in the centralized Github list.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
Loading