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 14 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.
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.
Copy link

Choose a reason for hiding this comment

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

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


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.

Choose a reason for hiding this comment

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

Suggested change
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.
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 the 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.

Choose a reason for hiding this comment

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

I hear the point that 32-byte identifiers might seem like an overcorrection at the moment, especially if the current chain ecosystem isn’t scaling into the millions anytime soon. But I believe that making room for robust, collision-resistant identifiers now—even if it adds a small hurdle in the short term—ultimately sets us up for long-term success. By implementing larger identifiers early, we ensure that we won’t need multiple incremental expansions down the line as the ecosystem evolves and potentially grows beyond today’s forecasts.

In other words, taking this step now creates a durable standard that can accommodate future growth without repeated adjustments or migration pains. It’s about thinking ahead and choosing a solution that positions us for scalability and reliability in the years to come.

Copy link

Choose a reason for hiding this comment

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

I think eth-lists/chains should stop accepting new entries as soon as we populate the chainid.reverse domain during bootstrap. We won't be able to add any additional entries to the domain afterwards, so new chains that inadvertently register new eth-lists/chains entries won't be resolvable by wallets later when chain-specific addresses are adopted.

New chains that for whatever reason prefer not to register their names on Ethereum L1 should register it in a new alt repo, so it'll be explicit that they opt out of chain-specific address resolution.

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?

Choose a reason for hiding this comment

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

Yes, I believe that incorporating additional information like the DA layer, tech stack, and other relevant details could be part of a new attestation-based specification or ERC. This will require further discussions and decisions on the optimal way to implement where this information is stored and how it's accessed. I strongly believe that these aspects are closely tied to how interoperability will function, and addressing them will be crucial for developing effective interop solutions.

Copy link

Choose a reason for hiding this comment

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

If the chain changes his nature, it needs to change chainID.

If we included tech-stack, wouldn't it mean that tech changes cause unneeded service interruption? E.g. if Optimism switches from Optimistic to ZK validity proofs, should it require switching to a new chainid and refreshing it in every user's wallet?

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.

Choose a reason for hiding this comment

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

It says

DEPLOYER_CONTRACT_ADDRESS is the address of the L2 on the L1

As in the Rollup Contract? Its not beyond the realms of possibility that this could change. As could SETTLEMENT_CHAIN_ID in principle. Is that the intention?

Copy link

Choose a reason for hiding this comment

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

Then here’s the principle again, as I stated in another comment: if the DEPLOYER_CONTRACT_ADDRESS, does it mean that the Rollup changes, relative to the L1? In the same way, if the SETTLEMENT_CHAIN_ID changes, the chain is changing nature, so it’s another chain.

That’s because if the user deposits on the Rollup, they do it knowing that there’s a specific configuration (at a high level), for example that the X L2 settles on Ethereum.

If the settlement chain changes to another L1, maybe the users or developers don’t trust it anymore because they trusted Ethereum better. The same could be said about changing the DA layer, and similarly the tech stack (OP, ZK, SN, etc.)

Maybe the alias can be the same, but there’s got to be a way to differentiate the chains when they change their fundamental nature. This is about trust assumption as much as it is about versioning chain releases for the community.

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?

Choose a reason for hiding this comment

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

I would say this is the version of the ERC.

```
where:
- `SETTLEMENT_CHAIN_ID` is the id of the L1 where the L2 settles, it could be Mainnet or a testnet.
- `VERSION` is to separate the domain of the hash function with an arbitrary string
- `DEPLOYER_CONTRACT_ADDRESS` is the address of the L2 on the L1
Copy link

Choose a reason for hiding this comment

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

The one contract that is unlikely to ever change for a rollup, even if it changes its underlying technology, is the canonical bridge. It can't change easily because it holds assets on L1. Anything else might change in a future upgrade. Shouldn't we use CANONICAL_BRIDGE_ADDRESS rather than DEPLOYER?


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

Copy link
Contributor

Choose a reason for hiding this comment

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

ENSIP-11

This is an external link, and must be removed. We do have a process for allowing certain external links. See EIP-5757.


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?

Choose a reason for hiding this comment

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

If they are live testnets i think they should be treated same way as a mainnet is.

Copy link

Choose a reason for hiding this comment

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

ERC-7828 indicates that they're resolved in the chain specified as the TLD. E.g. rollup.sepolia.

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

Copy link

Choose a reason for hiding this comment

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

This should be a one-time process during bootstrap. EF's role would be just to copy current content of eth-lists/chains to the new domain. This operation will be publicly verifiable. After it's populated, EF should have no way to keep editing the data in the domain.

ERC-7828 can be seen as an 'enforcement plan' because wallets that use chain-specific addresses won't be able to resolve new chains that don't adhere to this process.

For that reason I proposed (above) that eth-lists/chains stops accepting new entries when the one-time migration happens. It'll prevent inadvertent use of incompatible chainids by devs not familiar with the new process. Chains devs that don't adhere to it could register elsewhere and should be aware that they opt out of ERC-7828 support.

Copy link

Choose a reason for hiding this comment

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

Just to again remind about the chainID collision: there are two chains that currently use the same chainID.

Nova Network and Waves use the same chainID, 87.



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

Choose a reason for hiding this comment

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

This is a great point. Let me put together some ideas for how we can potentially lock the data.


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.
Copy link

Choose a reason for hiding this comment

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

This domain could also be made more expensive to deter squatting. L2 projects require significant funding anyway so spending hundreds of dollars on registration won't be a major issue, but will make squatting impractical.


## Copyright

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