Skip to content

feat(api): Implement debug_traceTransaction API#6751

Merged
akaladarshi merged 9 commits intomainfrom
akaladarshi/debug-trace-txn
Mar 25, 2026
Merged

feat(api): Implement debug_traceTransaction API#6751
akaladarshi merged 9 commits intomainfrom
akaladarshi/debug-trace-txn

Conversation

@akaladarshi
Copy link
Copy Markdown
Collaborator

@akaladarshi akaladarshi commented Mar 16, 2026

Summary of changes

Changes introduced in this pull request:

Reference issue to close (if applicable)

Closes #6675

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.

Outside contributions

  • I have read and agree to the CONTRIBUTING document.
  • I have read and agree to the AI Policy document. I understand that failure to comply with the guidelines will lead to rejection of the pull request.

Summary by CodeRabbit

  • New Features

    • Added a Geth-compatible debug_traceTransaction RPC (Forest.EthDebugTraceTransaction) supporting call, flatCall, prestate, and noop tracers, plus prestate diff mode and Filecoin-specific tracing behaviors.
  • Documentation

    • New developer and user tracer guides with examples, configs, workflows, and updated deployed tracer contract address.
  • Tests

    • Added test helpers and comprehensive unit/integration tests covering trace construction, prestate diffs, storage/code toggles, and tracer behaviors.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 16, 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

Adds a Geth-compatible debug_traceTransaction RPC: new RPC method and registry entry, tracer option types, Geth/PreState trace builders, state-replay support in StateManager, state-diff and trace utilities, test helpers and unit tests, plus developer and user documentation updates.

Changes

Cohort / File(s) Summary
Documentation
docs/docs/developers/guides/debug_trace_transaction_guide.md, docs/docs/users/knowledge_base/rpc/debug_trace_transaction.md, docs/docs/developers/guides/trace_call_guide.md, docs/docs/users/knowledge_base/rpc/trace_call.md
Adds developer and user guides for debug_traceTransaction and updates deployed Tracer contract addresses and examples.
RPC method & registry
src/rpc/methods/eth.rs, src/rpc/mod.rs, src/tool/subcommands/api_cmd/test_snapshots_ignored.txt
Adds Forest.EthDebugTraceTransaction/debug_traceTransaction RPC method and handler, options parsing, registry entry, and snapshot-ignore update; minor receipt formatting tweak.
Trace types & builders
src/rpc/methods/eth/trace/types.rs, src/rpc/methods/eth/trace/geth.rs
Introduces Geth tracing data models (GethTrace, call frames, PreStateFrame), tracer config types, builders (build_geth_call_frame, build_prestate_frame), revert constant, and extensive unit tests.
Tracing infra & public surface
src/rpc/methods/eth/trace/mod.rs, src/rpc/methods/eth/trace/parity.rs, src/rpc/methods/eth/trace/state_diff.rs
Adds shared Environment/base_environment, re-exports geth module, exposes parity/state-diff functions/types, and adapts parity traces to shared environment; exposes build_state_diff, extract_evm_storage_entries, diff_entry_keys.
Trace utilities & test helpers
src/rpc/methods/eth/trace/utils.rs, src/rpc/methods/eth/trace/test_helpers.rs
Adds ZERO_HASH, trace_to_address, revert extraction, u256->hash helper and test helpers for building state trees/diffs; includes unit tests.
State replay & VM visibility
src/state_manager/mod.rs, src/interpreter/vm.rs
Adds async replay_for_prestate (and blocking implementation) to capture pre/post roots and invocation result during tipset replay; relaxes reward_message visibility to pub(crate).
Misc scripts/tests
scripts/tests/trace_call_integration_test.sh, src/tool/subcommands/api_cmd/test_snapshots_ignored.txt
Updates default FOREST_CONTRACT address in integration test script and adds RPC snapshot-ignore entry.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant RPC as "RPC Handler\n(Forest.EthDebugTraceTransaction)"
    participant StateMan as "State Manager\n(replay_for_prestate)"
    participant TraceBuilder as "Trace Builder\n(geth/parity builders)"
    participant DB as "State DB / Blockstore"

    Client->>RPC: debug_traceTransaction(txHash, opts)
    RPC->>DB: Resolve tx by hash (ensure included in block)
    alt PreState tracer
        RPC->>StateMan: replay_for_prestate(tipset, target_msg_cid)
        StateMan->>DB: Load parent state, execute messages up to target
        StateMan-->>RPC: (pre_root, ApiInvocResult, post_root)
        RPC->>TraceBuilder: build_prestate_frame(pre_state, post_state, touched_addrs)
        TraceBuilder-->>RPC: PreStateFrame
    else Call/FlatCall tracer
        RPC->>StateMan: replay tipset to collect ExecutionTrace[]
        StateMan-->>RPC: ExecutionTrace[]
        RPC->>TraceBuilder: build_geth_call_frame(execution_trace)
        TraceBuilder-->>RPC: GethCallFrame / Flat frames
    end
    RPC->>RPC: Construct GethTrace variant (PreState/Call/Flat/Noop)
    RPC-->>Client: JSON GethTrace response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • sudo-shashank
  • LesnyRumcajs
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(api): Implement debug_traceTransaction API' clearly and accurately summarizes the main change: implementing a new RPC API endpoint for transaction debugging.
Linked Issues check ✅ Passed The PR successfully implements all requirements from issue #6675: accepts different tracer types (CallTracer, PreStateTracer, FlatCallTracer, Noop), processes tracer-specific configurations, and builds Geth-compatible trace output formats.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing debug_traceTransaction. Updates to Tracer.sol contract addresses and test helpers are supportive; visibility changes (reward_message, parse_eth_revert) are necessary infrastructure for the main feature.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch akaladarshi/debug-trace-txn
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch akaladarshi/debug-trace-txn

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

@akaladarshi akaladarshi reopened this Mar 16, 2026
@akaladarshi akaladarshi force-pushed the akaladarshi/debug-trace-txn branch from 0b8c563 to 38cb7df Compare March 17, 2026 09:08
@akaladarshi akaladarshi marked this pull request as ready for review March 17, 2026 09:09
@akaladarshi akaladarshi requested a review from a team as a code owner March 17, 2026 09:09
@akaladarshi akaladarshi requested review from LesnyRumcajs and hanabi1224 and removed request for a team March 17, 2026 09:09
@akaladarshi akaladarshi added the RPC requires calibnet RPC checks to run on CI label Mar 17, 2026
Copy link
Copy Markdown
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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/rpc/methods/eth.rs (1)

3700-3716: ⚠️ Potential issue | 🟠 Major

Resolve touched subcall addresses from actor metadata, not raw message addresses.

This is fine for the top-level message, but internal ExecutionTrace.msg.from / msg.to values can be ID addresses. Converting those directly yields masked IDs, so build_prestate_frame / build_state_diff can emit snapshots under masked addresses even though the trace builders already use src/rpc/methods/eth/trace/utils.rs:10-17 trace_to_address(...) to resolve delegated 0x addresses when actor metadata is available.

🔧 Suggested direction
-fn extract_touched_eth_addresses(trace: &crate::rpc::state::ExecutionTrace) -> HashSet<EthAddress> {
+fn extract_touched_eth_addresses(trace: &crate::rpc::state::ExecutionTrace) -> HashSet<EthAddress> {
     let mut addresses = HashSet::default();
-    let mut stack = vec![trace];
+    let mut stack = vec![(trace, None)];

-    while let Some(current) = stack.pop() {
-        if let Ok(eth_addr) = EthAddress::from_filecoin_address(&current.msg.from) {
-            addresses.insert(eth_addr);
-        }
-        if let Ok(eth_addr) = EthAddress::from_filecoin_address(&current.msg.to) {
-            addresses.insert(eth_addr);
-        }
-        stack.extend(&current.subcalls);
+    while let Some((current, parent_caller)) = stack.pop() {
+        let caller = parent_caller
+            .or_else(|| EthAddress::from_filecoin_address(&current.msg.from).ok());
+        let callee = current
+            .invoked_actor
+            .as_ref()
+            .map(trace_to_address)
+            .or_else(|| EthAddress::from_filecoin_address(&current.msg.to).ok());
+
+        if let Some(addr) = caller {
+            addresses.insert(addr);
+        }
+        if let Some(addr) = callee {
+            addresses.insert(addr);
+            for subcall in &current.subcalls {
+                stack.push((subcall, Some(addr)));
+            }
+        }
     }

     addresses
 }
🤖 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 3700 - 3716,
extract_touched_eth_addresses currently converts subcall msg.from/msg.to
directly via EthAddress::from_filecoin_address which yields masked IDs; instead
resolve internal addresses using the trace_to_address helper (from
src/rpc/methods/eth/trace/utils.rs) so delegated 0x addresses from actor
metadata are used; update extract_touched_eth_addresses to call
trace_to_address(current, ...) for subcall "from" and "to" resolution (falling
back to EthAddress::from_filecoin_address only if trace_to_address returns None)
while keeping the top-level behavior intact.
src/rpc/methods/eth/trace/state_diff.rs (1)

206-243: ⚠️ Potential issue | 🟠 Major

Don't collapse storage read failures into an empty diff.

If an EVM actor's state or KAMT can't be read, this helper currently returns {} and the callers treat that as “no storage touched”. That can produce false-negative stateDiff / prestateTracer output instead of surfacing the underlying corruption or read failure. Keep the None / non-EVM fast path, but propagate real load/iteration errors with context.

🔧 Suggested direction
-pub fn extract_evm_storage_entries<DB: Blockstore>(
+pub fn extract_evm_storage_entries<DB: Blockstore>(
     store: &DB,
     actor: Option<&ActorState>,
-) -> HashMap<[u8; 32], U256> {
+) -> anyhow::Result<HashMap<[u8; 32], U256>> {
     let actor = match actor {
         Some(a) if is_evm_actor(&a.code) => a,
-        _ => return HashMap::default(),
+        _ => return Ok(HashMap::default()),
     };

-    let evm_state = match evm::State::load(store, actor.code, actor.state) {
-        Ok(state) => state,
-        Err(e) => {
-            debug!("failed to load EVM state for storage extraction: {e}");
-            return HashMap::default();
-        }
-    };
+    let evm_state = evm::State::load(store, actor.code, actor.state)
+        .context("failed to load EVM state for storage extraction")?;

     // keep the explicit empty-storage fast path here if needed

     let mut entries = HashMap::default();
-    if let Err(e) = kamt.for_each(|key, value| {
+    kamt.for_each(|key, value| {
         entries.insert(key.to_big_endian(), *value);
         Ok(())
-    }) {
-        debug!("failed to iterate storage KAMT: {e}");
-        return HashMap::default();
-    }
+    })
+    .context("failed to iterate storage KAMT")?;

-    entries
+    Ok(entries)
 }

As per coding guidelines "Use anyhow::Result for most operations and add context with .context() when errors occur".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/state_diff.rs` around lines 206 - 243, Change
extract_evm_storage_entries to return anyhow::Result<HashMap<[u8;32], U256>> and
keep the non-EVM fast path returning Ok(HashMap::default()); for actual I/O/load
failures propagate errors instead of returning an empty map by using
.context(...) (or anyhow::Error::new) on the calls that can fail:
evm::State::load(store, actor.code, actor.state),
Kamt::load_with_config(&storage_cid, store, config) and kamt.for_each(...),
returning Err(...) with clear context strings like "loading EVM state", "loading
storage KAMT", and "iterating storage KAMT"; update callers to handle Result
accordingly.
🧹 Nitpick comments (3)
src/rpc/methods/eth/trace/utils.rs (1)

11-26: Add doc comments to the new public trace helpers.

trace_to_address, extract_revert_reason, and u256_to_eth_hash are new public helpers and currently undocumented. Brief doc comments would make their contracts and edge-case behavior much easier to follow.

As per coding guidelines "Document public functions and structs with doc comments".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/utils.rs` around lines 11 - 26, Add concise Rust
doc comments to each public helper: trace_to_address, extract_revert_reason, and
u256_to_eth_hash. For trace_to_address describe what address is derived
(delegated_address preferred, fallback to ActorID via from_actor_id) and any
edge cases (when delegated_address is absent or conversion fails). For
extract_revert_reason document the expected input (EthBytes from a reverted
transaction), what parse_eth_revert returns, and that it returns None or
Some(String) only when the parsed reason does not start with "0x" (i.e., non-hex
reasons). For u256_to_eth_hash state that it converts a U256 into an EthHash by
writing big-endian bytes into an ethereum_types::H256 and note any assumptions
about byte ordering and fixed-size padding. Keep each comment short, use /// doc
comment style, and place them immediately above the respective function
definitions.
src/rpc/methods/eth/trace/types.rs (2)

180-191: Document the new public helper methods.

These helpers are public API surface but still lack doc comments: PreStateConfig::{is_diff_mode,is_code_disabled,is_storage_disabled}, GethCallType::{as_str,is_static_call}, AccountState::is_empty, and EthTrace::is_success.

As per coding guidelines, "Document public functions and structs with doc comments".

Also applies to: 219-232, 312-317, 430-432

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/types.rs` around lines 180 - 191, Several
newly-added public helper methods lack doc comments; add concise Rustdoc for
PreStateConfig::is_diff_mode, PreStateConfig::is_code_disabled,
PreStateConfig::is_storage_disabled, GethCallType::as_str,
GethCallType::is_static_call, AccountState::is_empty, and EthTrace::is_success
describing what each returns, the semantics (e.g. what true/false means), and
any edge cases (like unwrap_or default behavior); place the /// comments
immediately above each function or enum method, using brief one-line summary
plus a short note if needed about defaults or behavior when underlying Option is
None.

204-248: Use strum for GethCallType string conversions.

This enum now keeps Serde renames, as_str(), and a manual Display impl in sync by hand. Deriving the string conversions with strum would remove that duplication and reduce drift.

As per coding guidelines, "Use strum crate for enum string conversions".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/types.rs` around lines 204 - 248, Replace the
hand-rolled string conversion and Display for GethCallType with strum derives:
add strum_macros derives (e.g., EnumString, AsRefStr and Display) to the
GethCallType enum, add #[strum(serialize = "...")] on each variant using the
current uppercase tokens ("CALL", "STATICCALL", etc.) to preserve as_str/Display
behavior, keep the existing #[serde(rename = "...")] attributes, remove the
manual as_str() and the std::fmt::Display impl, and simplify
from_parity_call_type to parse the parity string (e.g.,
call_type.parse().unwrap_or(Self::Call)) or map via EnumString serializations
for lowercase parity inputs using appropriate #[strum(serialize = "staticcall")]
entries on the matching variants; update any callers accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/docs/developers/guides/debug_trace_transaction_guide.md`:
- Around line 119-120: Replace the literal Anvil private key value assigned to
the ANVIL_KEY export with a symbolic placeholder to avoid committing secrets;
update the line that sets ANVIL_KEY so it references a descriptive placeholder
(e.g., "ANVIL_PRIVATE_KEY_PLACEHOLDER" or instruct readers to set their own key
in their environment) and keep the ANVIL_RPC export as-is; ensure the guide text
around ANVIL_KEY explains to replace the placeholder with their own key or load
it from a secure source.

In `@docs/docs/users/knowledge_base/rpc/debug_trace_transaction.md`:
- Around line 127-134: The doc text contradicts itself about which accounts
appear in diff-mode: update the Diff mode behavior to state that "pre" contains
the state before execution for all accounts that were touched by the transaction
(including read-only touches that existed before execution), while "post"
contains only the fields that changed after execution; make explicit that
read-only touched accounts therefore appear in "pre" but not in "post", and
clarify that accounts that were neither touched nor changed are omitted from
both "pre" and "post". Reference the "pre" and "post" labels in that paragraph
so readers clearly understand read-only touches appear only in "pre".

In `@src/interpreter/vm.rs`:
- Line 524: Add a Rustdoc comment for the crate-public function reward_message
describing its purpose and contract: explain what reward_message does, the
meaning of its parameters and return value (and any side effects or error/panic
conditions) so other crate modules can use it correctly; place the doc comment
(/// ...) immediately above the pub(crate) fn reward_message declaration and
keep it concise and informative.

In `@src/rpc/methods/eth/trace/geth.rs`:
- Around line 171-188: The code currently always calls
extract_evm_storage_entries and diff_entry_keys even when storage tracing is
disabled; update the logic to check the tracer option (e.g.,
config.disableStorage or the tracer disable flag) and skip the expensive KAMT
walks when true: only call extract_evm_storage_entries for pre_actor/post_actor
and diff_entry_keys when storage is enabled, otherwise set
pre_entries/post_entries/changed_keys to None or empty and pass that through to
build_account_snapshot_from_entries so build_account_snapshot_from_entries is
invoked without attempting to read storage; apply the same conditional change
for the second occurrence that mirrors the block using pre_entries/post_entries
at the later lines.
- Around line 171-173: The diff drops pure storage clears because when a slot
goes nonzero->0 the post snapshot is empty and subsequent retain/remove logic
eliminates those cleared slots; update the logic around
extract_evm_storage_entries/diff_entry_keys handling so that for each key in
changed_keys missing from post_entries you insert a zero-valued entry into the
post structure (or otherwise preserve the pre entry for that key) before
building post_map/post_snap and before calling
pre_map.retain(...)/retain_changed, ensuring cleared slots are represented in
post_map and the account isn’t removed; reference extract_evm_storage_entries,
diff_entry_keys, pre_entries, post_entries, changed_keys, post_snap, pre_map,
post_map, and retain_changed when making the change.
- Around line 119-124: The code silently drops errors by calling .ok() on
actor.eth_nonce(store) and actor.eth_bytecode(store), which hides state decoding
failures; update build_prestate_frame to propagate these errors (it already
returns anyhow::Result) by replacing .ok()/flatten() with the try operator (?)
and add context() to both calls (e.g., when calling actor.eth_nonce(store) and
actor.eth_bytecode(store)) so failures return an Err with a helpful message;
keep honoring config.is_code_disabled() for skipping bytecode retrieval.

In `@src/rpc/methods/eth/trace/types.rs`:
- Around line 113-144: Change parse_tracer_config to return anyhow::Result<T>
(instead of T) and fail on JSON deserialization errors using
serde_json::from_value(...).context("invalid tracerConfig") rather than
defaulting to T::default(); update GethDebugTracingOptions::call_config to
propagate that Result (it already returns anyhow::Result<CallTracerConfig>) and
ensure it still checks cfg.with_log after successful parsing, and change
GethDebugTracingOptions::prestate_config to return
anyhow::Result<PreStateConfig> (propagating parse_tracer_config errors) so
callers of prestate_config and any upstream call sites (e.g. trace entrypoints)
are updated to handle the Result.

In `@src/state_manager/mod.rs`:
- Around line 907-912: The current code calls vm.flush() and traced_vm.flush()
while the VM is bound to the canonical DB (TipsetExecutor::create_vm /
chain_index.db()), causing non-canonical per-request roots to be persisted;
instead, create a temporary/overlay blockstore (in-memory or overlay layer) and
bind both the pre-execution VM and the traced VM to that temporary store so
their flush() calls write only to the overlay and are discarded after the trace.
Specifically, replace the use of the canonical-bound VMs when calling vm.flush()
and traced_vm.flush() by constructing VMs via create_vm (or the VM constructor
used here) that accept a temporary store or overlay, run apply_message on the
traced VM, compute pre_root/post_root against that temp store, then drop the
overlay without writing to chain_index.db(); ensure TipsetExecutor::create_vm
remains used for canonical state changes only.

---

Outside diff comments:
In `@src/rpc/methods/eth.rs`:
- Around line 3700-3716: extract_touched_eth_addresses currently converts
subcall msg.from/msg.to directly via EthAddress::from_filecoin_address which
yields masked IDs; instead resolve internal addresses using the trace_to_address
helper (from src/rpc/methods/eth/trace/utils.rs) so delegated 0x addresses from
actor metadata are used; update extract_touched_eth_addresses to call
trace_to_address(current, ...) for subcall "from" and "to" resolution (falling
back to EthAddress::from_filecoin_address only if trace_to_address returns None)
while keeping the top-level behavior intact.

In `@src/rpc/methods/eth/trace/state_diff.rs`:
- Around line 206-243: Change extract_evm_storage_entries to return
anyhow::Result<HashMap<[u8;32], U256>> and keep the non-EVM fast path returning
Ok(HashMap::default()); for actual I/O/load failures propagate errors instead of
returning an empty map by using .context(...) (or anyhow::Error::new) on the
calls that can fail: evm::State::load(store, actor.code, actor.state),
Kamt::load_with_config(&storage_cid, store, config) and kamt.for_each(...),
returning Err(...) with clear context strings like "loading EVM state", "loading
storage KAMT", and "iterating storage KAMT"; update callers to handle Result
accordingly.

---

Nitpick comments:
In `@src/rpc/methods/eth/trace/types.rs`:
- Around line 180-191: Several newly-added public helper methods lack doc
comments; add concise Rustdoc for PreStateConfig::is_diff_mode,
PreStateConfig::is_code_disabled, PreStateConfig::is_storage_disabled,
GethCallType::as_str, GethCallType::is_static_call, AccountState::is_empty, and
EthTrace::is_success describing what each returns, the semantics (e.g. what
true/false means), and any edge cases (like unwrap_or default behavior); place
the /// comments immediately above each function or enum method, using brief
one-line summary plus a short note if needed about defaults or behavior when
underlying Option is None.
- Around line 204-248: Replace the hand-rolled string conversion and Display for
GethCallType with strum derives: add strum_macros derives (e.g., EnumString,
AsRefStr and Display) to the GethCallType enum, add #[strum(serialize = "...")]
on each variant using the current uppercase tokens ("CALL", "STATICCALL", etc.)
to preserve as_str/Display behavior, keep the existing #[serde(rename = "...")]
attributes, remove the manual as_str() and the std::fmt::Display impl, and
simplify from_parity_call_type to parse the parity string (e.g.,
call_type.parse().unwrap_or(Self::Call)) or map via EnumString serializations
for lowercase parity inputs using appropriate #[strum(serialize = "staticcall")]
entries on the matching variants; update any callers accordingly.

In `@src/rpc/methods/eth/trace/utils.rs`:
- Around line 11-26: Add concise Rust doc comments to each public helper:
trace_to_address, extract_revert_reason, and u256_to_eth_hash. For
trace_to_address describe what address is derived (delegated_address preferred,
fallback to ActorID via from_actor_id) and any edge cases (when
delegated_address is absent or conversion fails). For extract_revert_reason
document the expected input (EthBytes from a reverted transaction), what
parse_eth_revert returns, and that it returns None or Some(String) only when the
parsed reason does not start with "0x" (i.e., non-hex reasons). For
u256_to_eth_hash state that it converts a U256 into an EthHash by writing
big-endian bytes into an ethereum_types::H256 and note any assumptions about
byte ordering and fixed-size padding. Keep each comment short, use /// doc
comment style, and place them immediately above the respective function
definitions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a4153233-bbd4-42d7-bc3e-632757f9ac1b

📥 Commits

Reviewing files that changed from the base of the PR and between f0ac8db and 38cb7df.

⛔ Files ignored due to path filters (2)
  • src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap is excluded by !**/*.snap
  • src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap is excluded by !**/*.snap
📒 Files selected for processing (15)
  • docs/docs/developers/guides/debug_trace_transaction_guide.md
  • docs/docs/users/knowledge_base/rpc/debug_trace_transaction.md
  • src/interpreter/vm.rs
  • src/rpc/methods/eth.rs
  • src/rpc/methods/eth/trace/geth.rs
  • src/rpc/methods/eth/trace/mod.rs
  • src/rpc/methods/eth/trace/parity.rs
  • src/rpc/methods/eth/trace/state_diff.rs
  • src/rpc/methods/eth/trace/test_helpers.rs
  • src/rpc/methods/eth/trace/types.rs
  • src/rpc/methods/eth/trace/utils.rs
  • src/rpc/methods/eth/utils.rs
  • src/rpc/mod.rs
  • src/state_manager/mod.rs
  • src/tool/subcommands/api_cmd/test_snapshots_ignored.txt

Comment thread docs/docs/developers/guides/debug_trace_transaction_guide.md
Comment thread docs/docs/users/knowledge_base/rpc/debug_trace_transaction.md
Comment thread src/interpreter/vm.rs
Comment thread src/rpc/methods/eth/trace/geth.rs Outdated
Comment thread src/rpc/methods/eth/trace/geth.rs Outdated
Comment thread src/rpc/methods/eth/trace/geth.rs Outdated
Comment thread src/rpc/methods/eth/trace/types.rs
Comment thread src/state_manager/mod.rs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 17, 2026

Codecov Report

❌ Patch coverage is 72.39933% with 329 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.70%. Comparing base (7868455) to head (abf8a12).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/rpc/methods/eth.rs 0.93% 106 Missing ⚠️
src/state_manager/mod.rs 0.00% 83 Missing ⚠️
src/rpc/methods/eth/trace/geth.rs 81.18% 58 Missing and 12 partials ⚠️
src/rpc/methods/eth/trace/types.rs 90.28% 39 Missing and 2 partials ⚠️
src/rpc/methods/eth/trace/test_helpers.rs 85.71% 1 Missing and 15 partials ⚠️
src/rpc/methods/eth/trace/state_diff.rs 76.19% 8 Missing and 2 partials ⚠️
src/rpc/methods/eth/trace/mod.rs 81.81% 0 Missing and 2 partials ⚠️
src/rpc/methods/eth/trace/parity.rs 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/interpreter/vm.rs 81.51% <100.00%> (ø)
src/rpc/methods/eth/trace/utils.rs 100.00% <100.00%> (ø)
src/rpc/methods/eth/utils.rs 87.75% <100.00%> (ø)
src/rpc/mod.rs 89.20% <ø> (ø)
src/rpc/methods/eth/trace/parity.rs 65.21% <50.00%> (-1.18%) ⬇️
src/rpc/methods/eth/trace/mod.rs 81.81% <81.81%> (ø)
src/rpc/methods/eth/trace/state_diff.rs 80.74% <76.19%> (-0.94%) ⬇️
src/rpc/methods/eth/trace/test_helpers.rs 85.71% <85.71%> (ø)
src/rpc/methods/eth/trace/types.rs 90.66% <90.28%> (-1.19%) ⬇️
src/rpc/methods/eth/trace/geth.rs 81.18% <81.18%> (ø)
... and 2 more

... and 5 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7868455...abf8a12. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/rpc/methods/eth/trace/parity.rs
Comment thread src/rpc/methods/eth/trace/geth.rs
Comment thread src/rpc/methods/eth/trace/geth.rs
Comment thread src/state_manager/mod.rs Outdated
Comment thread src/state_manager/mod.rs Outdated
Comment thread src/rpc/methods/eth.rs Outdated
Comment thread src/rpc/methods/eth/trace/utils.rs
Comment thread src/rpc/methods/eth/trace/types.rs
Comment thread docs/docs/developers/guides/debug_trace_transaction_guide.md
Copy link
Copy Markdown
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/rpc/methods/eth/trace/state_diff.rs (1)

206-243: ⚠️ Potential issue | 🟠 Major

Don’t silently convert storage read failures into empty diffs.

Returning HashMap::default() on KAMT/state load errors can hide real failures and emit incorrect debug_traceTransaction state diffs.

Suggested direction
+use anyhow::Context as _;
 
-pub fn extract_evm_storage_entries<DB: Blockstore>(
+pub fn extract_evm_storage_entries<DB: Blockstore>(
     store: &DB,
     actor: Option<&ActorState>,
-) -> HashMap<[u8; 32], U256> {
+) -> anyhow::Result<HashMap<[u8; 32], U256>> {
     let actor = match actor {
         Some(a) if is_evm_actor(&a.code) => a,
-        _ => return HashMap::default(),
+        _ => return Ok(HashMap::default()),
     };
 
-    let evm_state = match evm::State::load(store, actor.code, actor.state) {
-        Ok(state) => state,
-        Err(e) => {
-            debug!("failed to load EVM state for storage extraction: {e}");
-            return HashMap::default();
-        }
-    };
+    let evm_state = evm::State::load(store, actor.code, actor.state)
+        .context("failed to load EVM state for storage extraction")?;
 
     let storage_cid = evm_state.contract_state();
     let config = evm_kamt_config();
 
-    let kamt: EvmStorageKamt<&DB> = match Kamt::load_with_config(&storage_cid, store, config) {
-        Ok(k) => k,
-        Err(e) => {
-            debug!("failed to load storage KAMT: {e}");
-            return HashMap::default();
-        }
-    };
+    let kamt: EvmStorageKamt<&DB> = Kamt::load_with_config(&storage_cid, store, config)
+        .context("failed to load storage KAMT")?;
 
     let mut entries = HashMap::default();
-    if let Err(e) = kamt.for_each(|key, value| {
+    kamt.for_each(|key, value| {
         entries.insert(key.to_big_endian(), *value);
         Ok(())
-    }) {
-        debug!("failed to iterate storage KAMT: {e}");
-        return HashMap::default();
-    }
+    })
+    .context("failed to iterate storage KAMT")?;
 
-    entries
+    Ok(entries)
 }

As per coding guidelines: “Use anyhow::Result<T> for most operations and add context with .context() when errors occur”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/state_diff.rs` around lines 206 - 243, The function
extract_evm_storage_entries currently swallows errors from evm::State::load,
Kamt::load_with_config and kamt.for_each and returns an empty HashMap; change
its signature to return anyhow::Result<HashMap<[u8; 32], U256>> and propagate
errors instead of returning HashMap::default(), adding context() on failures
(e.g. on evm::State::load, Kamt::load_with_config and kamt.for_each) to provide
meaningful messages; update callers to handle the Result and stop converting
real storage/load/iterate failures into silent empty diffs; keep the same
key/value extraction logic but return Ok(entries) on success.
src/rpc/methods/eth/trace/parity.rs (1)

43-48: ⚠️ Potential issue | 🟡 Minor

The new rustdoc describes the opposite of the Lotus-parity guard.

This predicate intentionally returns true for more than just EVM/EAM invocations, so the current comment will mislead anyone treating it as a contract. Please document the parity quirk explicitly instead of describing the idealized behavior.

Based on learnings, "In Forest's trace_is_evm_or_eam() helper in src/rpc/methods/eth/trace/parity.rs, the current guard (invoked_actor.id != ETHEREUM_ACCOUNT_MANAGER_ACTOR) intentionally mirrors Lotus behavior even though it can return true for non-EVM actors."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/parity.rs` around lines 43 - 48, Update the rustdoc
for trace_is_evm_or_eam to explicitly state it mirrors the Lotus/Parity guard
and can return true for non-EVM actors (i.e., it is intentionally permissive),
rather than describing an idealized “EVM or EAM only” predicate. Mention the
parity quirk and the exact check used (the
is_evm_actor(&invoked_actor.state.code) || invoked_actor.id !=
Address::ETHEREUM_ACCOUNT_MANAGER_ACTOR.id().unwrap() condition) so readers know
the != ETHEREUM_ACCOUNT_MANAGER_ACTOR branch is deliberate and may cause non-EVM
traces to be treated as true.
♻️ Duplicate comments (1)
src/state_manager/mod.rs (1)

907-913: ⚠️ Potential issue | 🟠 Major

Avoid persisting trace-only pre/post roots into the canonical blockstore.

At Line 908 and Line 912, flush() runs on VMs created by TipsetExecutor::create_vm, which is backed by self.chain_index.db() (Line 2002). That persists per-request intermediate roots for a read RPC, and repeated tracing can grow node storage unnecessarily. Please execute this pre/post replay on an overlay/in-memory blockstore and discard it after building the response.

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

Inline comments:
In `@docs/docs/developers/guides/debug_trace_transaction_guide.md`:
- Line 120: Add an inline gitleaks allow marker to the known Anvil test private
key export so scanners won't flag it; edit the line that defines the ANVIL_KEY
export (the line containing export ANVIL_KEY="0xac0974...f2ff80") and append the
comment marker `#gitleaks`:allow on the same line to explicitly permit this
test-only key.

In `@src/rpc/methods/eth/trace/types.rs`:
- Around line 459-485: The current construction of GethCallFrame sets output
using (!result.output.is_empty()).then_some(...) which collapses a successful
empty return into None; update the logic in the GethCallFrame creation (the
output field) to always set Some(result.output.clone()) for successful
calls/creates (even when empty) and only set output = None when the trace
actually failed (the existing !is_success branch should clear the output on
failure). Do the analogous change for create frames that use result.code so
successful empty code remains Some(EthBytes::default()) and only clear on
failure; locate the output/code assignments near the GethCallFrame creation and
the later !is_success handling and adjust them accordingly.

---

Outside diff comments:
In `@src/rpc/methods/eth/trace/parity.rs`:
- Around line 43-48: Update the rustdoc for trace_is_evm_or_eam to explicitly
state it mirrors the Lotus/Parity guard and can return true for non-EVM actors
(i.e., it is intentionally permissive), rather than describing an idealized “EVM
or EAM only” predicate. Mention the parity quirk and the exact check used (the
is_evm_actor(&invoked_actor.state.code) || invoked_actor.id !=
Address::ETHEREUM_ACCOUNT_MANAGER_ACTOR.id().unwrap() condition) so readers know
the != ETHEREUM_ACCOUNT_MANAGER_ACTOR branch is deliberate and may cause non-EVM
traces to be treated as true.

In `@src/rpc/methods/eth/trace/state_diff.rs`:
- Around line 206-243: The function extract_evm_storage_entries currently
swallows errors from evm::State::load, Kamt::load_with_config and kamt.for_each
and returns an empty HashMap; change its signature to return
anyhow::Result<HashMap<[u8; 32], U256>> and propagate errors instead of
returning HashMap::default(), adding context() on failures (e.g. on
evm::State::load, Kamt::load_with_config and kamt.for_each) to provide
meaningful messages; update callers to handle the Result and stop converting
real storage/load/iterate failures into silent empty diffs; keep the same
key/value extraction logic but return Ok(entries) on success.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 239365ef-26eb-4e64-a9ac-e2c2b84bc4dd

📥 Commits

Reviewing files that changed from the base of the PR and between 38cb7df and c4da3ee.

⛔ Files ignored due to path filters (2)
  • src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap is excluded by !**/*.snap
  • src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap is excluded by !**/*.snap
📒 Files selected for processing (15)
  • docs/docs/developers/guides/debug_trace_transaction_guide.md
  • docs/docs/users/knowledge_base/rpc/debug_trace_transaction.md
  • src/interpreter/vm.rs
  • src/rpc/methods/eth.rs
  • src/rpc/methods/eth/trace/geth.rs
  • src/rpc/methods/eth/trace/mod.rs
  • src/rpc/methods/eth/trace/parity.rs
  • src/rpc/methods/eth/trace/state_diff.rs
  • src/rpc/methods/eth/trace/test_helpers.rs
  • src/rpc/methods/eth/trace/types.rs
  • src/rpc/methods/eth/trace/utils.rs
  • src/rpc/methods/eth/utils.rs
  • src/rpc/mod.rs
  • src/state_manager/mod.rs
  • src/tool/subcommands/api_cmd/test_snapshots_ignored.txt
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/interpreter/vm.rs
  • src/rpc/methods/eth/trace/mod.rs
  • src/rpc/methods/eth/trace/test_helpers.rs
  • docs/docs/users/knowledge_base/rpc/debug_trace_transaction.md

Comment thread docs/docs/developers/guides/debug_trace_transaction_guide.md
Comment thread src/rpc/methods/eth/trace/types.rs
Comment thread src/rpc/methods/eth/trace/types.rs Outdated
hanabi1224
hanabi1224 previously approved these changes Mar 23, 2026
Copy link
Copy Markdown
Contributor

@hanabi1224 hanabi1224 left a comment

Choose a reason for hiding this comment

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

Some NITs, otherwise LGTM.

Copy link
Copy Markdown
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: 3

♻️ Duplicate comments (1)
src/state_manager/mod.rs (1)

907-912: ⚠️ Potential issue | 🟠 Major

Keep pre/post replay roots out of the shared blockstore.

Line 908 and Line 912 create roots that debug_trace_transaction later reopens from ctx.store_owned(), so this read RPC is persisting non-canonical intermediate states into the node DB. Repeated traces can grow durable state indefinitely. Please run this replay on a temporary/overlay store and load the pre/post StateTrees from that store instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/state_manager/mod.rs` around lines 907 - 912, The current replay writes
intermediate pre/post roots into the shared node DB because vm.flush() and
traced_vm.flush() persist to the default store, so change the replay to use a
temporary/overlay blockstore instead: create an ephemeral in-memory or overlay
store and pass it into exec.create_vm(...) (and any VM construction that
currently uses ctx.store_owned()), call vm.flush() and traced_vm.flush() against
that temp store so pre_root/post_root are created there, and then load the
pre/post StateTree from that temporary store when debug_trace_transaction
reopens them (avoid calling ctx.store_owned() for these roots). Ensure you
reference vm.flush(), exec.create_vm, traced_vm.flush(), debug_trace_transaction
and StateTree to locate and update the VM creation and flush paths.
🧹 Nitpick comments (1)
src/rpc/methods/eth/trace/types.rs (1)

176-188: Add rustdoc to the new public helper methods.

These helpers extend the exported tracer/RPC surface, but several of them are still undocumented (PreStateConfig::is_*, GethCallType::as_str / is_static_call, AccountState::is_empty, EthTrace::is_success, StateDiff::new). Please document them before this API solidifies.

As per coding guidelines, "Document public functions and structs with doc comments".

Also applies to: 215-228, 308-313, 426-428, 719-722

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/trace/types.rs` around lines 176 - 188, Add Rustdoc
comments to the new public helper methods so the exported tracer/RPC API is
documented: add concise triple-slash (///) docs above
PreStateConfig::is_diff_mode, PreStateConfig::is_code_disabled,
PreStateConfig::is_storage_disabled and likewise for GethCallType::as_str,
GethCallType::is_static_call, AccountState::is_empty, EthTrace::is_success, and
StateDiff::new that explain what the method does, any important semantics or
edge cases, and what the return value represents; keep descriptions short, use
imperative style and mention if the method is a convenience wrapper (e.g.,
unwrap_or default), and include examples or panics only if relevant.
🤖 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/trace/types.rs`:
- Around line 489-514: In the TraceAction::Create / TraceResult::Create arm
(inside into_geth_frame), detect the invalid case where is_success is true but
result.address is None and bail early instead of building a success-shaped
GethCallFrame; return an error (e.g., a TraceError::InvalidTrace or similar
existing error variant) when is_success && result.address.is_none() so
successful CREATE traces always include a deployed address before constructing
the GethCallFrame.
- Around line 116-121: call_config currently rejects CallTracerConfig when
with_log is true; update the handling so the error is explicit and actionable:
in call_config (using parse_tracer_config::<CallTracerConfig> and the
CallTracerConfig.with_log field) replace the generic anyhow::bail!("callTracer:
withLog is not yet supported") with an error that names the unsupported option
and points callers to the public docs/CHANGELOG entry (or a link/marker)
explaining the incompatibility, and ensure the repository's
documentation/release notes are updated to declare that Forest's callTracer does
not support withLog (unless you instead implement with_log handling here and the
associated log-collection behavior).
- Around line 338-360: Remove deserialization support for the response-only
GethTrace enum by deleting the Deserialize derive from the GethTrace declaration
(leave Serialize) and removing any lotus_json_with_self! invocation that
registers GethTrace for deserialization; keep PreStateFrame and other types
unchanged but ensure GethTrace remains #[derive(PartialEq, Debug, Clone,
Serialize, JsonSchema)] and untagged so it only serializes. This eliminates the
unreachable Noop variant during deserialization while preserving response
serialization for debug_trace_transaction.

---

Duplicate comments:
In `@src/state_manager/mod.rs`:
- Around line 907-912: The current replay writes intermediate pre/post roots
into the shared node DB because vm.flush() and traced_vm.flush() persist to the
default store, so change the replay to use a temporary/overlay blockstore
instead: create an ephemeral in-memory or overlay store and pass it into
exec.create_vm(...) (and any VM construction that currently uses
ctx.store_owned()), call vm.flush() and traced_vm.flush() against that temp
store so pre_root/post_root are created there, and then load the pre/post
StateTree from that temporary store when debug_trace_transaction reopens them
(avoid calling ctx.store_owned() for these roots). Ensure you reference
vm.flush(), exec.create_vm, traced_vm.flush(), debug_trace_transaction and
StateTree to locate and update the VM creation and flush paths.

---

Nitpick comments:
In `@src/rpc/methods/eth/trace/types.rs`:
- Around line 176-188: Add Rustdoc comments to the new public helper methods so
the exported tracer/RPC API is documented: add concise triple-slash (///) docs
above PreStateConfig::is_diff_mode, PreStateConfig::is_code_disabled,
PreStateConfig::is_storage_disabled and likewise for GethCallType::as_str,
GethCallType::is_static_call, AccountState::is_empty, EthTrace::is_success, and
StateDiff::new that explain what the method does, any important semantics or
edge cases, and what the return value represents; keep descriptions short, use
imperative style and mention if the method is a convenience wrapper (e.g.,
unwrap_or default), and include examples or panics only if relevant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cc16da0e-cb17-45b3-a190-c987a903247d

📥 Commits

Reviewing files that changed from the base of the PR and between c4da3ee and 33323c2.

📒 Files selected for processing (3)
  • src/rpc/methods/eth.rs
  • src/rpc/methods/eth/trace/types.rs
  • src/state_manager/mod.rs

Comment thread src/rpc/methods/eth/trace/types.rs
Comment thread src/rpc/methods/eth/trace/types.rs
Comment thread src/rpc/methods/eth/trace/types.rs
Copy link
Copy Markdown
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)

3493-3495: Consider using invalid_params for "transaction not found".

The error "transaction not found" typically indicates invalid client input (non-existent hash) rather than an internal server error. However, I note that EthTraceTransaction::handle (line 3757) uses the same internal_error pattern, so this is consistent with existing code.

💡 Optional: Use invalid_params for consistency with RPC semantics
     let eth_txn = get_eth_transaction_by_hash(&ctx, &eth_hash, None)
         .await?
-        .ok_or(ServerError::internal_error("transaction not found", None))?;
+        .ok_or(ServerError::invalid_params("transaction not found", None))?;

If you adopt this change, consider applying it to EthTraceTransaction::handle as well for consistency.

🤖 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 3493 - 3495, Replace the
ServerError::internal_error used when get_eth_transaction_by_hash returns None
with ServerError::invalid_params("transaction not found", None) to reflect that
a missing transaction is a client/input error; update the expression that
constructs eth_txn (the call to get_eth_transaction_by_hash and its .ok_or(...)?
chain) to return invalid_params instead of internal_error, and consider making
the same change in EthTraceTransaction::handle to keep RPC error semantics
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/rpc/methods/eth.rs`:
- Around line 3493-3495: Replace the ServerError::internal_error used when
get_eth_transaction_by_hash returns None with
ServerError::invalid_params("transaction not found", None) to reflect that a
missing transaction is a client/input error; update the expression that
constructs eth_txn (the call to get_eth_transaction_by_hash and its .ok_or(...)?
chain) to return invalid_params instead of internal_error, and consider making
the same change in EthTraceTransaction::handle to keep RPC error semantics
consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 77e5f559-119b-44c1-8c53-715fdd5afaf2

📥 Commits

Reviewing files that changed from the base of the PR and between 0ed900d and abf8a12.

📒 Files selected for processing (4)
  • src/interpreter/vm.rs
  • src/rpc/methods/eth.rs
  • src/rpc/mod.rs
  • src/state_manager/mod.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/interpreter/vm.rs
  • src/state_manager/mod.rs

@akaladarshi akaladarshi added this pull request to the merge queue Mar 25, 2026
Merged via the queue into main with commit 4539320 Mar 25, 2026
47 checks passed
@akaladarshi akaladarshi deleted the akaladarshi/debug-trace-txn branch March 25, 2026 13:10
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 debug_traceTransaction API

3 participants