foundry_evm_fuzz/strategies/
calldata.rs
1use crate::{
2 strategies::{fuzz_param_from_state, fuzz_param_with_fixtures, EvmFuzzState},
3 FuzzFixtures,
4};
5use alloy_dyn_abi::JsonAbiExt;
6use alloy_json_abi::Function;
7use alloy_primitives::Bytes;
8use proptest::prelude::Strategy;
9
10pub fn fuzz_calldata(func: Function, fuzz_fixtures: &FuzzFixtures) -> impl Strategy<Value = Bytes> {
13 let strats = func
16 .inputs
17 .iter()
18 .map(|input| {
19 fuzz_param_with_fixtures(
20 &input.selector_type().parse().unwrap(),
21 fuzz_fixtures.param_fixtures(&input.name),
22 &input.name,
23 )
24 })
25 .collect::<Vec<_>>();
26 strats.prop_map(move |values| {
27 func.abi_encode_input(&values)
28 .unwrap_or_else(|_| {
29 panic!(
30 "Fuzzer generated invalid arguments for function `{}` with inputs {:?}: {:?}",
31 func.name, func.inputs, values
32 )
33 })
34 .into()
35 })
36}
37
38pub fn fuzz_calldata_from_state(
41 func: Function,
42 state: &EvmFuzzState,
43) -> impl Strategy<Value = Bytes> {
44 let strats = func
45 .inputs
46 .iter()
47 .map(|input| fuzz_param_from_state(&input.selector_type().parse().unwrap(), state))
48 .collect::<Vec<_>>();
49 strats
50 .prop_map(move |values| {
51 func.abi_encode_input(&values)
52 .unwrap_or_else(|_| {
53 panic!(
54 "Fuzzer generated invalid arguments for function `{}` with inputs {:?}: {:?}",
55 func.name, func.inputs, values
56 )
57 })
58 .into()
59 })
60 .no_shrink()
61}
62
63#[cfg(test)]
64mod tests {
65 use crate::{strategies::fuzz_calldata, FuzzFixtures};
66 use alloy_dyn_abi::{DynSolValue, JsonAbiExt};
67 use alloy_json_abi::Function;
68 use alloy_primitives::{map::HashMap, Address};
69 use proptest::prelude::Strategy;
70
71 #[test]
72 fn can_fuzz_with_fixtures() {
73 let function = Function::parse("test_fuzzed_address(address addressFixture)").unwrap();
74
75 let address_fixture = DynSolValue::Address(Address::random());
76 let mut fixtures = HashMap::default();
77 fixtures.insert(
78 "addressFixture".to_string(),
79 DynSolValue::Array(vec![address_fixture.clone()]),
80 );
81
82 let expected = function.abi_encode_input(&[address_fixture]).unwrap();
83 let strategy = fuzz_calldata(function, &FuzzFixtures::new(fixtures));
84 let _ = strategy.prop_map(move |fuzzed| {
85 assert_eq!(expected, fuzzed);
86 });
87 }
88}