Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7f0d2ba
feat(test): ast-seeded fuzzer dictionary
0xrusowsky Oct 8, 2025
2809ba5
test: add unit tests
0xrusowsky Oct 8, 2025
9bea99a
test: add unit tests
0xrusowsky Oct 9, 2025
83542a4
fix: default config test
0xrusowsky Oct 9, 2025
2a6c8c4
fix: merge `sample_values` and `ast_values.words`
0xrusowsky Oct 9, 2025
738a7f6
fix: typos
0xrusowsky Oct 9, 2025
951e0cd
better test
0xrusowsky Oct 9, 2025
07a5dca
chore: move `LiteralsCollector` to the fuzz crate
0xrusowsky Oct 9, 2025
7316df5
feat: bytes support
0xrusowsky Oct 9, 2025
dc063ca
feat: int support
0xrusowsky Oct 10, 2025
fc4f3d4
style: clippy
0xrusowsky Oct 10, 2025
3440429
fix: bump max dict values
0xrusowsky Oct 10, 2025
5ea2f8d
style: simplify tests
0xrusowsky Oct 10, 2025
bf49a49
style: cmnts
0xrusowsky Oct 10, 2025
6477f11
fix: test
0xrusowsky Oct 10, 2025
58e45f9
fix: test
0xrusowsky Oct 10, 2025
e4e5b4d
feat: insert all possible uint types that fit
0xrusowsky Oct 10, 2025
6aaa729
test: turn `unit256` to `uint64` to ensure discovery of smaller uints
0xrusowsky Oct 10, 2025
cba4f57
test: add `LiteralCollector` coverage and size tests
0xrusowsky Oct 10, 2025
b56e2ae
test: simplify
0xrusowsky Oct 10, 2025
c7ff115
style: avoid typo error
0xrusowsky Oct 10, 2025
935c435
test: revert `should_fuzz_literals` changes
0xrusowsky Oct 10, 2025
bc9504e
fix: missing test
0xrusowsky Oct 13, 2025
7ed7476
Merge branch 'master' into rusowsky/ast-fuzz-dict
0xrusowsky Oct 13, 2025
9a05ffb
style: use MB const + use `bool::weighted` + rename `state_clone`
0xrusowsky Oct 14, 2025
5813a5a
refactor: new literals.rs file
0xrusowsky Oct 14, 2025
e7d3159
feat: lazily collect literals
0xrusowsky Oct 14, 2025
544d7ff
fix: default config tests
0xrusowsky Oct 14, 2025
7907e97
Merge branch 'master' into rusowsky/ast-fuzz-dict
0xrusowsky Oct 14, 2025
a0fe257
Merge branch 'master' of github.com:foundry-rs/foundry into rusowsky/…
0xrusowsky Oct 20, 2025
172b63a
fix: merge conflicts
0xrusowsky Oct 20, 2025
8f854be
Merge branch 'master' into rusowsky/ast-fuzz-dict
0xrusowsky Oct 20, 2025
aa48772
fix: more merge conflicts
0xrusowsky Oct 20, 2025
587038c
fix: no need to rmv cache
0xrusowsky Oct 20, 2025
c212567
Merge branch 'master' into rusowsky/ast-fuzz-dict
0xrusowsky Oct 21, 2025
6475317
chore: use alias type for `Arc<Compiler>`
0xrusowsky Oct 21, 2025
959314f
Merge branch 'rusowsky/ast-fuzz-dict' of github.com:foundry-rs/foundr…
0xrusowsky Oct 21, 2025
34d280e
style: rename for consistency
0xrusowsky Oct 21, 2025
4d9ee25
test: prove improvement with new features
0xrusowsky Oct 22, 2025
a4d0c1c
fix: use seed to prevent potential flakiness
0xrusowsky Oct 22, 2025
15856c8
Merge branch 'master' into rusowsky/ast-fuzz-dict
0xrusowsky Oct 22, 2025
5e7847b
fix: assert contract outputs individually
0xrusowsky Oct 22, 2025
a65342c
Merge branch 'rusowsky/ast-fuzz-dict' of github.com:foundry-rs/foundr…
0xrusowsky Oct 22, 2025
4094e81
chore: bump forge-std
0xrusowsky Oct 22, 2025
5f80af8
Merge branch 'master' into rusowsky/ast-fuzz-dict
0xrusowsky Oct 22, 2025
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/common/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ use std::{
io::IsTerminal,
path::{Path, PathBuf},
str::FromStr,
sync::Arc,
time::Instant,
};

/// A Solar compiler instance, to grant syntactic and semantic analysis capabilities.
pub type Analysis = Arc<solar::sema::Compiler>;

/// Builder type to configure how to compile a project.
///
/// This is merely a wrapper for [`Project::compile()`] which also prints to stdout depending on its
Expand Down
1 change: 1 addition & 0 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub mod transactions;
mod utils;
pub mod version;

pub use compile::Analysis;
pub use constants::*;
pub use contracts::*;
pub use io::{Shell, shell, stdin};
Expand Down
14 changes: 10 additions & 4 deletions crates/config/src/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,24 @@ pub struct FuzzDictionaryConfig {
/// Once the fuzzer exceeds this limit, it will start evicting random entries
#[serde(deserialize_with = "crate::deserialize_usize_or_max")]
pub max_fuzz_dictionary_values: usize,
/// How many literal values to seed from the AST, at most.
///
/// This value is independent from the max amount of addresses and values.
#[serde(deserialize_with = "crate::deserialize_usize_or_max")]
pub max_fuzz_dictionary_literals: usize,
}

impl Default for FuzzDictionaryConfig {
fn default() -> Self {
const MB: usize = 1024 * 1024;

Self {
dictionary_weight: 40,
include_storage: true,
include_push_bytes: true,
// limit this to 300MB
max_fuzz_dictionary_addresses: (300 * 1024 * 1024) / 20,
// limit this to 200MB
max_fuzz_dictionary_values: (200 * 1024 * 1024) / 32,
max_fuzz_dictionary_addresses: 300 * MB / 20,
max_fuzz_dictionary_values: 300 * MB / 32,
max_fuzz_dictionary_literals: 200 * MB / 32,
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions crates/evm/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ foundry-evm-fuzz.workspace = true
foundry-evm-networks.workspace = true
foundry-evm-traces.workspace = true

solar.workspace = true

alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] }
alloy-evm.workspace = true
alloy-json-abi.workspace = true
Expand Down
12 changes: 11 additions & 1 deletion crates/evm/evm/src/executors/fuzz/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,23 @@ impl FuzzedExecutor {

/// Stores fuzz state for use with [fuzz_calldata_from_state]
pub fn build_fuzz_state(&self, deployed_libs: &[Address]) -> EvmFuzzState {
let inspector = self.executor.inspector();

if let Some(fork_db) = self.executor.backend().active_fork_db() {
EvmFuzzState::new(fork_db, self.config.dictionary, deployed_libs)
EvmFuzzState::new(
fork_db,
self.config.dictionary,
deployed_libs,
inspector.analysis.as_ref(),
inspector.paths_config(),
)
} else {
EvmFuzzState::new(
self.executor.backend().mem_db(),
self.config.dictionary,
deployed_libs,
inspector.analysis.as_ref(),
inspector.paths_config(),
)
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/evm/evm/src/executors/invariant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,10 +566,13 @@ impl<'a> InvariantExecutor<'a> {
self.select_contracts_and_senders(invariant_contract.address)?;

// Stores fuzz state for use with [fuzz_calldata_from_state].
let inspector = self.executor.inspector();
let fuzz_state = EvmFuzzState::new(
self.executor.backend().mem_db(),
self.config.dictionary,
deployed_libs,
inspector.analysis.as_ref(),
inspector.paths_config(),
);

// Creates the invariant strategy.
Expand Down
24 changes: 21 additions & 3 deletions crates/evm/evm/src/inspectors/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use alloy_primitives::{
map::{AddressHashMap, HashMap},
};
use foundry_cheatcodes::{CheatcodeAnalysis, CheatcodesExecutor, Wallets};
use foundry_common::compile::Analysis;
use foundry_compilers::ProjectPathsConfig;
use foundry_evm_core::{
ContextExt, Env, InspectorExt,
backend::{DatabaseExt, JournaledState},
Expand Down Expand Up @@ -38,8 +40,8 @@ use std::{
#[derive(Clone, Debug, Default)]
#[must_use = "builders do nothing unless you call `build` on them"]
pub struct InspectorStackBuilder {
/// Solar compiler instance, to grant syntactic and semantic analysis capabilities
pub analysis: Option<Arc<solar::sema::Compiler>>,
/// Solar compiler instance, to grant syntactic and semantic analysis capabilities.
pub analysis: Option<Analysis>,
/// The block environment.
///
/// Used in the cheatcode handler to overwrite the block environment separately from the
Expand Down Expand Up @@ -85,7 +87,7 @@ impl InspectorStackBuilder {

/// Set the solar compiler instance that grants syntactic and semantic analysis capabilities
#[inline]
pub fn set_analysis(mut self, analysis: Arc<solar::sema::Compiler>) -> Self {
pub fn set_analysis(mut self, analysis: Analysis) -> Self {
self.analysis = Some(analysis);
self
}
Expand Down Expand Up @@ -209,6 +211,7 @@ impl InspectorStackBuilder {
let mut cheatcodes = Cheatcodes::new(config);
// Set analysis capabilities if they are provided
if let Some(analysis) = analysis {
stack.set_analysis(analysis.clone());
cheatcodes.set_analysis(CheatcodeAnalysis::new(analysis));
}
// Set wallets if they are provided
Expand Down Expand Up @@ -308,11 +311,20 @@ pub struct InspectorStack {
pub inner: InspectorStackInner,
}

impl InspectorStack {
pub fn paths_config(&self) -> Option<&ProjectPathsConfig> {
self.cheatcodes.as_ref().map(|c| &c.config.paths)
}
}

/// All used inpectors besides [Cheatcodes].
///
/// See [`InspectorStack`].
#[derive(Default, Clone, Debug)]
pub struct InspectorStackInner {
/// Solar compiler instance, to grant syntactic and semantic analysis capabilities.
pub analysis: Option<Analysis>,

// Inspectors.
// These are boxed to reduce the size of the struct and slightly improve performance of the
// `if let Some` checks.
Expand Down Expand Up @@ -388,6 +400,12 @@ impl InspectorStack {
});
}

/// Set the solar compiler instance.
#[inline]
pub fn set_analysis(&mut self, analysis: Analysis) {
self.analysis = Some(analysis);
}

/// Set variables from an environment for the relevant inspectors.
#[inline]
pub fn set_env(&mut self, env: &Env) {
Expand Down
2 changes: 2 additions & 0 deletions crates/evm/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ foundry-evm-core.workspace = true
foundry-evm-coverage.workspace = true
foundry-evm-traces.workspace = true

solar.workspace = true

alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] }
alloy-json-abi.workspace = true
alloy-primitives = { workspace = true, features = [
Expand Down
1 change: 1 addition & 0 deletions crates/evm/fuzz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub use error::FuzzError;

pub mod invariant;
pub mod strategies;
pub use strategies::LiteralMaps;

mod inspector;
pub use inspector::Fuzzer;
Expand Down
Loading
Loading