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,
18 pub seed: Option<U256>,
20 #[serde(flatten)]
22 pub dictionary: FuzzDictionaryConfig,
23 pub gas_report_samples: u32,
25 #[serde(flatten)]
27 pub corpus: FuzzCorpusConfig,
28 pub failure_persist_dir: Option<PathBuf>,
30 pub show_logs: bool,
32 pub timeout: Option<u32>,
34}
35
36impl Default for FuzzConfig {
37 fn default() -> Self {
38 Self {
39 runs: 256,
40 fail_on_revert: true,
41 max_test_rejects: 65536,
42 seed: None,
43 dictionary: FuzzDictionaryConfig::default(),
44 gas_report_samples: 256,
45 corpus: FuzzCorpusConfig::default(),
46 failure_persist_dir: None,
47 show_logs: false,
48 timeout: None,
49 }
50 }
51}
52
53impl FuzzConfig {
54 pub fn new(cache_dir: PathBuf) -> Self {
56 Self { failure_persist_dir: Some(cache_dir), ..Default::default() }
57 }
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
62pub struct FuzzDictionaryConfig {
63 #[serde(deserialize_with = "crate::deserialize_stringified_percent")]
65 pub dictionary_weight: u32,
66 pub include_storage: bool,
68 pub include_push_bytes: bool,
70 #[serde(deserialize_with = "crate::deserialize_usize_or_max")]
75 pub max_fuzz_dictionary_addresses: usize,
76 #[serde(deserialize_with = "crate::deserialize_usize_or_max")]
79 pub max_fuzz_dictionary_values: usize,
80 #[serde(deserialize_with = "crate::deserialize_usize_or_max")]
84 pub max_fuzz_dictionary_literals: usize,
85}
86
87impl Default for FuzzDictionaryConfig {
88 fn default() -> Self {
89 const MB: usize = 1024 * 1024;
90
91 Self {
92 dictionary_weight: 40,
93 include_storage: true,
94 include_push_bytes: true,
95 max_fuzz_dictionary_addresses: 300 * MB / 20,
96 max_fuzz_dictionary_values: 300 * MB / 32,
97 max_fuzz_dictionary_literals: 200 * MB / 32,
98 }
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
103pub struct FuzzCorpusConfig {
104 pub corpus_dir: Option<PathBuf>,
107 pub corpus_gzip: bool,
109 pub corpus_min_mutations: usize,
112 pub corpus_min_size: usize,
114 pub show_edge_coverage: bool,
116}
117
118impl FuzzCorpusConfig {
119 pub fn with_test(&mut self, contract: &str, test: &str) {
120 if let Some(corpus_dir) = &self.corpus_dir {
121 self.corpus_dir = Some(canonicalized(corpus_dir.join(contract).join(test)));
122 }
123 }
124
125 pub fn collect_edge_coverage(&self) -> bool {
127 self.corpus_dir.is_some() || self.show_edge_coverage
128 }
129
130 pub fn is_coverage_guided(&self) -> bool {
132 self.corpus_dir.is_some()
133 }
134}
135
136impl Default for FuzzCorpusConfig {
137 fn default() -> Self {
138 Self {
139 corpus_dir: None,
140 corpus_gzip: true,
141 corpus_min_mutations: 5,
142 corpus_min_size: 0,
143 show_edge_coverage: false,
144 }
145 }
146}