Skip to content
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
926e8d5
feat(`forge`): sample typed storage values
yash-atreya Aug 4, 2025
8ec91b3
arc it
yash-atreya Aug 4, 2025
cfd4a15
nit
yash-atreya Aug 4, 2025
c56c920
clippy
yash-atreya Aug 4, 2025
90a1dea
nit
yash-atreya Aug 4, 2025
e7caa86
strip file prefixes
yash-atreya Aug 4, 2025
bccf3ad
fmt
yash-atreya Aug 4, 2025
fd6ecd6
don't add adjacent values to sample
yash-atreya Aug 5, 2025
a4c4a79
Merge branch 'master' into yash/fuzz-storage-values-by-type
yash-atreya Aug 5, 2025
f62bcb8
feat(cheatcodes): add contract identifier to AccountStateDiffs
yash-atreya Aug 5, 2025
1b4520f
forge fmt
yash-atreya Aug 5, 2025
cc29481
Merge branch 'master' into yash/state-diff-storage-labels
yash-atreya Aug 11, 2025
729ea8e
doc nits
yash-atreya Aug 11, 2025
2a8da88
fix tests
yash-atreya Aug 11, 2025
3c74ed9
feat(`cheatcodes`): include `SlotInfo` in SlotStateDiff
yash-atreya Aug 12, 2025
85a225b
cleanup + identify slots of static arrays
yash-atreya Aug 12, 2025
a4228ef
nits
yash-atreya Aug 12, 2025
1853d8e
nit
yash-atreya Aug 12, 2025
5b8b95b
nits
yash-atreya Aug 12, 2025
e619e0d
test + nits
yash-atreya Aug 12, 2025
caf21b9
docs
yash-atreya Aug 12, 2025
e9630a0
handle 2d arrays
yash-atreya Aug 12, 2025
b44b410
use DynSolType
yash-atreya Aug 12, 2025
e78b087
feat: decode storage values
yash-atreya Aug 13, 2025
ebcef04
doc nit
yash-atreya Aug 13, 2025
65db931
skip decoded serialization if none
yash-atreya Aug 13, 2025
7d3c87b
nit
yash-atreya Aug 13, 2025
fe8b59d
Merge branch 'master' into yash/state-diff-storage-labels
yash-atreya Aug 13, 2025
e63e817
fmt
yash-atreya Aug 13, 2025
f9ffcea
fix
yash-atreya Aug 13, 2025
05d4a38
Merge branch 'yash/state-diff-storage-labels' into yash/decode-label-…
yash-atreya Aug 13, 2025
f25c85d
fix
yash-atreya Aug 13, 2025
055797d
fix
yash-atreya Aug 13, 2025
0882694
Merge branch 'yash/state-diff-storage-labels' into yash/decode-label-…
yash-atreya Aug 13, 2025
0026752
resolve conflicts
Aug 18, 2025
2d62559
feat(cheatcodes): decode structs in state diff output
Aug 18, 2025
0db68f7
fix
yash-atreya Aug 18, 2025
927e756
while decode
yash-atreya Aug 19, 2025
e487e82
fix: show only decoded in plaintext / display output + test
yash-atreya Aug 19, 2025
a28c41c
Merge branch 'master' into yash/decode-label-state-diffs
yash-atreya Aug 19, 2025
1482e30
Merge branch 'yash/decode-label-state-diffs' into yash/decode-structs…
yash-atreya Aug 19, 2025
aa36022
feat: format slots to only significant bits in vm.getStateDiff output
yash-atreya Aug 19, 2025
3cfefdc
encode_prefixed
yash-atreya Aug 19, 2025
850dc6c
nit
yash-atreya Aug 19, 2025
8f9f82f
Merge branch 'yash/decode-label-state-diffs' into yash/decode-structs…
yash-atreya Aug 19, 2025
6e3120b
chore: add @onbjerg to `CODEOWNERS` (#11343)
zerosnacks Aug 19, 2025
0ea49a2
resolve conflicts
yash-atreya Aug 20, 2025
a11c347
fix: disable tx gas limit cap (#11347)
mattsse Aug 19, 2025
f9964de
chore(deps): bump all dependencies (#11349)
DaniPopes Aug 19, 2025
6ebfaf3
chore: use get_or_calculate_hash better (#11350)
DaniPopes Aug 19, 2025
cc09011
resolve more conflicts
yash-atreya Aug 20, 2025
9c78c61
fix(lint): 'unwrapped-modifier-logic' incorrectly marked with `Severi…
srdtrk Aug 19, 2025
cbbbdb6
feat: identify and decode nested structs
yash-atreya Aug 20, 2025
156bc80
resolve conflicts
yash-atreya Aug 20, 2025
55249e8
cleanup
yash-atreya Aug 20, 2025
1b1f626
decode structs and members recursively
yash-atreya Aug 20, 2025
499abf6
cleanup
yash-atreya Aug 20, 2025
a1de1dc
doc fix
yash-atreya Aug 20, 2025
bb255b3
Merge branch 'master' into yash/decode-structs-in-state-diffs
0xrusowsky Aug 20, 2025
c9d1cef
feat(cheatcodes): decode mappings in state diffs (#11381)
yash-atreya Aug 25, 2025
7460161
dedup assertContains test util
yash-atreya Aug 25, 2025
befdf4b
Merge branch 'master' into yash/decode-structs-in-state-diffs
yash-atreya Aug 25, 2025
5cd7b12
fix
yash-atreya Aug 25, 2025
398c5ab
Update crates/common/src/slot_identifier.rs
grandizzy Aug 26, 2025
8be596d
Review changes: simplify get or insert, use common fmt
grandizzy Aug 26, 2025
b850bc7
alloy-dyn-abi.workspace
grandizzy Aug 26, 2025
fbcd265
nits
yash-atreya Aug 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/cheatcodes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ foundry-evm-traces.workspace = true
foundry-wallets.workspace = true
forge-script-sequence.workspace = true

alloy-dyn-abi.workspace = true
alloy-dyn-abi = { workspace = true, features = ["eip712"] }
alloy-evm.workspace = true
alloy-json-abi.workspace = true
alloy-primitives.workspace = true
Expand Down
277 changes: 56 additions & 221 deletions crates/cheatcodes/src/evm.rs

Large diffs are not rendered by default.

44 changes: 2 additions & 42 deletions crates/cheatcodes/src/evm/mapping.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,12 @@
use crate::{Cheatcode, Cheatcodes, Result, Vm::*};
use alloy_primitives::{
Address, B256, U256, keccak256,
map::{AddressHashMap, B256HashMap},
};
use alloy_primitives::{Address, B256, U256, keccak256, map::AddressHashMap};
use alloy_sol_types::SolValue;
use foundry_common::mapping_slots::MappingSlots;
use revm::{
bytecode::opcode,
interpreter::{Interpreter, interpreter_types::Jumps},
};

/// Recorded mapping slots.
#[derive(Clone, Debug, Default)]
pub struct MappingSlots {
/// Holds mapping parent (slots => slots)
pub parent_slots: B256HashMap<B256>,

/// Holds mapping key (slots => key)
pub keys: B256HashMap<B256>,

/// Holds mapping child (slots => slots[])
pub children: B256HashMap<Vec<B256>>,

/// Holds the last sha3 result `sha3_result => (data_low, data_high)`, this would only record
/// when sha3 is called with `size == 0x40`, and the lower 256 bits would be stored in
/// `data_low`, higher 256 bits in `data_high`.
/// This is needed for mapping_key detect if the slot is for some mapping and record that.
pub seen_sha3: B256HashMap<(B256, B256)>,
}

impl MappingSlots {
/// Tries to insert a mapping slot. Returns true if it was inserted.
pub fn insert(&mut self, slot: B256) -> bool {
match self.seen_sha3.get(&slot).copied() {
Some((key, parent)) => {
if self.keys.contains_key(&slot) {
return false;
}
self.keys.insert(slot, key);
self.parent_slots.insert(slot, parent);
self.children.entry(parent).or_default().push(slot);
self.insert(parent);
true
}
None => false,
}
}
}

impl Cheatcode for startMappingRecordingCall {
fn apply(&self, state: &mut Cheatcodes) -> Result {
let Self {} = self;
Expand Down
7 changes: 4 additions & 3 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use crate::{
CheatsConfig, CheatsCtxt, DynCheatcode, Error, Result,
Vm::{self, AccountAccess},
evm::{
DealRecord, GasRecord, RecordAccess,
mapping::{self, MappingSlots},
DealRecord, GasRecord, RecordAccess, mapping,
mock::{MockCallDataContext, MockCallReturnData},
prank::Prank,
},
Expand Down Expand Up @@ -33,7 +32,9 @@ use alloy_rpc_types::{
request::{TransactionInput, TransactionRequest},
};
use alloy_sol_types::{SolCall, SolInterface, SolValue};
use foundry_common::{SELECTOR_LEN, TransactionMaybeSigned, evm::Breakpoints};
use foundry_common::{
SELECTOR_LEN, TransactionMaybeSigned, evm::Breakpoints, mapping_slots::MappingSlots,
};
use foundry_evm_core::{
InspectorExt,
abi::Vm::stopExpectSafeMemoryCall,
Expand Down
2 changes: 2 additions & 0 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ pub mod contracts;
pub mod errors;
pub mod evm;
pub mod fs;
pub mod mapping_slots;
mod preprocessor;
pub mod provider;
pub mod reports;
pub mod retry;
pub mod selectors;
pub mod serde_helpers;
pub mod slot_identifier;
pub mod term;
pub mod traits;
pub mod transactions;
Expand Down
39 changes: 39 additions & 0 deletions crates/common/src/mapping_slots.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use alloy_primitives::{B256, map::B256HashMap};

/// Recorded mapping slots.
#[derive(Clone, Debug, Default)]
pub struct MappingSlots {
/// Holds mapping parent (slots => slots)
pub parent_slots: B256HashMap<B256>,

/// Holds mapping key (slots => key)
pub keys: B256HashMap<B256>,

/// Holds mapping child (slots => slots[])
pub children: B256HashMap<Vec<B256>>,

/// Holds the last sha3 result `sha3_result => (data_low, data_high)`, this would only record
/// when sha3 is called with `size == 0x40`, and the lower 256 bits would be stored in
/// `data_low`, higher 256 bits in `data_high`.
/// This is needed for mapping_key detect if the slot is for some mapping and record that.
pub seen_sha3: B256HashMap<(B256, B256)>,
}

impl MappingSlots {
/// Tries to insert a mapping slot. Returns true if it was inserted.
pub fn insert(&mut self, slot: B256) -> bool {
match self.seen_sha3.get(&slot).copied() {
Some((key, parent)) => {
if self.keys.contains_key(&slot) {
return false;
}
self.keys.insert(slot, key);
self.parent_slots.insert(slot, parent);
self.children.entry(parent).or_default().push(slot);
self.insert(parent);
true
}
None => false,
}
}
}
Loading
Loading