foundry_cheatcodes/evm/
mapping.rs1use crate::{Cheatcode, Cheatcodes, Result, Vm::*};
2use alloy_primitives::{Address, B256};
3use alloy_sol_types::SolValue;
4use foundry_common::mapping_slots::MappingSlots;
5
6impl Cheatcode for startMappingRecordingCall {
7 fn apply(&self, state: &mut Cheatcodes) -> Result {
8 let Self {} = self;
9 state.mapping_slots.get_or_insert_default();
10 Ok(Default::default())
11 }
12}
13
14impl Cheatcode for stopMappingRecordingCall {
15 fn apply(&self, state: &mut Cheatcodes) -> Result {
16 let Self {} = self;
17 state.mapping_slots = None;
18 Ok(Default::default())
19 }
20}
21
22impl Cheatcode for getMappingLengthCall {
23 fn apply(&self, state: &mut Cheatcodes) -> Result {
24 let Self { target, mappingSlot } = self;
25 let result = slot_child(state, target, mappingSlot).map(Vec::len).unwrap_or(0);
26 Ok((result as u64).abi_encode())
27 }
28}
29
30impl Cheatcode for getMappingSlotAtCall {
31 fn apply(&self, state: &mut Cheatcodes) -> Result {
32 let Self { target, mappingSlot, idx } = self;
33 let result = slot_child(state, target, mappingSlot)
34 .and_then(|set| set.get(idx.saturating_to::<usize>()))
35 .copied()
36 .unwrap_or_default();
37 Ok(result.abi_encode())
38 }
39}
40
41impl Cheatcode for getMappingKeyAndParentOfCall {
42 fn apply(&self, state: &mut Cheatcodes) -> Result {
43 let Self { target, elementSlot: slot } = self;
44 let mut found = false;
45 let mut key = &B256::ZERO;
46 let mut parent = &B256::ZERO;
47 if let Some(slots) = mapping_slot(state, target) {
48 if let Some(key2) = slots.keys.get(slot) {
49 found = true;
50 key = key2;
51 parent = &slots.parent_slots[slot];
52 } else if let Some((key2, parent2)) = slots.seen_sha3.get(slot) {
53 found = true;
54 key = key2;
55 parent = parent2;
56 }
57 }
58 Ok((found, key, parent).abi_encode_params())
59 }
60}
61
62fn mapping_slot<'a>(state: &'a Cheatcodes, target: &'a Address) -> Option<&'a MappingSlots> {
63 state.mapping_slots.as_ref()?.get(target)
64}
65
66fn slot_child<'a>(
67 state: &'a Cheatcodes,
68 target: &'a Address,
69 slot: &'a B256,
70) -> Option<&'a Vec<B256>> {
71 mapping_slot(state, target)?.children.get(slot)
72}