Ultimate EVM Tracing Reference
This repo is a collection of trace-related information for easy reference.
A best effort is made to provide accurate information. Please submit corrections to the issue tracker.
Contents
- Tracers
- Trace Methods
- Node Client Support
- RPC Provider Support
- Ecosystem Tooling Support
- Hosted Data Platform Support
- Example Tracer Data
Tracers
A tracer gives a detailed view into what happened during a block or transaction.
Each tracer type provides a different set of information. There are two main categories of tracers, parity and geth. Each node client supports these tracer types to varying degrees.
To see the specific information returned by each tracer, see the schemas and data samples in the Example Tracer Data below.
tracer | description | parameters |
---|---|---|
parity calls 1 |
calls in a flat list structure | [ "trace" ] |
parity stateDiffs 2 |
all state changes for each tx | [ "stateDiff" ] |
parity vmTraces |
opcode-level trace | [ "vmTrace" ] |
geth opcodes |
opcode-level trace | { } |
geth calls 1 |
calls in a nested structure | { "tracer": "callTracer" } |
geth preState 2 |
data that was read before each tx | { "tracer": "prestateTracer" } |
geth stateDiffs 2 |
all state changes for each tx | { "tracer": "prestateTracer", "diffMode": true } |
geth 4byte |
4byte prefixes of function calls | { "tracer": "4byteTracer" } |
geth javascript 3 |
custom javascript tracer functions | { "tracer": "{ fault: ..., result: ... }" } |
1: Geth call traces contain nearly identical information to Parity call traces. There are differences such as 1) they include precompile calls, 2) they used a nested schema instead of a list, 3) they do not include block rewards. See here for additional differences.
2: There are four types of state changes: balances, codes, nonces, and storage. State-related traces include information about all four.
3: "tracer is interpreted as a JavaScript expression that is expected to evaluate to an object which must expose the result and fault methods. There exist 4 additional methods, namely: setup, step, enter, and exit. enter and exit must be present or omitted together."
Trace Methods
RPC methods are used to obtain trace data from RPC endpoints.
Each method applies one or more tracers to a particular scope of data, such as a block, transaction, or call data.
rpc method | description | tracers |
---|---|---|
trace_block |
basic block trace | parity calls |
trace_transaction |
basic transaction trace | parity calls |
trace_replayBlockTransactions |
advanced block trace | all parity tracers |
trace_replayTransaction |
advanced transaction trace | all parity tracers |
trace_filter |
query a subset of traces | all parity tracers |
trace_call |
trace custom call_data | all parity tracers |
trace_callMany |
trace sequence of call_data | all parity tracers |
trace_rawTransaction |
parity call_data trace | all parity tracers |
trace_get |
parity indexed trace | parity calls |
debug_traceBlock |
advanced block trace | all geth tracers |
debug_traceTransaction |
basic transaction trace | all geth tracers |
debug_traceCall |
trace custom call_data | all geth tracers |
debug_traceBlockByNumber |
advanced block trace | all geth tracers |
debug_traceBlockByHash |
advanced block trace | all geth tracers |
Node Client Support
Node clients track the state of the chain and can perform tracing on the chain's history.
Each node client supports a different set of tracers and trace methods.
rpc method | geth | reth | erigon | besu | nethermind |
---|---|---|---|---|---|
trace_block |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_transaction |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_replayBlockTransactions |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_replayTransaction |
❌ | ✅ | ✅ | ❌ | ✅ |
trace_filter |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_call |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_callMany |
❌ | ✅ | ✅ | ✅ | ❌ |
trace_rawTransaction |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_get |
❌ | ✅ | ✅ | ✅ | ❌ |
debug_traceBlock |
✅ | ✅ | ✅ | ✅ | ✅ |
debug_traceTransaction |
✅ | ✅ | ✅ | ❌ | ✅ |
debug_traceCall |
✅ | ✅ | ✅ | ❌ | ✅ |
debug_traceBlockByNumber |
✅ | ✅ | ✅ | ❌ | ✅ |
debug_traceBlockByHash |
✅ | ✅ | ✅ | ✅ | ✅ |
The set of traces that can be obtained for a chain is determined by the clients that support that chain:
rpc method | geth | reth | erigon | besu | nethermind | geth fork |
---|---|---|---|---|---|---|
ethereum | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
goerli | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
arbitrum | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
optimism | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ |
zora | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ |
base | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ |
polygon | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ |
gnosis | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
bnb | ❌ | ❌ | ✅* | ❌ | ❌ | ✅ |
RPC Provider Support
RPC providers create endpoints where customers can access RPC data without having to run their own nodes.
Every node provider supports different tracers and trace methods.
rpc method | infura | alchemy (pricing) |
quicknode (pricing) |
llamanodes (pricing) |
chainstack (pricing) |
---|---|---|---|---|---|
trace_block |
✅ | ✅ | ✅ | ✅ | ✅ |
trace_transaction |
✅ | ✅ | ✅ | ✅ | ✅ |
trace_replayBlockTransactions |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_replayTransaction |
❌ | ✅ | ✅ | ✅ | ✅ |
trace_filter |
✅ | ✅ | ✅ | ✅ | ✅ |
trace_call |
✅ | ✅ | ✅ | ✅ | ✅ |
trace_callMany |
✅ | ❌ | ✅ | ✅ | ✅ |
trace_rawTransaction |
❌ | ✅ | ✅ | ❌ | ✅ |
trace_get |
❌ | ✅ | ❌ | ✅ | ✅ |
debug_traceBlock |
❌ | ❌ | ✅ | ❌ | ✅ |
debug_traceTransaction |
❌ | ✅ | ✅ | ✅ | ✅ |
debug_traceCall |
❌ | ✅ | ✅ | ✅ | ✅ |
debug_traceBlockByNumber |
❌ | ✅ | ✅ | ✅ | ✅ |
debug_traceBlockByHash |
❌ | ✅ | ✅ | ✅ | ✅ |
Ecosystem Tooling Support
Many different tools exist for obtaining and analyzing traces.
Each tool supports a different set of tracers and trace methods. The libraries in the javascript ecosystem generally do not support tracing.
📟 = can use from command line
🐍 = can use as a python library
🦀 = can use as a rust library
tracer | cryo 📟🐍🦀 |
ethereum etl 📟 |
ethers.rs 🦀 |
ctc 🐍 |
ape 🐍 |
web3py 🐍 |
---|---|---|---|---|---|---|
parity calls |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
parity stateDiffs |
✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
parity vmTraces |
✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
geth opcodes |
✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
geth calls |
✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
geth preState |
✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
geth stateDiffs |
✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
geth 4byte counts |
✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
geth javascript |
✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
Hosted Data Platform Support
Hosted data platforms allow customers to interact with trace data directly without running their own infrastructure.
Most platforms only support call traces.
tracer | Dune | Flipside | Bigquery | Allium |
---|---|---|---|---|
parity calls |
✅ | ✅ | ✅ | ✅ |
parity stateDiffs |
❌ | ❌ | ❌ | ❌ |
parity vmTraces |
❌ | ❌ | ❌ | ❌ |
geth opcodes |
❌ | ❌ | ❌ | ❌ |
geth calls |
✅ | ✅ | ✅ | ✅ |
geth preState |
❌ | ❌ | ❌ | ❌ |
geth state diffs |
❌ | ❌ | ❌ | ❌ |
geth 4byte counts |
❌ | ❌ | ❌ | ❌ |
geth javascript |
❌ | ❌ | ❌ | ❌ |
Example Tracer Data
A 100 block sample of data is provided for each tracer (block range 10,000,000 through 10,000,099)
tracer | schema | data | collection command |
---|---|---|---|
parity calls |
schema- action_from: binary |
parquet | cryo traces -b 10M:+100 |
parity stateDiffs balances |
schema- transaction_hash: binary |
parquet | cryo balance_diffs -b 10M:+100 |
parity stateDiffs codes |
schema- block_number: uint32 |
parquet | cryo code_diffs -b 10M:+100 |
parity stateDiffs nonces |
schema- block_number: uint32 |
parquet | cryo nonce_diffs -b 10M:+100 |
parity stateDiffs storage |
schema- block_number: uint32 |
parquet | cryo storage_diffs -b 10M:+100 |
parity vmTraces |
schema- block_number: uint32 |
parquet | cryo vm_traces -b 10M:+100 |
geth opcodes |
schema- block_number: uint32 |
parquet | cryo geth_opcodes -b 10M:+100 \ --include-columns stack storage |
geth calls |
schema- typ: string |
parquet | cryo geth_calls -b 10M:+100 |
geth prestate balances |
schema- block_number: uint32 |
parquet | cryo balance_reads -b 10M:+100 |
geth prestate codes |
schema- block_number: uint32 |
parquet | cryo code_reads -b 10M:+100 |
geth prestate nonces |
schema- block_number: uint32 |
parquet | cryo nonce_reads -b 10M:+100 |
geth prestate storages |
schema- block_number: uint32 |
parquet | cryo storage_reads -b 10M:+100 |
geth stateDiffs balances |
schema- block_number: uint32 |
parquet | cryo geth_balance_diffs -b 10M:+100 |
geth stateDiffs codes |
schema- block_number: uint32 |
parquet | cryo geth_code_diffs -b 10M:+100 |
geth stateDiffs nonces |
schema- block_number: uint32 |
parquet | cryo geth_nonce_diffs -b 10M:+100 |
geth stateDiffs storages |
schema- block_number: uint32 |
parquet | cryo geth_storage_diffs -b 10M:+100 |
geth 4byte counts |
schema- block_number: uint32 |
parquet | cryo 4byte_counts -b 10M:+100 |