Skip to content

Conversation

@bogdan-alexandrescu
Copy link

@bogdan-alexandrescu bogdan-alexandrescu commented Nov 13, 2025

Motivation

When testing smart contracts against Cosmos-EVM compatible chains (such as Evmos, Injective, SagaEVM, and others), developers encounter a critical limitation: local REVM-based tracing cannot accurately reproduce the chain's execution behavior, especially when dealing with chain-specific precompiles and custom EVM implementations.

The problem manifests in several ways:

  1. Precompile Behavior Mismatch: Cosmos-EVM chains often implement custom precompiles (e.g., ERC20 precompiles at fixed addresses) that behave differently than standard Ethereum precompiles. Local REVM tracing cannot execute these precompiles, leading to incorrect trace outputs and missed execution paths.

  2. Chain-Specific Execution Differences: Different EVM implementations may have subtle differences in gas accounting, opcode behavior, or state transitions that are not captured by local tracing. This makes it difficult to debug issues that only occur on the actual chain.

  3. Inability to Verify Chain Behavior: Developers need a way to verify that their contracts execute correctly on the target chain's actual node implementation, not just a local simulation.

  4. Debugging Challenges: When tests pass locally but fail on-chain, developers lack visibility into the actual execution trace from the chain node, making debugging significantly more difficult.

The existing --fork-url feature allows testing against remote chains, but tracing was still performed locally using REVM, which doesn't capture the chain's actual execution behavior. This PR adds the --trace-source remote flag to enable remote tracing via the node's debug_traceCall RPC method, providing accurate execution traces that reflect the chain's actual behavior.

Solution

This PR adds a new CLI flag --trace-source to forge test that allows developers to choose between local REVM-based tracing (default) and remote tracing via the chain node's debug_traceCall method.

Implementation Details

  1. CLI Flag Addition: Added --trace-source flag to forge test with two options:

    • local (default): Uses REVM for local tracing (existing behavior)
    • remote: Delegates tracing to the remote RPC node via debug_traceCall
  2. Configuration Support: The trace source can be configured via:

    • CLI flag: --trace-source remote
    • foundry.toml: trace_source = "remote"
  3. Remote Tracing Implementation:

    • When --trace-source remote is specified, Forge constructs a TransactionRequest from the local trace
    • Calls the remote node's debug_traceCall method with callTracer configuration
    • Renders the remote trace as a compact nested call tree showing gas usage
    • Only applies to Execution traces (Setup/Deployment traces remain local)
  4. Integration with Fork Mode: Remote tracing requires --fork-url to be specified, as it needs an RPC endpoint to call. The implementation checks for config.eth_rpc_url before attempting remote tracing.

  5. Trace Rendering: Remote traces are rendered using a minimal call tree format:

    CALL 0x...from -> 0x...to gasUsed=24567
      CALL 0x... -> 0x... gasUsed=3245
        CALL 0x... -> 0x... gasUsed=410
    
  6. Error Handling: The implementation gracefully falls back to local tracing if remote tracing fails (e.g., if the RPC doesn't support debug_traceCall or returns an error).

Code Changes

  • crates/forge/src/cmd/test/mod.rs:

    • Added trace_source: Option<TraceSourceArg> field to TestArgs
    • Added TraceSourceArg enum with Local and Remote variants
    • Implemented remote tracing logic in run_tests_inner() that checks for TraceSource::Remote and fetches traces via debug_traceCall
    • Added render_remote_call_frame() function to format remote trace output
    • Integrated trace source configuration into the config provider
  • crates/config/src/lib.rs:

    • Added TraceSource enum with Local (default) and Remote variants
    • Added trace_source: TraceSource field to Config struct
  • crates/forge/tests/remote_trace.rs:

    • Added test debug_trace_call_parses_calltracer() to verify remote tracing RPC integration
  • crates/forge/src/cmd/test/mod.rs (tests):

    • Added trace_source_arg_remote_parses() test to verify CLI flag parsing and config integration
  • docs/dev/forge-tracing.md:

    • Added comprehensive documentation for remote tracing feature, including usage examples, requirements, limitations, and troubleshooting

Usage Example

# Test with remote tracing against a Cosmos-EVM chain
forge test \
  --fork-url https://sagaevm.jsonrpc.sagarpc.io \
  --trace-source remote \
  -vvvv

Or configure in foundry.toml:

[profile.default]
trace_source = "remote"

Benefits

  1. Accurate Chain Behavior: Traces reflect the actual execution behavior of the target chain, including precompiles and custom EVM implementations
  2. Better Debugging: Developers can see exactly how their contracts execute on-chain, making it easier to debug chain-specific issues
  3. Precompile Support: Enables accurate tracing of Cosmos-EVM precompiles that don't exist in standard Ethereum
  4. Backward Compatible: Default behavior remains unchanged (local tracing), ensuring no breaking changes
  5. Flexible Configuration: Can be set via CLI flag or config file, providing flexibility for different workflows

Limitations

  • Remote tracing currently only fetches Execution traces (not Setup/Deployment traces)
  • Uses built-in callTracer only; other tracers like prestateTracer are not yet exposed
  • Remote traces use minimal rendering (no ABI decoding or labels) compared to local traces
  • Requires RPC endpoint to support debug_ namespace methods
  • Slightly slower than local tracing due to RPC calls

PR Checklist

  • Added Tests

    • Added trace_source_arg_remote_parses() test in crates/forge/src/cmd/test/mod.rs to verify CLI flag parsing
    • Added debug_trace_call_parses_calltracer() test in crates/forge/tests/remote_trace.rs to verify RPC integration
  • Added Documentation

    • Added comprehensive documentation in docs/dev/forge-tracing.md covering:
      • Feature overview and use cases
      • CLI usage examples
      • Configuration options
      • Requirements and limitations
      • Troubleshooting guide
      • Example workflows
  • Breaking changes

    • No breaking changes. The feature is opt-in via --trace-source remote flag, and defaults to local (existing behavior).

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

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant