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