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 #[serde(deserialize_with = "crate::deserialize_usize_or_max")]
87 pub max_fuzz_dictionary_literals: usize,
88}
89
90impl Default for FuzzDictionaryConfig {
91 fn default() -> Self {
92 const MB: usize = 1024 * 1024;
93
94 Self {
95 dictionary_weight: 40,
96 include_storage: true,
97 include_push_bytes: true,
98 max_fuzz_dictionary_addresses: 300 * MB / 20,
99 max_fuzz_dictionary_values: 300 * MB / 32,
100 max_fuzz_dictionary_literals: 200 * MB / 32,
101 }
102 }
103}
104
105#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
106pub struct FuzzCorpusConfig {
107 pub corpus_dir: Option<PathBuf>,
110 pub corpus_gzip: bool,
112 pub corpus_min_mutations: usize,
115 pub corpus_min_size: usize,
117 pub show_edge_coverage: bool,
119}
120
121impl FuzzCorpusConfig {
122 pub fn with_test(&mut self, contract: &str, test: &str) {
123 if let Some(corpus_dir) = &self.corpus_dir {
124 self.corpus_dir = Some(canonicalized(corpus_dir.join(contract).join(test)));
125 }
126 }
127
128 pub fn collect_edge_coverage(&self) -> bool {
130 self.corpus_dir.is_some() || self.show_edge_coverage
131 }
132
133 pub fn is_coverage_guided(&self) -> bool {
135 self.corpus_dir.is_some()
136 }
137}
138
139impl Default for FuzzCorpusConfig {
140 fn default() -> Self {
141 Self {
142 corpus_dir: None,
143 corpus_gzip: true,
144 corpus_min_mutations: 5,
145 corpus_min_size: 0,
146 show_edge_coverage: false,
147 }
148 }
149}