Skip to content

Comments

feat: Implement Forest.EthTraceCall#6412

Merged
akaladarshi merged 24 commits intomainfrom
akaladarshi/eth-trace-call
Feb 23, 2026
Merged

feat: Implement Forest.EthTraceCall#6412
akaladarshi merged 24 commits intomainfrom
akaladarshi/eth-trace-call

Conversation

@akaladarshi
Copy link
Collaborator

@akaladarshi akaladarshi commented Jan 13, 2026

Summary of changes

Changes introduced in this pull request:

Reference issue to close (if applicable)

Closes #6185

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Summary by CodeRabbit

  • New Features

    • Implemented EthTraceCall RPC method for detailed transaction tracing
    • Added state diff support to show account and storage changes during transaction execution
  • Documentation

    • Added developer guide for trace_call implementation and testing workflows
    • Added user documentation for trace_call RPC method with usage examples and troubleshooting
  • Tests

    • Added integration test harness for validating trace outputs
    • Added Tracer contract for EVM behavior testing

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR implements the trace_call RPC method for Forest with support for trace types and state diffs. It introduces new types for trace results and state diffs, adds state diff computation logic, includes an integration test suite with a test contract, and provides comprehensive documentation for users and developers.

Changes

Cohort / File(s) Summary
Core RPC Implementation
src/rpc/methods/eth.rs, src/rpc/mod.rs
Added public EthTraceCall RPC method with EthTraceType and EthTraceResults types; pre/post state computation, trace generation, and conditional state-diff output; updated call paths to use non-clone semantics for block_hash.
Type System & State Diffs
src/rpc/methods/eth/types.rs
Introduced Delta, ChangedType, AccountDiff, and StateDiff types for tracking account/storage changes; updated EthAddress and EthHash to derive PartialOrd, Ord, Copy; changed to_filecoin_address signature from &self to self.
State Diff Computation
src/rpc/methods/eth/trace.rs
Implemented build_state_diff with storage-diff integration using KAMT; added helpers for pre/post actor comparison, EVM storage diffing, and storage entry extraction; replaced env.caller.clone() with direct usage.
State Manager Updates
src/state_manager/mod.rs
Updated apply_on_state_with_gas and call_with_gas to accept flush: bool parameter; returns now include optional state root Cid via vm.flush() when requested.
EVM Accessors
src/shim/actors/builtin/evm/mod.rs
Added three new accessor methods: bytecode(), bytecode_hash(), contract_state() to expose EVM state data.
Clone Optimizations
src/rpc/methods/eth/filter/mod.rs, src/tool/subcommands/api_cmd/api_compare_tests.rs, src/tool/subcommands/api_cmd/stateful_tests.rs
Replaced block_hash and address clones with direct values; adjusted test setups to use moved values instead of clones.
Dependencies & Configuration
Cargo.toml
Added fvm_ipld_kamt = "0.4.5" dependency for KAMT-based storage diffing.
Gas Estimation Update
src/rpc/methods/gas.rs
Updated call_with_gas invocation to handle new return signature with two additional unused values and extra boolean argument.
Testing & Test Contracts
scripts/tests/trace_call_integration_test.sh, src/tool/subcommands/api_cmd/contracts/tracer/Tracer.sol, src/tool/subcommands/api_cmd/test_snapshots_ignored.txt
Added comprehensive bash integration test script with Forest/Anvil trace comparison; created Tracer contract with storage, ETH flow, and trace-testing functions; updated snapshot ignore list.
Documentation
docs/docs/developers/guides/trace_call_guide.md, docs/docs/users/knowledge_base/RPC/trace_call.md, docs/dictionary.txt
Added developer guide covering Tracer.sol usage and integration testing; added user guide detailing trace_call RPC method, request/response formats, and examples; expanded dictionary with blockchain terminology.

Sequence Diagram

sequenceDiagram
    participant Client
    participant RPC as RPC Handler<br/>(trace_call)
    participant StateManager
    participant VM
    participant Store as Blockstore
    
    Client->>RPC: call trace_call(message, traceTypes, blockTag)
    RPC->>StateManager: Get state for blockTag
    StateManager->>Store: Load pre-execution state
    Store-->>StateManager: pre_state
    
    RPC->>VM: Invoke transaction with gas
    VM->>VM: Execute message
    VM-->>RPC: execution result, gas usage
    
    RPC->>StateManager: Get post-execution state
    StateManager->>Store: Load post-execution state
    Store-->>StateManager: post_state
    
    alt if StateDiff requested
        RPC->>RPC: build_state_diff(pre_state, post_state, touched_addresses)
        RPC->>Store: Extract EVM storage entries
        Store-->>RPC: storage map
        RPC->>RPC: Compute Delta for each slot
        RPC->>RPC: Compare balance, nonce, code
    end
    
    RPC->>RPC: Format traces and state diffs
    RPC-->>Client: EthTraceResults (traces + optional stateDiff)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • LesnyRumcajs
  • sudo-shashank
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive While most changes directly support trace_call implementation, several modifications appear tangential: Cargo.toml dependency (fvm_ipld_kamt), dictionary entries, and numerous clone-to-value refactorings lack clear justification. Clarify the necessity of the fvm_ipld_kamt dependency, dictionary additions, and whether clone removal changes are essential vs. optimization-only.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Implement Forest.EthTraceCall' clearly and specifically describes the main change—implementing the EthTraceCall RPC method.
Linked Issues check ✅ Passed The PR implements the trace_call RPC method, includes comprehensive tests (integration test script, extended test coverage in eth.rs and trace.rs), and adds extensive documentation (trace_call.md, trace_call_guide.md).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch akaladarshi/eth-trace-call

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

@akaladarshi akaladarshi changed the title feat: Implement Forest.EthTraceCall feat: Implement Forest.EthTraceCall [Skip CI] Jan 13, 2026
@akaladarshi akaladarshi force-pushed the akaladarshi/eth-trace-call branch 2 times, most recently from 701d095 to a69d125 Compare January 29, 2026 15:28
@akaladarshi akaladarshi force-pushed the akaladarshi/eth-trace-call branch from a69d125 to 47b7aa3 Compare February 3, 2026 14:16
@LesnyRumcajs
Copy link
Member

As discussed, let's have a short guide in docs outlining its usage. This is important in light of various formats used across the Ethereum ecosystem for the output of this method.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/rpc/methods/eth/types.rs`:
- Around line 785-844: Add doc comments to all public helpers related to diffs:
document Delta::from_comparison (describe that it compares old/new Option<T> and
returns Added/Removed/Changed/Unchanged), Delta::is_unchanged (explain it
returns true only for Delta::Unchanged), AccountDiff::is_unchanged (explain it
tests all fields and empty storage), StateDiff::new (note it constructs an empty
StateDiff) and StateDiff::insert_if_changed (state that it inserts the
AccountDiff only when not unchanged). Use /// style comments placed immediately
above each function/struct definition, briefly describing inputs, behavior, and
any important side-effects (e.g., that insert_if_changed skips unchanged diffs).

---

Duplicate comments:
In `@src/rpc/methods/eth.rs`:
- Around line 474-501: Add top-level doc comments for the public trace types:
place concise /// doc comments above the EthTraceType enum describing it
represents the two supported trace output modes (structured call graph "Trace"
and state changes "StateDiff") and above the EthTraceResults struct describing
it represents the combined trace result (output bytes, optional state_diff, and
call trace Vec<EthTrace>) so consumers can discover purpose and fields; keep
existing variant/field docs and serde/lifecycle attributes
(lotus_json_with_self!, #[serde(...)] and derives) intact and ensure comments
follow crate style (brief summary sentence and any important usage notes).
- Around line 4078-4091: In get_trace_output, stop swallowing decode errors by
removing the final .ok(); change the function to propagate decode failures
(e.g., change the signature from fn get_trace_output(...) -> Option<EthBytes> to
return Result<Option<EthBytes>, E>), replace decode_payload(&return_data,
CBOR).ok() with a fallible propagation (e.g., decode_payload(&return_data,
CBOR)? wrapped to produce Ok(Some(...))), and convert the early default-return
branches to Ok(Some(EthBytes::default())) or Ok(None) as appropriate so callers
of get_trace_output (and types like ApiInvocResult and EthBytes) must handle
decoding errors instead of silently receiving None.

@akaladarshi akaladarshi force-pushed the akaladarshi/eth-trace-call branch from 8b47987 to ee300c5 Compare February 20, 2026 17:44
@akaladarshi akaladarshi marked this pull request as draft February 20, 2026 17:46
@akaladarshi akaladarshi marked this pull request as draft February 20, 2026 17:46
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/rpc/methods/eth.rs (1)

4015-4031: Prefer .context() to wrap state/apply errors.
Keeps error chains consistent with project style.

♻️ Suggested tweak
-        let (pre_state_root, _) = ctx
-            .state_manager
-            .tipset_state(&ts, StateLookupPolicy::Enabled)
-            .await
-            .map_err(|e| anyhow::anyhow!("failed to get tipset state: {e}"))?;
+        let (pre_state_root, _) = ctx
+            .state_manager
+            .tipset_state(&ts, StateLookupPolicy::Enabled)
+            .await
+            .context("failed to get tipset state")?;
@@
-            .await
-            .map_err(|e| anyhow::anyhow!("failed to apply message: {e}"))?;
+            .await
+            .context("failed to apply message")?;
As per coding guidelines: "Use `anyhow::Result` for most operations, adding context with `.context()`".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth.rs` around lines 4015 - 4031, Wrap the error returns with
anyhow::Context instead of map_err(anyhow::anyhow!(...)): add use
anyhow::Context if missing, change the tipset_state call to use
.await.context("failed to get tipset state"), change
StateTree::new_from_root(...) to append .context("failed to create StateTree
from root"), and change the apply_on_state_with_gas call to
.await.context("failed to apply message"); keep the same messages but use
.context() for consistent error chaining around tipset_state,
StateTree::new_from_root, and apply_on_state_with_gas.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/docs/developers/guides/trace_call_guide.md`:
- Around line 72-75: Replace the unhyphenated compound adjectives "Geth style
tracing" and "Parity style tracing" with hyphenated forms "Geth-style tracing"
and "Parity-style tracing" in the document so the compounds are grammatically
correct; search for the exact phrases "Geth style" and "Parity style" in the
text and update them accordingly.

In `@src/rpc/methods/eth.rs`:
- Around line 474-501: Public API types EthTraceType and EthTraceResults lack
doc comments; add concise top-level Rust doc comments (/// ...) describing each
type's purpose and behavior, plus brief docs for each EthTraceType variant
(Trace, StateDiff) and for EthTraceResults fields (output, state_diff, trace) to
explain when they are populated and their semantics; ensure comments follow
camelCase/serde intent and appear above the enum, its variants, and the
struct/fields (retain existing serde attributes and lotus_json_with_self!
macros).
- Around line 4036-4038: The code currently swallows decoding failures by
calling decode_payload(...).ok() when building EthTraceResults (around the
get_trace_output/invoke_result usage); change that to propagate the decode error
instead of turning it into None — i.e., remove .ok() and use the fallible call
(e.g., decode_payload(...) ? or decode_payload(...).map_err(|e|
convert_to_rpc_error(e))?) so the enclosing function returns an Err on decode
failure; apply the same fix to the other occurrence that mirrors this behavior
later in the file (the second decode_payload(...) call used when constructing
trace output).

In `@src/rpc/methods/eth/types.rs`:
- Around line 785-845: Public API items lack doc comments; add concise doc
comments for Delta::from_comparison, Delta::is_unchanged, the AccountDiff struct
and AccountDiff::is_unchanged, and the StateDiff struct plus StateDiff::new and
StateDiff::insert_if_changed that explain purpose, parameters and return
behavior (e.g., what from_comparison does with old/new Options, what
is_unchanged checks, that StateDiff is a transparent BTreeMap of account ->
AccountDiff, new creates an empty StateDiff, and insert_if_changed only inserts
non-unchanged AccountDiffs). Keep comments short, use /// style and mention any
invariants or important behavior (like storage emptiness meaning unchanged).

---

Nitpick comments:
In `@src/rpc/methods/eth.rs`:
- Around line 4015-4031: Wrap the error returns with anyhow::Context instead of
map_err(anyhow::anyhow!(...)): add use anyhow::Context if missing, change the
tipset_state call to use .await.context("failed to get tipset state"), change
StateTree::new_from_root(...) to append .context("failed to create StateTree
from root"), and change the apply_on_state_with_gas call to
.await.context("failed to apply message"); keep the same messages but use
.context() for consistent error chaining around tipset_state,
StateTree::new_from_root, and apply_on_state_with_gas.

@akaladarshi akaladarshi added this pull request to the merge queue Feb 23, 2026
Merged via the queue into main with commit 3846eb2 Feb 23, 2026
45 of 46 checks passed
@akaladarshi akaladarshi deleted the akaladarshi/eth-trace-call branch February 23, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

RPC requires calibnet RPC checks to run on CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement trace_call RPC method

4 participants