1use alloy_primitives::U256;
4use foundry_compilers::utils::canonicalized;
5use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7
8#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
10pub struct FuzzConfig {
11 pub runs: u32,
13 pub fail_on_revert: bool,
15 pub max_test_rejects: u32,
21 pub seed: Option<U256>,
23 #[serde(flatten)]
25 pub dictionary: FuzzDictionaryConfig,
26 pub gas_report_samples: u32,
28 #[serde(flatten)]
30 pub corpus: FuzzCorpusConfig,
31 pub failure_persist_dir: Option<PathBuf>,
33 pub show_logs: bool,
35 pub timeout: Option<u32>,
37}
38
39impl Default for FuzzConfig {
40 fn default() -> Self {
41 Self {
42 runs: 256,
43 fail_on_revert: true,
44 max_test_rejects: 65536,
45 seed: None,
46 dictionary: FuzzDictionaryConfig::default(),
47 gas_report_samples: 256,
48 corpus: FuzzCorpusConfig::default(),
49 failure_persist_dir: None,
50 show_logs: false,
51 timeout: None,
52 }
53 }
54}
55
56impl FuzzConfig {
57 pub fn new(cache_dir: PathBuf) -> Self {
59 Self { failure_persist_dir: Some(cache_dir), ..Default::default() }
60 }
61}
62
63#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
65pub struct FuzzDictionaryConfig {
66 #[serde(deserialize_with = "crate::deserialize_stringified_percent")]
68 pub dictionary_weight: u32,
69 pub include_storage: bool,
71 pub include_push_bytes: bool,
73 #[serde(deserialize_with = "crate::deserialize_usize_or_max")]
78 pub max_fuzz_dictionary_addresses: usize,
79 #[serde(deserialize_with = "crate::deserialize_usize_or_max")]
82 pub max_fuzz_dictionary_values: usize,
83}
84
85impl Default for FuzzDictionaryConfig {
86 fn default() -> Self {
87 Self {
88 dictionary_weight: 40,
89 include_storage: true,
90 include_push_bytes: true,
91 max_fuzz_dictionary_addresses: (300 * 1024 * 1024) / 20,
93 max_fuzz_dictionary_values: (200 * 1024 * 1024) / 32,
95 }
96 }
97}
98
99#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
100pub struct FuzzCorpusConfig {
101 pub corpus_dir: Option<PathBuf>,
104 pub corpus_gzip: bool,
106 pub corpus_min_mutations: usize,
109 pub corpus_min_size: usize,
111 pub show_edge_coverage: bool,
113}
114
115impl FuzzCorpusConfig {
116 pub fn with_test(&mut self, contract: &str, test: &str) {
117 if let Some(corpus_dir) = &self.corpus_dir {
118 self.corpus_dir = Some(canonicalized(corpus_dir.join(contract).join(test)));
119 }
120 }
121
122 pub fn collect_edge_coverage(&self) -> bool {
124 self.corpus_dir.is_some() || self.show_edge_coverage
125 }
126
127 pub fn is_coverage_guided(&self) -> bool {
129 self.corpus_dir.is_some()
130 }
131}
132
133impl Default for FuzzCorpusConfig {
134 fn default() -> Self {
135 Self {
136 corpus_dir: None,
137 corpus_gzip: true,
138 corpus_min_mutations: 5,
139 corpus_min_size: 0,
140 show_edge_coverage: false,
141 }
142 }
143}