Skip to content

Commit 46984c2

Browse files
authored
refactor: moves state diff decoding to common (#11413)
* refactor: storage decoder * cleanup * dedup MappingSlots by moving it to common * move decoding logic into SlotInfo * rename to SlotIndentifier * docs * fix: delegate identification according to encoding types * clippy + fmt * docs fix * fix * merge match arms * merge ifs * recurse handle_struct
1 parent 8b0dc48 commit 46984c2

File tree

7 files changed

+792
-893
lines changed

7 files changed

+792
-893
lines changed

crates/cheatcodes/src/evm.rs

Lines changed: 47 additions & 843 deletions
Large diffs are not rendered by default.

crates/cheatcodes/src/evm/mapping.rs

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,12 @@
11
use crate::{Cheatcode, Cheatcodes, Result, Vm::*};
2-
use alloy_primitives::{
3-
Address, B256, U256, keccak256,
4-
map::{AddressHashMap, B256HashMap},
5-
};
2+
use alloy_primitives::{Address, B256, U256, keccak256, map::AddressHashMap};
63
use alloy_sol_types::SolValue;
4+
use foundry_common::mapping_slots::MappingSlots;
75
use revm::{
86
bytecode::opcode,
97
interpreter::{Interpreter, interpreter_types::Jumps},
108
};
119

12-
/// Recorded mapping slots.
13-
#[derive(Clone, Debug, Default)]
14-
pub struct MappingSlots {
15-
/// Holds mapping parent (slots => slots)
16-
pub parent_slots: B256HashMap<B256>,
17-
18-
/// Holds mapping key (slots => key)
19-
pub keys: B256HashMap<B256>,
20-
21-
/// Holds mapping child (slots => slots[])
22-
pub children: B256HashMap<Vec<B256>>,
23-
24-
/// Holds the last sha3 result `sha3_result => (data_low, data_high)`, this would only record
25-
/// when sha3 is called with `size == 0x40`, and the lower 256 bits would be stored in
26-
/// `data_low`, higher 256 bits in `data_high`.
27-
/// This is needed for mapping_key detect if the slot is for some mapping and record that.
28-
pub seen_sha3: B256HashMap<(B256, B256)>,
29-
}
30-
31-
impl MappingSlots {
32-
/// Tries to insert a mapping slot. Returns true if it was inserted.
33-
pub fn insert(&mut self, slot: B256) -> bool {
34-
match self.seen_sha3.get(&slot).copied() {
35-
Some((key, parent)) => {
36-
if self.keys.contains_key(&slot) {
37-
return false;
38-
}
39-
self.keys.insert(slot, key);
40-
self.parent_slots.insert(slot, parent);
41-
self.children.entry(parent).or_default().push(slot);
42-
self.insert(parent);
43-
true
44-
}
45-
None => false,
46-
}
47-
}
48-
}
49-
5010
impl Cheatcode for startMappingRecordingCall {
5111
fn apply(&self, state: &mut Cheatcodes) -> Result {
5212
let Self {} = self;

crates/cheatcodes/src/inspector.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use crate::{
44
CheatsConfig, CheatsCtxt, DynCheatcode, Error, Result,
55
Vm::{self, AccountAccess},
66
evm::{
7-
DealRecord, GasRecord, RecordAccess,
8-
mapping::{self, MappingSlots},
7+
DealRecord, GasRecord, RecordAccess, mapping,
98
mock::{MockCallDataContext, MockCallReturnData},
109
prank::Prank,
1110
},
@@ -33,7 +32,9 @@ use alloy_rpc_types::{
3332
request::{TransactionInput, TransactionRequest},
3433
};
3534
use alloy_sol_types::{SolCall, SolInterface, SolValue};
36-
use foundry_common::{SELECTOR_LEN, TransactionMaybeSigned, evm::Breakpoints};
35+
use foundry_common::{
36+
SELECTOR_LEN, TransactionMaybeSigned, evm::Breakpoints, mapping_slots::MappingSlots,
37+
};
3738
use foundry_evm_core::{
3839
InspectorExt,
3940
abi::Vm::stopExpectSafeMemoryCall,

crates/common/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ pub mod contracts;
2525
pub mod errors;
2626
pub mod evm;
2727
pub mod fs;
28+
pub mod mapping_slots;
2829
mod preprocessor;
2930
pub mod provider;
3031
pub mod reports;
3132
pub mod retry;
3233
pub mod selectors;
3334
pub mod serde_helpers;
35+
pub mod slot_identifier;
3436
pub mod term;
3537
pub mod traits;
3638
pub mod transactions;

crates/common/src/mapping_slots.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use alloy_primitives::{B256, map::B256HashMap};
2+
3+
/// Recorded mapping slots.
4+
#[derive(Clone, Debug, Default)]
5+
pub struct MappingSlots {
6+
/// Holds mapping parent (slots => slots)
7+
pub parent_slots: B256HashMap<B256>,
8+
9+
/// Holds mapping key (slots => key)
10+
pub keys: B256HashMap<B256>,
11+
12+
/// Holds mapping child (slots => slots[])
13+
pub children: B256HashMap<Vec<B256>>,
14+
15+
/// Holds the last sha3 result `sha3_result => (data_low, data_high)`, this would only record
16+
/// when sha3 is called with `size == 0x40`, and the lower 256 bits would be stored in
17+
/// `data_low`, higher 256 bits in `data_high`.
18+
/// This is needed for mapping_key detect if the slot is for some mapping and record that.
19+
pub seen_sha3: B256HashMap<(B256, B256)>,
20+
}
21+
22+
impl MappingSlots {
23+
/// Tries to insert a mapping slot. Returns true if it was inserted.
24+
pub fn insert(&mut self, slot: B256) -> bool {
25+
match self.seen_sha3.get(&slot).copied() {
26+
Some((key, parent)) => {
27+
if self.keys.contains_key(&slot) {
28+
return false;
29+
}
30+
self.keys.insert(slot, key);
31+
self.parent_slots.insert(slot, parent);
32+
self.children.entry(parent).or_default().push(slot);
33+
self.insert(parent);
34+
true
35+
}
36+
None => false,
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)