Skip to content

State-test sender validation divergences for EIP-7702 malformed delegation code and EIP-2681 saturated nonce #20684

@N0zoM1z0

Description

@N0zoM1z0

System information

Erigon version: evm version 3.3.10-e7de183d

OS & Version: Linux x86_64

Commit hash: e7de183d03cf428094a3329ab5225e876c1d4d36

Erigon Command (with flags/config):

build/bin/evm --json --noreturndata --nomemory statetest <testcase.json>

Consensus Layer: N/A

Consensus Layer Command (with flags/config): N/A

Chain/Network:

  • Prague state tests for the EIP-7702 malformed delegation sender cases.
  • Berlin state test for the EIP-2681 saturated sender nonce case.

Expected behaviour

Erigon should match geth on the attached state tests:

  • Sender code that is not exactly 0xef0100 || 20-byte address should not be treated as a valid EIP-7702 delegation designator.
  • Prefix-only, one-byte-short, and trailing-junk delegation sender code should remain ordinary sender code and should not bypass sender-code rejection.
  • A transaction from a sender whose account nonce is already 2^64 - 1 should be rejected before execution under EIP-2681.

For these expected-invalid cases, the state transition should preserve the expected reject-state root and should not enter the destination contract.

Actual behaviour

Erigon evm from v3.3.10 executes all four attached tests and returns a different post-state root from geth.

The reproduced cases are:

Fixture geth Erigon v3.3.10
eip7702-prefix-only-delegation-sender.json preserves reject-state root enters execution and changes root
eip7702-short-target-delegation-sender.json preserves reject-state root enters execution and changes root
eip7702-trailing-junk-delegation-sender.json preserves reject-state root enters execution and changes root
eip2681-max-sender-nonce.json preserves reject-state root enters execution and changes root

Representative trace boundary from the prefix-only EIP-7702 case:

geth:   {"stateRoot":"0xf224752fba8af944766f36c870787d137b78e2a5981123a07ef042b79902bd0f"}
erigon: {"depth":1,"pc":0,"gas":979000,"op":"0x60","opName":"PUSH1","stack":[]}

This suggests two state-test sender validation gaps:

  1. The EIP-7702 delegation sender exception appears to be applied to malformed sender code.
  2. The EIP-2681 sender nonce upper bound check appears to be missing or bypassed when the sender nonce is already 2^64 - 1.

I have not reproduced these four fixtures through normal block import, Engine API, or p2p sync. The current report is limited to state-test / direct state-transition behavior.

Steps to reproduce the behaviour

The attached archive contains the state tests under attachments/testcases/.

Build Erigon evm from v3.3.10:

git checkout v3.3.10
make evm
build/bin/evm --version

Run the four testcases:

build/bin/evm --json --noreturndata --nomemory statetest attachments/testcases/eip7702-prefix-only-delegation-sender.json
build/bin/evm --json --noreturndata --nomemory statetest attachments/testcases/eip7702-short-target-delegation-sender.json
build/bin/evm --json --noreturndata --nomemory statetest attachments/testcases/eip7702-trailing-junk-delegation-sender.json
build/bin/evm --json --noreturndata --nomemory statetest attachments/testcases/eip2681-max-sender-nonce.json

For comparison, run the same files with geth:

evm statetest --trace --trace.format=json --trace.nomemory=true --trace.noreturndata=true <testcase.json>

The archive also includes:

  • attachments/evidence/*/repro.log: replay transcript for each testcase.
  • attachments/evidence/*/geth-0-output.jsonl: geth comparator output.
  • attachments/evidence/*/erigon-0-output.jsonl: Erigon output.
  • attachments/evidence/erigon-version.txt: tested Erigon version.
  • attachments/evidence/geth-version.txt: comparator version.

Backtrace

N/A. This is a consensus/state-root divergence in statetest execution, not a crash.

Attachment

public-erigon-sender-validation-correctness-attachment.zip

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions