EIP-2294: Explicit bound to Chain ID

I came across this EIP-2294 and think it’s important. Highlighting it here for the community discussion.

Related prior discussion

So far the biggest chainid that’s publically known to us is

  • 868,455,272,153,094 aka
  • 0x 3 15DB 0000 0006

from in github.com/ethereum-lists/chains

Update 2022-10-18:

Here are two mutually exclusive scenarios the EIP try to prevent/resolve

  1. With the increasing number of chains, in particular in the post-sharding future of EVMs, some people want to use some hash function for collision resilient hashing functions e.g. keccak256(<human-readable-string") as a way to generate new chainIds which will be the full space of uint256

  2. ChainId was being used be added to the parity bit for signatures e.g. EIP-712 which has a ceiling of floor(MAX_UINT64 / 2) - 36 unless we manipulate the algorithm.

These two requirement for chainId space must be resolved and I urge that we make a decision before Shanghai hardfork

Invite to comment

Authors of EIPs that might be affected

Resuming the EIP-2294 as PR EIP-2294: Explicit bound to Chain ID size by xinbenlv · Pull Request #5728 · ethereum/EIPs · GitHub

One major concern I have with limiting chain IDs to ~63 bits is that you cannot then have a hash used as a chainID. I would want the limit to be 256, 384, or 512, or unspecified.

~63 bits of entropy is not sufficient collision resistance for a hash function, reasonable use or not.

What may be needed is for clients to present loud warning messages when chain IDs that are not supported by hardware wallets are used (and I think 32 bits is the real limit for that). Just a loud obnoxious warning if block height is < 100k (i.e. soon enough to reconsider your chain), not a hard block.

1 Like

Hi all, I am moving the EIP-2294 to Review status

Totally agree with that rationale. Let me address them and loop in other authors for comment

In today’s ACD,
@xinbenlv advocated to prioritize EIP-2294 into shanghai fork.
@MariusVanDerWijden responded that if it’s low cost, let’s do it, but don’t need to have a deadline to be shipped before Shanghai fork.
@MicahZoltu responded support EIP-2294 that bounds chainId at its current proposed ceiling. Because it has been a de facto rule. @MicahZoltu further proposed that we don’t need to do any coding immediately, just need to agree as a group and call it a rule.
@shemnon responded whether we should accept such bounding just because no one has ever used any chainId above bounds. Ask to think twice.

Please correct me if I were wrong.

@sambacha responded on github

Metamask has a hardcoded value for rejecting chainId’s over a certain number. That number is calculated based off of

source from remarks, metamask engineer

From ethereumjs-util@7.0.5, we have that:

  v = recovery + (chainId * 2 + 35)

Per the above discussion, we also have that:

  int_max = 2**53 - 1
  recovery_max = 3
  chainId_max = ?


  v_max = 3 + (chainId * 2 + 35) = chainId * 2 + 38
  v_max <= int_max
  2**53 - 1 = MAX_SAFE_CHAIN_ID * 2 + 38
  // Since we're dealing with integers, we round down.
  MAX_SAFE_CHAIN_ID = floor( ( 2**53 - 39 ) / 2 ) = 4503599627370476

Ethereumjs-util as referenced above has BigInt support since 7.0.9, regardless metamask has encoded this value within their application.
see https://github.com/ethereumjs/ethereumjs-util/releases/tag/v7.0.9

1 Like

Here is an example of how replay protection safe chainId is used in a contract: tweak: add block.chainid as per t11s public shaming · yieldprotocol/yield-utils-v2@13ec941 · GitHub

A more comprehensive example: BoringSolidity/Domain.sol at master · boringcrypto/BoringSolidity · GitHub

WETH10 adopts such measures even: WETH10/WETH10.sol at e952d1ec4c149e85d93ed2ce4040ac571ed6bc19 · WETH10/WETH10 · GitHub

As for networks that exceed the safe limit, I have only seen one, and it was an ephemeral test network.

1 Like

I understand that some tooling limits CHAIND, but I don’t see this as a reason to shut down all ChainIDs over 53 bits in length. I see a future where there are large amounts of ephemiral L2 and L3 chains and they will need a mechanical way to set a rational and deterministic means, and a 256 bit hash is that means. Much like how CREATE2 enabled Uniswap and it’s derivatives. I don’t want to kneecap this future because math in JavaScript has non-obvious rules.

Perhaps we need to limit chainIDs expressable by transaction types.

  • For Type 0/legacy (Frontier) transactions the metamask limit is enforced, since integer math needs to be performed on the chain ID.
  • For Type 1 (Berlin) and Type 2 (London) transactions a 256 bit limit is enforced. There is no math done for these transactions: it is a binary blob moved around without encoding. The limit here comes from EVM limits of 256 bits returned from the CHAINID operation.

The impact being if you want to use a hashed ChainID you must use a modern transaction container.

1 Like

I find the “deterministically generated globally unique chain ID” argument to be quite compelling and I think that puts me into the camp of asserting that ChainID is 256 bits.

1 Like

@MicahZoltu good point. I start to find @shemnon 's argument quite compelling too.

I see a future where there are large amounts of ephemiral L2 and L3 chains and they will need a mechanical way to set a rational and deterministic means

One possible use case: in the future @shemnon described one-day that uint256 bit of ChainId could be used to used on a chain to point to another chain… or bridges between them