Skip to content

feat: add backwards compatibility for Response::traces#1301

Open
Wodann wants to merge 4 commits intomainfrom
feat/tracing-back-compat
Open

feat: add backwards compatibility for Response::traces#1301
Wodann wants to merge 4 commits intomainfrom
feat/tracing-back-compat

Conversation

@Wodann
Copy link
Copy Markdown
Member

@Wodann Wodann commented Feb 19, 2026

Resolves #1288.

This reintroduces the Response::traces getter function to maintain support for Hardhat 2's EthereumJS VM interface.

I tested this using the help of Claude:

Hardhat Plugin Compatibility Report — EDR Tracing Back-Compat

Date: 2026-02-20
EDR branch: feat/tracing-back-compat
Hardhat branch: hh2/tracing-unification

Overview

This report validates that the new EDR trace format (unified tracing architecture)
is backward-compatible with the existing Hardhat v2 plugin ecosystem. Testing was
performed at three levels:

  1. Plugin test suites — each plugin's own tests run against local Hardhat+EDR
  2. Third-party project tests — real-world projects using stock plugins
  3. Third-party projects with linked plugins — full local stack (EDR + Hardhat + plugins)

Critical Finding: includeCallTraces Default

During testing, solidity-coverage's test suite revealed that Response::traces()
returned empty arrays because include_call_traces defaults to IncludeTraces::None
in the new architecture. This was fixed in Hardhat commit c46cf5b by setting
includeCallTraces: IncludeTraces.All in the provider's observability config.

Plugin Test Suite Results

hardhat-gas-reporter v2.3.0

Category Pass Fail Notes
Unit tests 16 5 Failures: missing API keys (CMC/Etherscan)
Integration tests 30 7 Failures: missing API keys + Alchemy token

Trace-format failures: 0. All gas measurement and reporting functionality works.

solidity-coverage v0.8.17

Category Pass Fail Notes
Unit tests (before fix) 60 75 All failures: 0% coverage
Unit tests (after fix) 135 0 All recovered
Integration tests (before fix) 19 23 All failures: 0% coverage
Integration tests (after fix) 41 1 1 pre-existing (block gas limit)

Trace-format failures after fix: 0.

hardhat-tracer v3.4.0

Category Pass Fail Notes
Tests 9 4 Failures: 2 missing Alchemy key, 2 stdin bug

Trace-format failures: 0. All trace-exercising tests pass (CALLs, STATICCALLs,
DELEGATECALLs, opcodes, debug_traceTransaction).

Third-Party Project Results (with linked plugins)

Seaport (best result — full validation)

Mode Pass Fail Extra
Tests 402 0 --
Gas Reporter 402 0 Real gas data (e.g., ConduitController.createConduit avg 223,418)
Coverage 402 0 13.79% stmts overall; 95% for zones

OpenZeppelin Contracts v5.5.0

Mode Pass Fail Extra
Tests (ERC20) 126 0 --
Gas Reporter 126 0 Real gas data (approve avg 44,656; transfer avg 40,133)
Coverage -- -- Compilation fails (instrumentation bloat, not trace-related)

NexusMutual

Mode Pass Fail Extra
Tests 0 2 Gas cap issue (30M > 16.7M cap)
Gas Reporter 0 2 Same gas cap issue
Coverage 2 0 Non-zero data (Pool.sol: 29.77% stmts)

Additional projects tested (stock plugins, local Hardhat+EDR)

Project Tests Gas Reporter Coverage Trace Errors
Rocket Pool Subset pass Works Works None
Synthetix 99/99 pass Works N/A None
Safe Contracts 0/58 (gas cap) N/A N/A None

Non-Trace Issues Found

  1. EIP-7825 gas cap (Safe, NexusMutual): Transactions exceeding 16,777,216 gas
    fail. This is a hardfork behavioral change, not a trace issue.
  2. Synthetix function overloading: Pre-existing EDR limitation. Unrelated to traces.
  3. OpenZeppelin coverage compilation: solidity-coverage instrumentation bloat
    causes compilation failure on the full OZ codebase. Not trace-related.

Risk Assessment

Risk of trace format changes breaking existing Hardhat plugins: LOW

With the includeCallTraces: IncludeTraces.All fix in place, the backward-compatibility
layer in EDR (Response::traces()) combined with the Hardhat adapter successfully
preserves the expected trace format for all tested plugins:

  • hardhat-gas-reporter: Fully functional
  • solidity-coverage: Fully functional (after fix)
  • hardhat-tracer: Fully functional

@Wodann Wodann requested a review from Copilot February 19, 2026 17:54
@Wodann Wodann self-assigned this Feb 19, 2026
@Wodann Wodann had a problem deploying to github-action-benchmark February 19, 2026 17:54 — with GitHub Actions Error
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 19, 2026

🦋 Changeset detected

Latest commit: 369dc66

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@nomicfoundation/edr Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR reintroduces backwards compatibility for the Response::traces getter to support Hardhat 2's EthereumJS VM interface. The implementation converts the new CallTraceArena format back to the flat trace format that Hardhat 2 expects.

Changes:

  • Adds Response::traces() method that converts CallTraceArena to flat trace format compatible with Hardhat 2
  • Removes edr_tracing dependency from multiple crates
  • Deletes nested_tracer.rs and related code that are no longer needed
  • Re-enables verbose tracing tests for Hardhat 2 compatibility

Reviewed changes

Copilot reviewed 22 out of 25 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/edr_napi/src/trace.rs Implements conversion from CallTraceArena to flat trace format with Hardhat 2 compatibility quirks
crates/edr_napi/src/provider/response.rs Adds traces() method to Response
crates/edr_provider/src/observability.rs Updates tracing configuration to capture full stack snapshots
patches/hardhat@2.28.4.patch Updates Hardhat 2 integration to use new trace format
crates/edr_napi/test/provider.ts Re-enables verbose tracing tests
Multiple Cargo.toml files Removes edr_tracing dependency
crates/edr_solidity/src/nested_tracer.rs Deleted - no longer needed
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/edr_napi/src/trace.rs Outdated
.get(call_id)
.expect("child index should be valid");

if matches!(step.op, OpCode::CREATE | OpCode::CREATE2) || !should_skip_call(trace) {
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The should_skip_call function is called with the wrong trace parameter. On line 230, it's called with trace (the parent trace), but it should be called with node.trace (the child trace) to check whether the child call should be skipped.

The function checks if a call has no steps and immediately reverts, which is a property of the child trace, not the parent trace.

Suggested change
if matches!(step.op, OpCode::CREATE | OpCode::CREATE2) || !should_skip_call(trace) {
if matches!(step.op, OpCode::CREATE | OpCode::CREATE2) || !should_skip_call(&node.trace) {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe this is a correct observation from Copilot.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Addresssed by df5f2c5.

Comment on lines 149 to +154
let tracing_config = if config.verbose_raw_tracing {
TracingInspectorConfig::all()
} else {
TracingInspectorConfig::default_parity().set_steps(true)
TracingInspectorConfig::default_parity()
.set_steps(true)
.set_stack_snapshots(StackSnapshotType::Full)
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The StackSnapshotType::Full configuration is set regardless of verbose mode. This means that the full stack will always be captured in the tracing inspector, even when verbose tracing is disabled.

However, the actual filtering to return only the top of the stack happens in the conversion function raw_trace_from_call_trace_arena based on the verbose parameter. This creates an inconsistency where:

  1. The inspector always captures full stack (performance cost)
  2. The conversion then throws away most of the data when verbose=false

Consider setting StackSnapshotType based on verbose_raw_tracing to avoid unnecessary data collection and improve performance.

Copilot uses AI. Check for mistakes.
@Wodann Wodann force-pushed the feat/tracing-back-compat branch from 87edb00 to 041399f Compare February 19, 2026 18:01
@Wodann Wodann temporarily deployed to github-action-benchmark February 19, 2026 18:01 — with GitHub Actions Inactive
@Wodann Wodann had a problem deploying to github-action-benchmark February 19, 2026 18:08 — with GitHub Actions Error
@Wodann Wodann had a problem deploying to github-action-benchmark February 19, 2026 18:08 — with GitHub Actions Error
@Wodann Wodann temporarily deployed to github-action-benchmark February 19, 2026 18:08 — with GitHub Actions Inactive
@Wodann Wodann had a problem deploying to github-action-benchmark February 19, 2026 18:16 — with GitHub Actions Failure
@Wodann Wodann had a problem deploying to github-action-benchmark February 19, 2026 18:16 — with GitHub Actions Failure
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 11.48649% with 131 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.94%. Comparing base (28b7b04) to head (d203b12).

Files with missing lines Patch % Lines
crates/edr_napi/src/trace.rs 0.00% 122 Missing ⚠️
crates/edr_napi/src/provider/response.rs 0.00% 7 Missing ⚠️
crates/edr_napi_core/src/spec.rs 71.42% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1301      +/-   ##
==========================================
+ Coverage   73.72%   73.94%   +0.21%     
==========================================
  Files         445      444       -1     
  Lines       75876    75662     -214     
  Branches    75876    75662     -214     
==========================================
+ Hits        55942    55945       +3     
+ Misses      17882    17666     -216     
+ Partials     2052     2051       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Wodann Wodann requested a review from a team February 20, 2026 19:49
@Wodann Wodann marked this pull request as ready for review February 20, 2026 22:32
Copy link
Copy Markdown
Contributor

@popescuoctavian popescuoctavian left a comment

Choose a reason for hiding this comment

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

Overall looks good, but I believe there is an issue which Copilot pointed out and a small simplification.

Comment thread crates/edr_napi/src/trace.rs Outdated
.get(call_id)
.expect("child index should be valid");

if matches!(step.op, OpCode::CREATE | OpCode::CREATE2) || !should_skip_call(trace) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe this is a correct observation from Copilot.

Comment thread crates/edr_napi/src/trace.rs Outdated
Comment on lines 291 to 298
if trace.steps.is_empty()
&& let Some(status) = trace.status
&& matches!(status, return_revert!())
{
true
} else {
false
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This can be simplified to return the condition

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Addressed by df5f2c5.

@popescuoctavian popescuoctavian temporarily deployed to github-action-benchmark February 23, 2026 14:59 — with GitHub Actions Inactive
@popescuoctavian popescuoctavian temporarily deployed to github-action-benchmark February 23, 2026 15:07 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@popescuoctavian popescuoctavian left a comment

Choose a reason for hiding this comment

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

There is significant performance regression seen in the benchmarks -- up to 2.45x.

I believe this is caused by the inclusion of the full stack snapshot. However, I don't see an immediate solution here, with the existing revm-inspectors tracing code.

@popescuoctavian popescuoctavian temporarily deployed to github-action-benchmark February 23, 2026 19:23 — with GitHub Actions Inactive
@popescuoctavian popescuoctavian temporarily deployed to github-action-benchmark February 23, 2026 19:40 — with GitHub Actions Inactive
@popescuoctavian popescuoctavian temporarily deployed to github-action-benchmark February 23, 2026 19:40 — with GitHub Actions Inactive
@popescuoctavian popescuoctavian temporarily deployed to github-action-benchmark February 23, 2026 20:53 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Re-enable traces for Hardhat 2

3 participants