foundry_config/invariant.rs
1//! Configuration for invariant testing
2
3use crate::fuzz::FuzzDictionaryConfig;
4use serde::{Deserialize, Serialize};
5use std::path::PathBuf;
6
7/// Contains for invariant testing
8#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
9pub struct InvariantConfig {
10 /// The number of runs that must execute for each invariant test group.
11 pub runs: u32,
12 /// The number of calls executed to attempt to break invariants in one run.
13 pub depth: u32,
14 /// Fails the invariant fuzzing if a revert occurs
15 pub fail_on_revert: bool,
16 /// Allows overriding an unsafe external call when running invariant tests. eg. reentrancy
17 /// checks
18 pub call_override: bool,
19 /// The fuzz dictionary configuration
20 #[serde(flatten)]
21 pub dictionary: FuzzDictionaryConfig,
22 /// The maximum number of attempts to shrink the sequence
23 pub shrink_run_limit: u32,
24 /// The maximum number of rejects via `vm.assume` which can be encountered during a single
25 /// invariant run.
26 pub max_assume_rejects: u32,
27 /// Number of runs to execute and include in the gas report.
28 pub gas_report_samples: u32,
29 /// Path where invariant corpus is stored. If not configured then coverage guided fuzzing is
30 /// disabled.
31 pub corpus_dir: Option<PathBuf>,
32 /// Whether corpus to use gzip file compression and decompression.
33 pub corpus_gzip: bool,
34 // Number of corpus mutations until marked as eligible to be flushed from memory.
35 pub corpus_min_mutations: usize,
36 // Number of corpus that won't be evicted from memory.
37 pub corpus_min_size: usize,
38 /// Path where invariant failures are recorded and replayed.
39 pub failure_persist_dir: Option<PathBuf>,
40 /// Whether to collect and display fuzzed selectors metrics.
41 pub show_metrics: bool,
42 /// Optional timeout (in seconds) for each invariant test.
43 pub timeout: Option<u32>,
44 /// Display counterexample as solidity calls.
45 pub show_solidity: bool,
46}
47
48impl Default for InvariantConfig {
49 fn default() -> Self {
50 Self {
51 runs: 256,
52 depth: 500,
53 fail_on_revert: false,
54 call_override: false,
55 dictionary: FuzzDictionaryConfig { dictionary_weight: 80, ..Default::default() },
56 shrink_run_limit: 5000,
57 max_assume_rejects: 65536,
58 gas_report_samples: 256,
59 corpus_dir: None,
60 corpus_gzip: true,
61 corpus_min_mutations: 5,
62 corpus_min_size: 0,
63 failure_persist_dir: None,
64 show_metrics: true,
65 timeout: None,
66 show_solidity: false,
67 }
68 }
69}
70
71impl InvariantConfig {
72 /// Creates invariant configuration to write failures in `{PROJECT_ROOT}/cache/fuzz` dir.
73 pub fn new(cache_dir: PathBuf) -> Self {
74 Self {
75 runs: 256,
76 depth: 500,
77 fail_on_revert: false,
78 call_override: false,
79 dictionary: FuzzDictionaryConfig { dictionary_weight: 80, ..Default::default() },
80 shrink_run_limit: 5000,
81 max_assume_rejects: 65536,
82 gas_report_samples: 256,
83 corpus_dir: None,
84 corpus_gzip: true,
85 corpus_min_mutations: 5,
86 corpus_min_size: 0,
87 failure_persist_dir: Some(cache_dir),
88 show_metrics: true,
89 timeout: None,
90 show_solidity: false,
91 }
92 }
93}