Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 35 additions & 15 deletions crates/forge/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,22 +891,28 @@ impl<'a, FEN: FoundryEvmNetwork> FunctionRunner<'a, FEN> {
&mut raw_call_result,
false,
);
if success {
self.result.symbolic_result(
false,
Some(
"incomplete symbolic execution (Error): symbolic counterexample did not replay"
.to_string(),
),
None,
stats,
);
self.result.symbolic_portfolio_diagnostics = portfolio_diagnostics;
self.result.symbolic_diagnostics = symbolic_diagnostics;
return self.result;
}

let counterexample = CounterExample::Single(BaseCounterExample::from_fuzz_call(
calldata,
args,
raw_call_result.traces.clone(),
));
self.result.extend(raw_call_result);
self.result.symbolic_result(
false,
if success {
Some("symbolic counterexample did not replay".to_string())
} else {
reason
},
Some(counterexample),
stats,
);
self.result.symbolic_result(false, reason, Some(counterexample), stats);
}
}

Expand Down Expand Up @@ -1028,13 +1034,27 @@ impl<'a, FEN: FoundryEvmNetwork> FunctionRunner<'a, FEN> {
SymbolicInvariantRunResult::Counterexample { sequence, stats } => {
let (replayed, reason, replay_sequence) =
self.replay_symbolic_invariant_sequence(func, &sequence, fail_on_revert);
if !replayed {
let reason = reason.map_or_else(
|| "symbolic invariant counterexample did not replay".to_string(),
|reason| {
format!("symbolic invariant counterexample did not replay: {reason}")
},
);
self.result.symbolic_result(
false,
Some(format!("incomplete symbolic invariant execution (Error): {reason}")),
None,
stats,
);
self.result.symbolic_portfolio_diagnostics = portfolio_diagnostics;
self.result.symbolic_diagnostics = symbolic_diagnostics;
return self.result;
}

self.result.symbolic_result(
false,
if replayed {
reason.or_else(|| Some("symbolic invariant counterexample".to_string()))
} else {
Some("symbolic invariant counterexample did not replay".to_string())
},
reason.or_else(|| Some("symbolic invariant counterexample".to_string())),
Some(CounterExample::Sequence(replay_sequence.len(), replay_sequence)),
stats,
);
Expand Down
12 changes: 7 additions & 5 deletions crates/forge/tests/cli/test_cmd/symbolic_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::symbolic_helpers::assert_relevant_lines;
use foundry_common::sh_eprintln;
use foundry_test_utils::{forgetest_init, str, util::OutputExt};

use super::symbolic_helpers::{assert_symbolic, assert_symbolic_witness, z3_available};
use super::symbolic_helpers::{assert_symbolic, z3_available};
use crate::skip_unless_z3;

forgetest_init!(symbolic_mapping_storage_finds_counterexample, |prj, cmd| {
Expand Down Expand Up @@ -437,8 +437,10 @@ checkSvmArbitraryStorage(address)

// Reading an unwritten mapping at a symbolic key must yield a fresh symbolic
// value, not a concrete zero. The assertion below claims that no caller is an
// admin; because nothing has ever written to `isAdmin`, the solver must still
// be able to satisfy `isAdmin[user] == true` and produce a counterexample.
// admin; because nothing has ever written to `isAdmin`, the solver can satisfy
// `isAdmin[user] == true`. That candidate does not replay concretely from the
// default concrete storage value, so Forge must report Incomplete instead of a
// user-facing counterexample.
forgetest_init!(symbolic_sload_unwritten_mapping_default_layout, |prj, cmd| {
skip_unless_z3!("symbolic_sload_unwritten_mapping_default_layout");

Expand All @@ -455,7 +457,7 @@ contract SymbolicSLoadUnwrittenMapping {
"#,
);

assert_symbolic_witness(cmd.args([
assert_symbolic(cmd.args([
"test",
"--symbolic",
"--match-test",
Expand All @@ -466,7 +468,7 @@ contract SymbolicSLoadUnwrittenMapping {
...
Failing tests:
Encountered 1 failing test in test/SymbolicSLoadUnwrittenMapping.t.sol:SymbolicSLoadUnwrittenMapping
[FAIL: symbolic counterexample did not replay; counterexample: [CALLDATA] [ARGS]] checkNoUserIsAdmin(address) ([METRICS])
[FAIL: incomplete symbolic execution (Error): symbolic counterexample did not replay] checkNoUserIsAdmin(address) ([METRICS])

Encountered a total of 1 failing tests, 0 tests succeeded

Expand Down
Loading