Skip to content

Conversation

yash-atreya
Copy link
Member

@yash-atreya yash-atreya commented Sep 4, 2025

Motivation

Closes #2328

Forge lacks backtraces, which are useful for pinpointing the line where the revert/error originated in the call stack. This is especially useful when there are multiple nested calls between different contracts, making traces hard to follow. Backtraces help you easily "goto" the line throwing the error.

Solution

  • Introduce backtrace support in forge test
  • Backtraces are enabled when verbosity >= 3 and printed if there is a revert
  • When verbosity >= 3, we collect the source maps, deployed bytecode, and source content using the BacktraceBuilder.
  • In case a test fails, extract the backtraces using from the trace arena using BacktraceBuilder::from_trace(arena); thebytecode.pc (program counter) is mapped to the instruction pointer and then source maps are used to pinpoint the source locations in the call stack.
  • Each call is stored as a BacktraceFrame containing the source location of the call along with the contract and function names.

Implementation can be tested using:

Followup

  • Internal calls and libraries using solar after feat(cheats): sorted JSON params #11612. See:
    // Initialize and configure the solar compiler.
    let mut analysis = solar::sema::Compiler::new(
    solar::interface::Session::builder().with_stderr_emitter().build(),
    );
    let dcx = analysis.dcx_mut();
    dcx.set_emitter(Box::new(
    solar::interface::diagnostics::HumanEmitter::stderr(Default::default())
    .source_map(Some(dcx.source_map().unwrap().clone())),
    ));
    dcx.set_flags_mut(|f| f.track_diagnostics = false);
    // Populate solar's global context by parsing and lowering the sources.
    analysis.enter_mut(|compiler| -> Result<()> {
    let mut pcx = compiler.parse();
    configure_pcx(&mut pcx, &config, Some(&project), Some(&analysis_files))?;
    pcx.parse();
    let _ = compiler.lower_asts();
    Ok(())
    })?;

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

@yash-atreya yash-atreya self-assigned this Sep 4, 2025
@yash-atreya yash-atreya added A-testing Area: testing Cmd-forge-test Command: forge test C-forge Command: forge labels Sep 4, 2025
@yash-atreya yash-atreya moved this to In Progress in Foundry Sep 4, 2025
@yash-atreya yash-atreya added the T-feature Type: feature label Sep 4, 2025
Comment on lines +390 to +393
if self.evm_opts.verbosity >= 3 && (mode == TraceMode::Call || mode == TraceMode::None) {
mode = TraceMode::Debug;
}
mode
Copy link
Member Author

Choose a reason for hiding this comment

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

TraceMode set to Debug for steps tracing when verbosity >= 3

@yash-atreya yash-atreya marked this pull request as ready for review September 12, 2025 12:33
@yash-atreya yash-atreya moved this from In Progress to Ready For Review in Foundry Sep 12, 2025
@grandizzy grandizzy force-pushed the yash/forge-backtraces branch from 1b1c2b7 to 6d198eb Compare September 12, 2025 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-testing Area: testing C-forge Command: forge Cmd-forge-test Command: forge test T-feature Type: feature
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

feat: extend (error) traces to include source code line number and filename
2 participants