HomeEIPs
EIPsEIP-1965
EIP-1965

Method to check if a chainID is valid at a specific block Number

StagnantStandards Track: Core
Created: 2019-04-20
Requires: EIP-155
Ronan Sandford (@wighawag)
DiscussionsOriginal linkEdit
1 min read

EIP-1965 proposes a method to check if a chainID is valid at a specific block number, which addresses the limitations of the current approach of specifying the chain ID at compile time or accessing the latest chainID. The proposal suggests modifying EIP-1344 to return the block number at which a chainID becomes invalid, but acknowledges that this could be easily ignored by contracts. The proposal assumes that minority-led forks will not gain traction and therefore do not need to be protected. The EIP is fully backwards compatible with all chains that implement EIP-155 chain ID domain separator for transaction signing. The proposal suggests updating EIP-712 to deal with chainID separately from the domain separator and acknowledges that implementing a smart contract-based caching solution as proposed in EIP-1344 comes with a higher gas cost. The proposal addresses the risks associated with using the latest chainID for L2 message verification and emphasizes the importance of ensuring the validity of past chainIDs via a trustless cache implemented via smart contract. Overall, the proposal aims to provide a more secure and reliable method for checking the validity of chainIDs at specific block numbers.

Video
Anyone may contribute to propose contents.
Go propose
Original

Abstract

This EIP adds a precompile that returns whether a specific chainID (EIP-155 unique identifier) is valid at a specific blockNumber. ChainID are assumed to be valid up to the blockNumber at which they get replaced by a new chainID.

Motivation

EIP-155 proposes to use the chain ID to prevent the replay of transactions between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling off-chain message signatures, especially for Layer 2 signature schemes using EIP-712.

EIP-1344 is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insuficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344. Furthermore EIP-1344 can't protect replay properly for minority-led hardfork as the caching system cannot guarantee accuracy of the blockNumber at which the new chainID has been introduced.

EIP-1959 solves the issue of EIP-1344 but do not attempt to protect from minority-led hardfork as mentioned in the rationale. We consider this a mistake, since it remove some freedom to fork. We consider that all fork should be given equal oportunities. And while there will always be issues we can't solve for the majority that ignore a particular fork, users that decide to use both the minority-fork and the majority-chain should be protected from replay without having to wait for the majority chain to update its chainID.

Specification

Adds a new precompile which uses 2 argument : a 32 bytes value that represent the chainID to test and a 32 bytes value representing the blockNumber at which the chainID is tested. It return 0x1 if the chainID is valid at the specific blockNumber, 0x0 otherwise. Note that chainID are considered valid up to the blockNumber at which they are replaced. So they are valid for every blockNumber past their replacement.

The operation will costs no more than G_blockhash + G_verylow to execute. This could be lower as chainID are only introduced during hardfork.

The cost of the operation might need to be adjusted later as the number of chainID in the history of the chain grows.

Note though that the alternative to keep track of old chainID is to implement a smart contract based caching solution as EIP-1344 proposes comes with an overall higher gas cost and exhibit issues for minority-led hardfork (see Rationale section below). As such the gas cost is simply a necessary cost for the feature.

Rationale

The rationale at EIP-1959 applies here as well too :

  • An opcode is better than a caching system for past chainID, It is cheaper, safer and do not include gaps.
  • Direct access to the latest chainID is dangerous since it make it easy for contract to use it as a replay protection mechanism while preventing otherwise valid old messages to be valid after a fork that change the chainID. This can have disastrous consequences on users.
  • all off-chain messaged signed before a fork should be valid across all side of the fork.

The only difference is that this current proposal propose a solution to protect hardfork led by a minority.

To summarize there is 2 possible fork scenario :

  1. The majority decide to make an hardfork but a minority disagree with it (ETC is such example). The fork is planned for block X. If the majority is not taking any action to automate the process of assigning a different chainID for both, the minority has plenty of time to plan for a chainID upgrade to happen at that same block X. Now if they do not do it, their users will face the problem that their messages will be replayable on the majority chain (Note that this is not true the other way around as we assume the majority decided to change the chainID). As such there is no reason that they’ll leave it that way.

  2. A minority decide to create an hardfork that the majority disagree with (or simply ignore). Now, the same as above can happen but since we are talking about a minority there is a chance that the majority do not care about the minority. In that case, there would be no incentive for the majority to upgrade the chainID. This means that user of both side of the fork will have the messages meant for the majority chain replayable on the minority-chain (even if this one changed its chainID) unless extra precaution is taken.

The solution is to add the blockNumber representing the time at which the message was signed and use it as an argument to the opcode proposed here. This way, when the minority forks with a new chainID, the previous chainID become invalid from that time onward. So new messages destinated to the majority chain can't be replayed on the minority fork.

Backwards Compatibility

EIP-712 is still in draft but would need to be updated to include the blockNumber as part of the values that wallets need to verify for the protection of their users.

Since chainID and blockNumber will vary, they should not be part of the domain separator (meant to be generated once) but another part of the message.

While the pair could be optional for contract that do not care about replays or have other ways to prevent them, if chainID is present, the blockNumber must be present too. And if any of them is present, wallet need to ensure that the chainID is indeed the latest one of the chain being used, while the blockNumber is the latest one at the point of signing. During fork transition, the wallet can use the blockNumber to know which chainID to use.

References

This was previously suggested as part of EIP1959 discussion.

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose
Adopted by projects
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve EIP builders, scale Ethereum.
Resources
GitHub
Supported by