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
@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
@grandizzy grandizzy force-pushed the yash/forge-backtraces branch from 6d198eb to c51d151 Compare September 15, 2025 03:41
…y + avoid cloning (#11648)

* defer source data collection + collect only required sources

* rm artifact_ids from BacktraceBuilder

* rm ast from SourceData

* avoid source data cloning

* defer BacktraceBuilder instatiation only in case of failure + pass required fields from config

* nit

* fix: oom due to TraceMode::Debug being set on verbosity >= 3

* fix backtrace tests - removal of internal lib detection

* fix

* fix: can_run_test_with_json_output_verbose

* fix: ext tests by setting verbosity for forge-std and sablier

* verbosity

* minify

* fix
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