reth: Bug: geth tracer returns hallucinated slot read data

Describe the bug

Performing a debug_traceBlockByNumber trace with the prestateTracer tracer, reth hallucinates some storage reads in the returned RPC response.

For example, let’s say we trace the transaction 0xc44ae9dc6047d56f0027f9e92e2a8d4e515e14e016bdfb7ff04f299cdfc29509. Erigon says there are 11 storage slot reads. Reth says there are 13 storage slot reads. The two extra slot reads from reth are in contract 0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad. This is the uniswap universal router contract, and it basically has only two storage slots that have been there since deployment. But reth claims that this contracts slot 0xe03178286da22a27dd0b1f68fb538cd07bc9080172ee9a5a2238416fe86db02a was read. This slot does not exist so far as I can tell.

Scanning many other blocks and contracts, there are lots of false reads attributed to non-existent slots of this contract in particular.

Steps to reproduce

I used the command cryo storage_reads -b 18.8M:+1 -r RPC_URL to extract data files for both reth and erigon. The transaction listed above 0xc44ae9dc6047d56f0027f9e92e2a8d4e515e14e016bdfb7ff04f299cdfc29509 is the first transaction in block 18,800,000.

Under the hood this uses geth traces debug_traceBlockByNumber with the prestateTracer tracer

Node logs

No response

Platform(s)

Linux (x86)

What version/commit are you on?

This is the reth public node: reth Version: 0.1.0-alpha.10 Commit SHA: 2e73e213 Build Timestamp: 2023-11-03T20:23:02.271051235Z Build Features: default,jemalloc Build Profile: release

What database version are you on?

Current database version: 1 Local database is uninitialized

What type of node are you running?

Archive (default)

What prune config do you use, if any?

No response

If you’ve built Reth from source, provide the full command you used

No response

Code of Conduct

  • I agree to follow the Code of Conduct

About this issue

  • Original URL
  • State: closed
  • Created 5 months ago
  • Comments: 16 (11 by maintainers)

Commits related to this issue

Most upvoted comments

I think this is the issue

the prestate tracer has two modes, prestate mode and diff mode. When t.config.DiffMode is false, meaning prestate mode, the function returns early and never gets rid of those unmodified slots. this gives it the behavior expected from the geth docs

that contradicts what is written here https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers

The prestate tracer has two modes: prestate and diff. The prestate mode returns the accounts necessary to execute a given transaction. diff mode returns the differences between the transaction’s pre and post-state (i.e. what changed because the transaction happened). The prestateTracer defaults to prestate mode. It reexecutes the given transaction and tracks every part of state that is touched. This is similar to the concept of a stateless witness, the difference being this tracer doesn’t return any cryptographic proof, rather only the trie leaves.

this might be fixed by https://github.com/paradigmxyz/evm-inspectors/pull/15 which will land with alpha17