1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! Work with `StorageAccessList` — the compact account/slot touch set captured
//! from simulations.
//!
//! It is smaller than an EIP-2930 transaction access list: accounts and
//! `(account, slot)` pairs are kept as sets so traces can be merged, warm-access
//! gas savings estimated, and slots prefetched. This example builds two touch
//! sets, merges them, estimates EIP-2929 savings, and converts to EIP-2930.
//!
//! Run with:
//!
//! ```sh
//! cargo run --example storage_access_list
//! ```
use alloy_primitives::{Address, U256};
use evm_fork_cache::StorageAccessList;
fn main() {
let contract = Address::repeat_byte(0xAA);
let token = Address::repeat_byte(0xBB);
// First simulation touches two slots on a hot contract.
let mut first = StorageAccessList::default();
first.accounts.insert(contract);
first.slots.insert((contract, U256::from(0)));
first.slots.insert((contract, U256::from(4)));
println!(
"first sim: {} accounts, {} slots",
first.account_count(),
first.slot_count()
);
// Second simulation re-touches the contract and additionally reads a token balance.
let mut second = StorageAccessList::default();
second.accounts.insert(contract);
second.accounts.insert(token);
second.slots.insert((contract, U256::from(0))); // overlaps with first
second.slots.insert((token, U256::from(3))); // a balance slot
// If `second` runs after `first` has warmed state, the overlap is cheaper
// under EIP-2929 (warm SLOAD/account access).
let savings = second.marginal_gas_savings(&first);
println!("estimated warm-access gas saved if run after first: {savings}");
// Merge both traces into a single prefetch set.
let mut merged = first.clone();
merged.extend(&second);
println!(
"merged: {} accounts, {} slots",
merged.account_count(),
merged.slot_count()
);
// Convert to an EIP-2930 access list for inclusion in a transaction.
let eip2930 = merged.to_eip2930();
println!("\nEIP-2930 access list ({} entries):", eip2930.0.len());
for item in &eip2930.0 {
println!(
" {} -> {} storage keys",
item.address,
item.storage_keys.len()
);
}
}