-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Expand file tree
/
Copy pathinvariant.rs
More file actions
92 lines (87 loc) · 3.68 KB
/
invariant.rs
File metadata and controls
92 lines (87 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! Configuration for invariant testing
use crate::fuzz::{FuzzCorpusConfig, FuzzDictionaryConfig};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
/// Contains for invariant testing
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct InvariantConfig {
/// The number of runs that must execute for each invariant test group.
pub runs: u32,
/// The number of calls executed to attempt to break invariants in one run.
pub depth: u32,
/// Fails the invariant fuzzing if a revert occurs
pub fail_on_revert: bool,
/// Allows overriding an unsafe external call when running invariant tests. eg. reentrancy
/// checks
pub call_override: bool,
/// The fuzz dictionary configuration
#[serde(flatten)]
pub dictionary: FuzzDictionaryConfig,
/// The maximum number of attempts to shrink the sequence
pub shrink_run_limit: u32,
/// The maximum number of rejects via `vm.assume` which can be encountered during a single
/// invariant run.
pub max_assume_rejects: u32,
/// Number of runs to execute and include in the gas report.
pub gas_report_samples: u32,
/// The fuzz corpus configuration.
#[serde(flatten)]
pub corpus: FuzzCorpusConfig,
/// Path where invariant failures are recorded and replayed.
pub failure_persist_dir: Option<PathBuf>,
/// Whether to collect and display fuzzed selectors metrics.
pub show_metrics: bool,
/// Optional timeout (in seconds) for each invariant test.
pub timeout: Option<u32>,
/// Display counterexample as solidity calls.
pub show_solidity: bool,
/// Maximum time (in seconds) between generated txs.
pub max_time_delay: Option<u32>,
/// Maximum number of blocks elapsed between generated txs.
pub max_block_delay: Option<u32>,
/// Number of calls to execute between invariant assertions.
///
/// - `0`: Only assert on the last call of each run (fastest, but may miss exact breaking call)
/// - `1` (default): Assert after every call (current behavior, most precise)
/// - `N`: Assert every N calls AND always on the last call
///
/// Example: `check_interval = 10` means assert after calls 10, 20, 30, ... and the last call.
pub check_interval: u32,
/// Assert every invariant declared in the current test suite, continuing the campaign after
/// the first failure until all invariants have been broken (or normal limits are hit).
/// When `false`, the campaign aborts on the first broken invariant (legacy behavior).
pub assert_all: bool,
}
impl Default for InvariantConfig {
fn default() -> Self {
Self {
runs: 256,
depth: 500,
fail_on_revert: false,
call_override: false,
dictionary: FuzzDictionaryConfig { dictionary_weight: 80, ..Default::default() },
shrink_run_limit: 5000,
max_assume_rejects: 65536,
gas_report_samples: 256,
corpus: FuzzCorpusConfig::default(),
failure_persist_dir: None,
show_metrics: true,
timeout: None,
show_solidity: false,
max_time_delay: None,
max_block_delay: None,
check_interval: 1,
assert_all: true,
}
}
}
impl InvariantConfig {
/// Creates invariant configuration to write failures in `{PROJECT_ROOT}/cache/fuzz` dir.
pub fn new(cache_dir: PathBuf) -> Self {
Self { failure_persist_dir: Some(cache_dir), ..Default::default() }
}
/// Returns true if generated invariant calls may advance block time or height.
pub const fn has_delay(&self) -> bool {
self.max_block_delay.is_some() || self.max_time_delay.is_some()
}
}