Skip to content

feat(l1): implement debug_traceCall RPC endpoint#6695

Open
azteca1998 wants to merge 5 commits into
mainfrom
feat/debug-trace-call
Open

feat(l1): implement debug_traceCall RPC endpoint#6695
azteca1998 wants to merge 5 commits into
mainfrom
feat/debug-trace-call

Conversation

@azteca1998
Copy link
Copy Markdown
Contributor

Summary

  • Adds debug_traceCall which traces an arbitrary call at a given block state without creating a transaction on-chain
  • Supports all existing tracers: callTracer, prestateTracer, opcodeTracer
  • Adds trace-call infrastructure at each layer (LEVM → Evm → Blockchain → RPC)
  • Accepts the same call object format as eth_call plus an optional trace config
  • Matches geth's debug_traceCall

Closes part of #6572

Test plan

  • debug_traceCall with callTracer returns nested call frames
  • debug_traceCall with prestateTracer returns pre/post state
  • debug_traceCall with opcodeTracer returns EIP-3155 step trace
  • Block identifier parameter works (latest, specific number, hash)
  • Default block (latest) works when block param omitted

Add debug_traceCall which traces an arbitrary call (GenericTransaction)
at a given block state without creating a transaction on-chain. Supports
all existing tracers: callTracer, prestateTracer, opcodeTracer.

Adds trace-call infrastructure at each layer:
- LEVM: trace_call_calls, trace_call_prestate, trace_call_opcodes
- Evm: wrapper methods for generic-tx tracing
- Blockchain: async trace_call_* methods with timeout support
- RPC: TraceCallRequest handler with geth-compatible param parsing

Part of #6572
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 21, 2026

⚠️ Known Issues — intentionally skipped tests

Source: docs/known_issues.md

Known Issues

Tests intentionally excluded from CI. Source of truth for the Known
Issues
section the L1 workflow appends to each ef-tests job summary
and posts as a sticky PR comment.

EF Tests — Stateless coverage narrowed to EIP-8025 optional-proofs

make -C tooling/ef_tests/blockchain test calls test-stateless-zkevm
instead of test-stateless. The zkevm@v0.3.3 fixtures are filled against
bal@v5.6.1, out of sync with current bal spec; the broad target trips ~549
fixtures. Re-broaden once the zkevm bundle is regenerated.

Why and resolution path

PR #6527 broadened
test-stateless to extract the entire for_amsterdam/ tree from the
zkevm bundle and run all of it under --features stateless; combined with
this branch's bal-devnet-7 semantics that scope produces ~549
GasUsedMismatch / ReceiptsRootMismatch /
BlockAccessListHashMismatch failures.

test-stateless-zkevm filters cargo to the eip8025_optional_proofs
suite, which still validates the stateless harness without the bal-version
mismatch.

Re-broaden by switching test: back to test-stateless in
tooling/ef_tests/blockchain/Makefile once the zkevm bundle is regenerated
against the current bal spec.

@github-actions github-actions Bot added the L1 Ethereum client label May 21, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 21, 2026

Lines of code report

Total lines added: 417
Total lines removed: 0
Total lines changed: 417

Detailed view
+-------------------------------------------+-------+------+
| File                                      | Lines | Diff |
+-------------------------------------------+-------+------+
| ethrex/crates/blockchain/tracing.rs       | 288   | +47  |
+-------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/rpc.rs       | 1302  | +1   |
+-------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/tracing.rs   | 514   | +199 |
+-------------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/mod.rs     | 2492  | +44  |
+-------------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/tracing.rs | 406   | +77  |
+-------------------------------------------+-------+------+
| ethrex/crates/vm/tracing.rs               | 139   | +49  |
+-------------------------------------------+-------+------+

Set up a funded account, then call debug_traceCall with a
simulated transfer. Assert the callTracer response shape.
Tests as shipped exercised one path: callTracer, "latest" block, against
a genesis-only state. That left the three tracer variants asymmetric on
coverage and didn't validate any of the items on the PR's own test plan.

Added integration tests covering: prestateTracer + opcodeTracer paths,
block-by-number, block-by-hash (EIP-1898 form), default-to-latest when
the block parameter is omitted, unknown-block error, and empty-params
error. The post-block tests pin `nonce` in the call object because
ethrex's LEVM enforces nonce equality even on simulated calls — a
pre-existing constraint shared with `eth_call`, documented inline so the
next person doesn't repeat the diagnosis.

Documented two ergonomic gaps on `TraceCallRequest` itself:

- `stateOverrides` / `blockOverrides` from the third parameter are
  silently ignored. Real geth-compat support requires plumbing overrides
  down to the VM, so this is called out as a known divergence rather
  than fixed in-flight.
- Pruned nodes that don't have the target block's state will surface
  the storage layer's "state root missing" error as a generic Internal.

Test setup boilerplate moves out of the misnamed `debug_trace_tests.rs`
into the shared `rpc::helpers` module introduced in #6701; the file is
renamed to `debug_trace_call_tests.rs`. Also polished the handler's
default-block fallback (one allocation instead of an `Option::clone`)
and switched the not-found error from "Block not Found" to "Block not
found" to match the casing every other endpoint uses.
@azteca1998 azteca1998 marked this pull request as ready for review May 26, 2026 14:42
@azteca1998 azteca1998 requested a review from a team as a code owner May 26, 2026 14:42
@ethrex-project-sync ethrex-project-sync Bot moved this to In Review in ethrex_l1 May 26, 2026
@github-actions
Copy link
Copy Markdown

🤖 Kimi Code Review

The PR implements debug_traceCall RPC method correctly with proper state isolation, timeout handling, and tracer support. Below are specific observations:

Code Quality & Correctness

crates/vm/backends/levm/tracing.rs (Lines 163-238)
The three new trace methods duplicate environment setup logic:

let mut env = env_from_generic(tx, block_header, db, vm_type)?;
env.block_gas_limit = i64::MAX as u64;
adjust_disabled_base_fee(&mut env);

Consider extracting this into a prepare_env_for_trace_call helper to reduce duplication, though this is minor given only three sites.

crates/vm/backends/levm/tracing.rs (Lines 176, 202, 234)
Using i64::MAX as u64 for unlimited gas works but u64::MAX is more idiomatic for "disable gas limit" semantics. Functionally equivalent since both exceed any practical block gas limit.

crates/networking/rpc/tracing.rs (Lines 418-419)
The default block fallback correctly resolves to "latest":

let default_block = BlockIdentifierOrHash::Identifier(BlockIdentifier::default());

Verify BlockIdentifier::default() returns "latest" (standard behavior).

Security & Consensus

State Isolation — The implementation correctly uses header.state_root (post-block state) and executes in memory without persistence, matching geth semantics documented in the code comments.

Timeout Protection — All three trace methods in blockchain/tracing.rs properly use timeout_trace_operation, preventing DoS via long-running traces on expensive calls.

Gas Price Handling — The adjust_disabled_base_fee call in tracing context (line 177, 203, 235 of levm/tracing.rs) correctly handles the edge case where gas_price == 0 by zeroing base fee, preventing EVM invariant violations as noted in the existing comment.

Testing

The integration tests in debug_trace_call_tests.rs comprehensively cover:

  1. Default tracer selection (callTracer)
  2. Block parameter defaulting to "latest"
  3. Block resolution by number and hash (EIP-1898)
  4. Alternative tracers (prestate, opcode)
  5. Error cases (unknown block, missing params)

Test Helper Safetysetup_genesis_only in helpers.rs correctly notes that nonce enforcement applies even to simulated calls, requiring explicit nonce matching in post-block tests. This aligns with eth_call behavior.

Documentation

The doc comment on TraceCallRequest (lines 35-55 of tracing.rs) excellently documents the known divergence from geth (stateOverrides/blockOverrides not supported). This is critical for RPC API compatibility expectations.

Minor Suggestions

  1. Line 428 in tracing.rs: The error message "Block not found" could include the block identifier for easier debugging:

    .ok_or_else(|| RpcErr::Internal(format!("Block not found: {:?}", block)))?;
  2. Line 234 in blockchain/tracing.rs: The clones tx.clone() and header.clone() are necessary for the move closure but could be expensive. Consider documenting why cloning is required (the closure runs in a potentially different thread context via spawn_blocking).

Verdict

The code is correct, secure, and well-tested. The implementation follows Ethereum RPC specifications appropriately and includes proper safeguards against resource exhaustion. No blocking issues identified.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions
Copy link
Copy Markdown

🤖 Codex Code Review

  1. crates/networking/rpc/types/block_identifier.rs:93-100 resolves BlockIdentifierOrHash::Hash by first mapping hash -> number and then calling get_block_header(number). For debug_traceCall, that means an EIP-1898 {blockHash} request can trace against the canonical header at that height instead of the exact block the caller named. If the store retains non-canonical forks, this returns the wrong state_root, wrong BLOCKHASH context, and wrong trace. This new endpoint is exposing that bug directly. Hash should resolve via get_block_header_by_hash (or equivalent) instead of round-tripping through block number.

  2. crates/networking/rpc/tracing.rs:61-70 and :405-406 silently drop unsupported traceConfig fields. In particular, stateOverrides and blockOverrides are documented as ignored, but the request still succeeds and produces a trace for the real chain state. For a debugging API, that is dangerous: callers can believe they traced a hypothetical state when they did not. Until overrides are implemented, this should return BadParams on those fields rather than succeeding.

  3. crates/networking/rpc/tracing.rs:75-86 keeps CallTracer as the default tracer, but debug_traceCall in geth defaults to the struct logger/opcode-style response. Since this PR adds a geth-named endpoint, omitting tracer now yields a different wire shape from what geth-compatible tooling expects. The divergence is documented, but for a brand-new RPC surface this is still an interoperability break.

Assumption: Item 1 depends on the store retaining non-canonical blocks, but StoreVmDatabase already has explicit non-canonical ancestor handling, so that looks like a supported case.

I couldn’t run the Rust tests here because cargo/rustup tried to create temp files under a read-only rustup directory (/home/runner/.rustup/tmp).


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 26, 2026

Greptile Summary

This PR implements the debug_traceCall RPC endpoint, which traces an arbitrary call against chain state at a given block without creating an on-chain transaction. All three existing tracer types are supported (callTracer, prestateTracer, opcodeTracer), and the implementation threads through all four layers: LEVM → Evm → Blockchain → RPC.

  • Adds trace_call_* methods at each layer that mirror the existing trace_tx_*/trace_block_* patterns, using a new vm_from_generic_with_tracer helper that builds a VM from a GenericTransaction with a caller-supplied tracer.
  • Introduces TraceCallRequest in the RPC layer with RpcHandler parse/handle logic, inline unit tests, and a new integration-test file (debug_trace_call_tests.rs) with shared helpers covering genesis-only and single-transfer-block states.

Confidence Score: 4/5

Safe to merge. The new endpoint follows established patterns for all three tracers and the test coverage is solid. Two minor code-quality notes but no functional defects.

The implementation correctly threads through all layers and closely mirrors the existing transaction-tracer code paths. The only notable gap is that vm_from_generic now duplicates vm_from_generic_with_tracer's body instead of delegating to it, which could cause the two to silently diverge when a new transaction type is added. The reexec field in TraceConfig is also accepted but silently ignored without documentation. Both are cosmetic rather than functional.

crates/vm/backends/levm/mod.rs for the duplicated function body; crates/networking/rpc/tracing.rs for the undocumented reexec no-op.

Important Files Changed

Filename Overview
crates/vm/backends/levm/mod.rs Exposes env_from_generic and adjust_disabled_base_fee as pub(crate), and adds vm_from_generic_with_tracer — a near-identical copy of vm_from_generic with an extra tracer parameter. The duplication is benign today but the original is not refactored to delegate.
crates/vm/backends/levm/tracing.rs Adds three trace_call_* methods on LEVM that mirror the existing trace_tx_* methods. Pattern is consistent: build env, override block_gas_limit to i64::MAX, build VM with tracer, execute, return result. Logic is sound.
crates/blockchain/tracing.rs Adds three async wrapper methods that follow the exact same timeout_trace_operation pattern used by the existing transaction tracers. No issues found.
crates/networking/rpc/tracing.rs New TraceCallRequest implements parse/handle following the existing TraceTransactionRequest pattern. The reexec field from TraceConfig is silently ignored without documentation. Good inline unit tests added.
crates/networking/rpc/rpc.rs One-line addition routing debug_traceCall to TraceCallRequest::call. Correct placement in the debug namespace dispatcher.
crates/vm/tracing.rs Adds three thin delegating methods on Evm that forward to LEVM::trace_call_*. Correctly plumbed with vm_type and crypto passthrough.
test/tests/rpc/debug_trace_call_tests.rs Good coverage: default tracer, omitted block param, by-block-number, by-block-hash (EIP-1898), prestateTracer, opcodeTracer, unknown block error, and empty-params error.
test/tests/rpc/helpers.rs New shared test helpers file: setup_store, setup_genesis_only, setup_single_transfer_block, rpc_call, and rpc_call_expect_err. Well-structured and reusable.

Sequence Diagram

sequenceDiagram
    participant Client
    participant RPC as TraceCallRequest (rpc/tracing.rs)
    participant BC as Blockchain (blockchain/tracing.rs)
    participant EVM as Evm (vm/tracing.rs)
    participant LEVM as LEVM (vm/backends/levm/tracing.rs)
    participant VM as VM (levm)

    Client->>RPC: debug_traceCall([callObj, blockId?, traceConfig?])
    RPC->>RPC: parse() — GenericTransaction + BlockIdentifierOrHash + TraceConfig
    RPC->>BC: resolve block header
    BC-->>RPC: BlockHeader
    RPC->>BC: "trace_call_calls/prestate/opcodes(&header, &tx, timeout, ...)"
    BC->>BC: StoreVmDatabase::new(storage, header)
    BC->>BC: new_evm(vm_db)
    BC->>BC: timeout_trace_operation(timeout, closure)
    BC->>EVM: "trace_call_calls/prestate/opcodes(&header, &tx, ...)"
    EVM->>LEVM: trace_call_calls/prestate/opcodes(db, header, tx, ...)
    LEVM->>LEVM: env_from_generic(tx, header, db)
    LEVM->>LEVM: "env.block_gas_limit = i64::MAX"
    LEVM->>LEVM: "adjust_disabled_base_fee(&mut env)"
    LEVM->>LEVM: vm_from_generic_with_tracer(tx, env, db, tracer)
    LEVM->>VM: VM::new(env, db, tx, tracer, vm_type, crypto)
    VM-->>LEVM: vm
    LEVM->>VM: vm.execute()
    VM-->>LEVM: Ok(())
    LEVM->>VM: get_trace_result / opcode_tracer.take_result
    VM-->>LEVM: CallTrace / PrestateResult / OpcodeTraceResult
    LEVM-->>EVM: Result
    EVM-->>BC: Result
    BC-->>RPC: Result
    RPC->>RPC: serialize result
    RPC-->>Client: JSON response
Loading

Comments Outside Diff (1)

  1. crates/vm/backends/levm/mod.rs, line 2838-2881 (link)

    P2 vm_from_generic is now an exact duplicate of vm_from_generic_with_tracer except for the hardcoded LevmCallTracer::disabled(). If the Transaction-building logic ever diverges (e.g. a new tx type is added), one copy will silently lag behind the other. The original can simply delegate to eliminate the duplication.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: crates/vm/backends/levm/mod.rs
    Line: 2838-2881
    
    Comment:
    `vm_from_generic` is now an exact duplicate of `vm_from_generic_with_tracer` except for the hardcoded `LevmCallTracer::disabled()`. If the Transaction-building logic ever diverges (e.g. a new tx type is added), one copy will silently lag behind the other. The original can simply delegate to eliminate the duplication.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
crates/vm/backends/levm/mod.rs:2838-2881
`vm_from_generic` is now an exact duplicate of `vm_from_generic_with_tracer` except for the hardcoded `LevmCallTracer::disabled()`. If the Transaction-building logic ever diverges (e.g. a new tx type is added), one copy will silently lag behind the other. The original can simply delegate to eliminate the duplication.

```suggestion
fn vm_from_generic<'a>(
    tx: &GenericTransaction,
    env: Environment,
    db: &'a mut GeneralizedDatabase,
    vm_type: VMType,
    crypto: &'a dyn Crypto,
) -> Result<VM<'a>, VMError> {
    vm_from_generic_with_tracer(tx, env, db, vm_type, crypto, LevmCallTracer::disabled())
}
```

### Issue 2 of 2
crates/networking/rpc/tracing.rs:43-46
The `reexec` field is deserialized from the caller's `traceConfig` but is never read in `TraceCallRequest::handle`. For `debug_traceTransaction` and `debug_traceBlockByNumber`, `reexec` controls how far back to re-execute blocks to rebuild missing trie state. That concept doesn't apply here (state comes directly from the block header's state root), so ignoring it is correct — but unlike `stateOverrides`/`blockOverrides`, this divergence is not mentioned in the doc comment, which may surprise callers who pass it expecting an effect.

```suggestion
/// **Known divergence from geth**: geth's `traceConfig` accepts
/// `stateOverrides` and `blockOverrides` for hypothetical-state debugging.
/// ethrex does not yet honour either — they are silently ignored. Pass-through
/// support requires applying overrides at the VM layer before execution.
///
/// The `reexec` field in `traceConfig` is also accepted but has no effect:
/// state is read directly from the block header's state root rather than
/// being rebuilt by re-executing ancestor blocks.
```

Reviews (1): Last reviewed commit: "fix(rpc): broaden debug_traceCall test c..." | Re-trigger Greptile

Comment on lines +43 to +46
/// **Known divergence from geth**: geth's `traceConfig` accepts
/// `stateOverrides` and `blockOverrides` for hypothetical-state debugging.
/// ethrex does not yet honour either — they are silently ignored. Pass-through
/// support requires applying overrides at the VM layer before execution.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The reexec field is deserialized from the caller's traceConfig but is never read in TraceCallRequest::handle. For debug_traceTransaction and debug_traceBlockByNumber, reexec controls how far back to re-execute blocks to rebuild missing trie state. That concept doesn't apply here (state comes directly from the block header's state root), so ignoring it is correct — but unlike stateOverrides/blockOverrides, this divergence is not mentioned in the doc comment, which may surprise callers who pass it expecting an effect.

Suggested change
/// **Known divergence from geth**: geth's `traceConfig` accepts
/// `stateOverrides` and `blockOverrides` for hypothetical-state debugging.
/// ethrex does not yet honour either — they are silently ignored. Pass-through
/// support requires applying overrides at the VM layer before execution.
/// **Known divergence from geth**: geth's `traceConfig` accepts
/// `stateOverrides` and `blockOverrides` for hypothetical-state debugging.
/// ethrex does not yet honour either — they are silently ignored. Pass-through
/// support requires applying overrides at the VM layer before execution.
///
/// The `reexec` field in `traceConfig` is also accepted but has no effect:
/// state is read directly from the block header's state root rather than
/// being rebuilt by re-executing ancestor blocks.
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/networking/rpc/tracing.rs
Line: 43-46

Comment:
The `reexec` field is deserialized from the caller's `traceConfig` but is never read in `TraceCallRequest::handle`. For `debug_traceTransaction` and `debug_traceBlockByNumber`, `reexec` controls how far back to re-execute blocks to rebuild missing trie state. That concept doesn't apply here (state comes directly from the block header's state root), so ignoring it is correct — but unlike `stateOverrides`/`blockOverrides`, this divergence is not mentioned in the doc comment, which may surprise callers who pass it expecting an effect.

```suggestion
/// **Known divergence from geth**: geth's `traceConfig` accepts
/// `stateOverrides` and `blockOverrides` for hypothetical-state debugging.
/// ethrex does not yet honour either — they are silently ignored. Pass-through
/// support requires applying overrides at the VM layer before execution.
///
/// The `reexec` field in `traceConfig` is also accepted but has no effect:
/// state is read directly from the block header's state root rather than
/// being rebuilt by re-executing ancestor blocks.
```

How can I resolve this? If you propose a fix, please make it concise.

@github-actions
Copy link
Copy Markdown

🤖 Claude Code Review

Now I have everything needed for a thorough review. Let me write it up.


Review: feat(l1): implement debug_traceCall RPC endpoint (#6695)

The layering (RPC → Blockchain → Evm → LEVM) is clean and mirrors the existing debug_traceTransaction structure. Unit tests cover parse edge cases well, and the integration tests exercise all three tracer types plus block identifier variants. A few issues worth addressing before merge:


Code Duplication — vm_from_generic_with_tracer vs vm_from_generic

crates/vm/backends/levm/mod.rs lines 2888–2431

vm_from_generic_with_tracer is a verbatim copy of vm_from_generic; the only difference is the final VM::new(…, tracer, …) call replacing VM::new(…, LevmCallTracer::disabled(), …). Any future fix to the transaction-construction logic (new tx types, authorization list edge cases, access list mapping) must be manually mirrored.

A cleaner approach: refactor vm_from_generic to accept the tracer and make the existing call sites pass LevmCallTracer::disabled(). That collapses two near-identical functions into one.


Undocumented Nonce-Enforcement Divergence from Geth

test/tests/rpc/debug_trace_call_tests.rs lines 643–651, crates/networking/rpc/tracing.rs doc comment lines 118–140

The test comment acknowledges that ethrex enforces nonce equality even for simulated calls. Geth's debug_traceCall bypasses nonce checks entirely (it builds the tx context with disableNonceCheck). The consequence: any caller whose account nonce is non-zero must pass an explicit "nonce" field, otherwise the trace silently fails rather than simulating the call.

This should be added to the "Known divergence from geth" list in the doc comment alongside stateOverrides/blockOverrides. It also affects usability more than the override divergence does, because override omission is at least a no-op, while a wrong nonce is a hard failure.


"Block not found" Mapped to RpcErr::Internal

crates/networking/rpc/tracing.rs line 185:

.ok_or_else(|| RpcErr::Internal("Block not found".to_string()))?;

A missing block is a client-supplied invalid parameter, not an internal server error. Geth returns error code -32000 with the message "block not found" (their InvalidParamsError). Using RpcErr::Internal misleads callers into thinking the node is broken when they simply asked for a non-existent block. Compare the test trace_call_unknown_block_errors which asserts on the message string—it would pass either way, but the JSON-RPC error code in the wire response would be wrong.


stateOverrides / blockOverrides Silently Ignored

crates/networking/rpc/tracing.rs doc comment lines 127–130

Silent ignore is documented but dangerous in a debugging tool — users sending overrides will get results against the real state without any indication that their overrides were dropped. Consider either:

  • Returning a structured "warning" field in the response, or
  • Returning a RpcErr::Unimplemented if override fields are detected in the request body

At minimum, the TraceConfig struct should deserialize and inspect those fields so the server is at least aware they were sent.


env.block_gas_limit = i64::MAX as u64 Repeated Three Times

crates/vm/backends/levm/tracing.rs lines 473, 501, 538

All three trace_call_* implementations apply the same two-line setup:

env.block_gas_limit = i64::MAX as u64;
adjust_disabled_base_fee(&mut env);

If a fourth tracer is added later, it's easy to forget one of these (especially adjust_disabled_base_fee). Extracting into a shared prepare_trace_call_env(env: &mut Environment) function in levm/mod.rs would make the intent explicit and ensure consistency.


Missing Tests

  • Reverted call: No test verifies that a call that reverts (e.g., insufficient balance, explicit REVERT) produces a trace with failed: true / an error frame rather than propagating an EvmError through the stack. The vm.execute()? in all three trace functions will surface VM-level errors; it's worth confirming that EVM-level reverts produce results, not errors.

  • Contract creation (to omitted): Geth supports tracing contract deployments via debug_traceCall (no to field). The EIP-1559 branch in vm_from_generic_with_tracer passes tx.to.clone() which preserves TxKind::Create, so this may work — but there's no test or documentation confirming it, and no integration test exercises the path.


Minor

  • crates/networking/rpc/tracing.rs line 160: BlockIdentifierOrHash::parse(v.clone(), 1) — the index argument 1 is the 0-based param position, which is correct for error messages.
  • StructLoggerEmit { refund: false } (line 246) — consistent with debug_traceTransaction handler and correct per the StructLoggerEmit doc ("non-zero refund is always emitted regardless of this flag").
  • The test #[allow(dead_code)] on helpers.rs is appropriate for shared test infrastructure.

Summary

The implementation is functionally complete for the common path. The two items most likely to cause user-facing confusion are the undocumented nonce enforcement (silent failures for accounts with nonce > 0) and the "block not found" wrong error code. The vm_from_generic_with_tracer duplication is the main maintenance risk. Everything else is low priority.


Automated review by Claude (Anthropic) · sonnet · custom prompt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

1 participant