alloy_rpc_types_eth/
state.rs

1//! bindings for state overrides in eth_call
2
3use crate::BlockOverrides;
4use alloc::boxed::Box;
5use alloy_primitives::{
6    map::{AddressHashMap, B256HashMap},
7    Address, Bytes, B256, U256,
8};
9
10/// A builder type for [`StateOverride`].
11#[derive(Clone, Debug, Default, PartialEq, Eq)]
12pub struct StateOverridesBuilder {
13    overrides: StateOverride,
14}
15
16impl StateOverridesBuilder {
17    /// Create a new StateOverridesBuilder.
18    pub const fn new(map: AddressHashMap<AccountOverride>) -> Self {
19        Self { overrides: map }
20    }
21
22    /// Creates a new [`StateOverridesBuilder`] with the given capacity.
23    pub fn with_capacity(capacity: usize) -> Self {
24        Self::new(StateOverride::with_capacity_and_hasher(capacity, Default::default()))
25    }
26
27    /// Adds an account override for a specific address.
28    pub fn append(mut self, address: Address, account_override: AccountOverride) -> Self {
29        self.overrides.insert(address, account_override);
30        self
31    }
32
33    /// Helper `append` function that appends an optional override.
34    pub fn append_opt<F>(self, f: F) -> Self
35    where
36        F: FnOnce() -> Option<(Address, AccountOverride)>,
37    {
38        if let Some((add, acc)) = f() {
39            self.append(add, acc)
40        } else {
41            self
42        }
43    }
44
45    /// Apply a function to the builder, returning the modified builder.
46    pub fn apply<F>(self, f: F) -> Self
47    where
48        F: FnOnce(Self) -> Self,
49    {
50        f(self)
51    }
52
53    /// Adds multiple account overrides from an iterator.
54    pub fn extend<I>(mut self, account_overrides: I) -> Self
55    where
56        I: IntoIterator<Item = (Address, AccountOverride)>,
57    {
58        self.overrides.extend(account_overrides);
59        self
60    }
61
62    /// Get the underlying `StateOverride`.
63    pub fn build(self) -> StateOverride {
64        self.overrides
65    }
66
67    /// Configures an account override with a balance.
68    pub fn with_balance(mut self, address: Address, balance: U256) -> Self {
69        self.overrides.entry(address).or_default().set_balance(balance);
70        self
71    }
72
73    /// Configures an account override with a nonce.
74    pub fn with_nonce(mut self, address: Address, nonce: u64) -> Self {
75        self.overrides.entry(address).or_default().set_nonce(nonce);
76        self
77    }
78
79    /// Configures an account override with bytecode.
80    pub fn with_code(mut self, address: Address, code: impl Into<Bytes>) -> Self {
81        self.overrides.entry(address).or_default().set_code(code);
82        self
83    }
84
85    /// Configures an account override with state overrides.
86    pub fn with_state(
87        mut self,
88        address: Address,
89        state: impl IntoIterator<Item = (B256, B256)>,
90    ) -> Self {
91        self.overrides.entry(address).or_default().set_state(state);
92        self
93    }
94
95    /// Configures an account override with state diffs.
96    pub fn with_state_diff(
97        mut self,
98        address: Address,
99        state_diff: impl IntoIterator<Item = (B256, B256)>,
100    ) -> Self {
101        self.overrides.entry(address).or_default().set_state_diff(state_diff);
102        self
103    }
104}
105
106impl FromIterator<(Address, AccountOverride)> for StateOverridesBuilder {
107    fn from_iter<T: IntoIterator<Item = (Address, AccountOverride)>>(iter: T) -> Self {
108        Self::new(StateOverride::from_iter(iter))
109    }
110}
111
112/// A set of account overrides
113pub type StateOverride = AddressHashMap<AccountOverride>;
114
115/// Allows converting `StateOverridesBuilder` directly into `StateOverride`.
116impl From<StateOverridesBuilder> for StateOverride {
117    fn from(builder: StateOverridesBuilder) -> Self {
118        builder.overrides
119    }
120}
121/// Custom account override used in call
122#[derive(Clone, Debug, Default, PartialEq, Eq)]
123#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
124#[cfg_attr(feature = "serde", serde(default, rename_all = "camelCase", deny_unknown_fields))]
125pub struct AccountOverride {
126    /// Fake balance to set for the account before executing the call.
127    #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
128    pub balance: Option<U256>,
129    /// Fake nonce to set for the account before executing the call.
130    #[cfg_attr(
131        feature = "serde",
132        serde(
133            default,
134            skip_serializing_if = "Option::is_none",
135            with = "alloy_serde::quantity::opt"
136        )
137    )]
138    pub nonce: Option<u64>,
139    /// Fake EVM bytecode to inject into the account before executing the call.
140    #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
141    pub code: Option<Bytes>,
142    /// Fake key-value mapping to override all slots in the account storage before executing the
143    /// call.
144    #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
145    pub state: Option<B256HashMap<B256>>,
146    /// Fake key-value mapping to override individual slots in the account storage before executing
147    /// the call.
148    #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
149    pub state_diff: Option<B256HashMap<B256>>,
150    /// Moves addresses precompile into the specified address. This move is done before the 'code'
151    /// override is set. When the specified address is not a precompile, the behaviour is undefined
152    /// and different clients might behave differently.
153    #[cfg_attr(
154        feature = "serde",
155        serde(
156            default,
157            skip_serializing_if = "Option::is_none",
158            rename = "movePrecompileToAddress"
159        )
160    )]
161    pub move_precompile_to: Option<Address>,
162}
163
164impl AccountOverride {
165    /// Configures the bytecode override
166    pub fn with_code(mut self, code: impl Into<Bytes>) -> Self {
167        self.code = Some(code.into());
168        self
169    }
170
171    /// Configures the state overrides
172    pub fn with_state(mut self, state: impl IntoIterator<Item = (B256, B256)>) -> Self {
173        self.state = Some(state.into_iter().collect());
174        self
175    }
176
177    /// Configures the state diffs
178    pub fn with_state_diff(mut self, state_diff: impl IntoIterator<Item = (B256, B256)>) -> Self {
179        self.state_diff = Some(state_diff.into_iter().collect());
180        self
181    }
182
183    /// Configures the balance override
184    pub const fn with_balance(mut self, balance: U256) -> Self {
185        self.balance = Some(balance);
186        self
187    }
188
189    /// Configures the nonce override
190    pub const fn with_nonce(mut self, nonce: u64) -> Self {
191        self.nonce = Some(nonce);
192        self
193    }
194
195    /// Sets the bytecode override in place.
196    pub fn set_code(&mut self, code: impl Into<Bytes>) {
197        self.code = Some(code.into());
198    }
199
200    /// Sets the state overrides in place.
201    pub fn set_state(&mut self, state: impl IntoIterator<Item = (B256, B256)>) {
202        self.state = Some(state.into_iter().collect());
203    }
204
205    /// Sets the state diffs in place.
206    pub fn set_state_diff(&mut self, state_diff: impl IntoIterator<Item = (B256, B256)>) {
207        self.state_diff = Some(state_diff.into_iter().collect());
208    }
209
210    /// Sets the balance override in place.
211    pub fn set_balance(&mut self, balance: U256) {
212        self.balance = Some(balance);
213    }
214
215    /// Sets the nonce override in place.
216    pub fn set_nonce(&mut self, nonce: u64) {
217        self.nonce = Some(nonce);
218    }
219
220    /// Sets the move precompile address in place.
221    pub fn set_move_precompile_to(&mut self, address: Address) {
222        self.move_precompile_to = Some(address);
223    }
224
225    /// Conditionally sets the bytecode override and returns self.
226    pub fn with_code_opt(mut self, code: Option<impl Into<Bytes>>) -> Self {
227        if let Some(code) = code {
228            self.code = Some(code.into());
229        }
230        self
231    }
232
233    /// Conditionally sets the balance override and returns self.
234    pub const fn with_balance_opt(mut self, balance: Option<U256>) -> Self {
235        if let Some(balance) = balance {
236            self.balance = Some(balance);
237        }
238        self
239    }
240
241    /// Conditionally sets the nonce override and returns self.
242    pub const fn with_nonce_opt(mut self, nonce: Option<u64>) -> Self {
243        if let Some(nonce) = nonce {
244            self.nonce = Some(nonce);
245        }
246        self
247    }
248
249    /// Conditionally sets the move precompile address and returns self.
250    pub const fn with_move_precompile_to_opt(mut self, address: Option<Address>) -> Self {
251        if let Some(address) = address {
252            self.move_precompile_to = Some(address);
253        }
254        self
255    }
256}
257
258/// Helper type that bundles various overrides for EVM Execution.
259///
260/// By `Default`, no overrides are included.
261#[derive(Debug, Clone, Default)]
262pub struct EvmOverrides {
263    /// Applies overrides to the state before execution.
264    pub state: Option<StateOverride>,
265    /// Applies overrides to the block before execution.
266    ///
267    /// This is a `Box` because less common and only available in debug trace endpoints.
268    pub block: Option<Box<BlockOverrides>>,
269}
270
271impl EvmOverrides {
272    /// Creates a new instance with the given overrides
273    pub const fn new(state: Option<StateOverride>, block: Option<Box<BlockOverrides>>) -> Self {
274        Self { state, block }
275    }
276
277    /// Creates a new instance with the given state overrides.
278    pub const fn state(state: Option<StateOverride>) -> Self {
279        Self { state, block: None }
280    }
281
282    /// Creates a new instance with the given block overrides.
283    pub const fn block(block: Option<Box<BlockOverrides>>) -> Self {
284        Self { state: None, block }
285    }
286
287    /// Returns `true` if the overrides contain state overrides.
288    pub const fn has_state(&self) -> bool {
289        self.state.is_some()
290    }
291
292    /// Returns `true` if the overrides contain block overrides.
293    pub const fn has_block(&self) -> bool {
294        self.block.is_some()
295    }
296
297    /// Adds state overrides to an existing instance.
298    pub fn with_state(mut self, state: StateOverride) -> Self {
299        self.state = Some(state);
300        self
301    }
302
303    /// Adds block overrides to an existing instance.
304    pub fn with_block(mut self, block: Box<BlockOverrides>) -> Self {
305        self.block = Some(block);
306        self
307    }
308}
309
310#[cfg(test)]
311mod tests {
312    use super::*;
313    use alloy_primitives::{address, map::B256HashMap, Bytes, B256, U256};
314    use similar_asserts::assert_eq;
315
316    #[test]
317    fn test_default_account_override() {
318        let acc_override = AccountOverride::default();
319        assert!(acc_override.balance.is_none());
320        assert!(acc_override.nonce.is_none());
321        assert!(acc_override.code.is_none());
322        assert!(acc_override.state.is_none());
323        assert!(acc_override.state_diff.is_none());
324    }
325
326    #[test]
327    #[cfg(feature = "serde")]
328    #[should_panic(expected = "invalid type")]
329    fn test_invalid_json_structure() {
330        let invalid_json = r#"{
331            "0x1234567890123456789012345678901234567890": {
332                "balance": true
333            }
334        }"#;
335
336        let _: StateOverride = serde_json::from_str(invalid_json).unwrap();
337    }
338
339    #[test]
340    #[cfg(feature = "serde")]
341    fn test_large_values_in_override() {
342        let large_values_json = r#"{
343            "0x1234567890123456789012345678901234567890": {
344                "balance": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
345                "nonce": "0xffffffffffffffff"
346            }
347        }"#;
348
349        let state_override: StateOverride = serde_json::from_str(large_values_json).unwrap();
350        let acc =
351            state_override.get(&address!("1234567890123456789012345678901234567890")).unwrap();
352        assert_eq!(acc.balance, Some(U256::MAX));
353        assert_eq!(acc.nonce, Some(u64::MAX));
354    }
355
356    #[test]
357    #[cfg(feature = "serde")]
358    fn test_state_override() {
359        let s = r#"{
360            "0x0000000000000000000000000000000000000124": {
361                "code": "0x6080604052348015600e575f80fd5b50600436106026575f3560e01c80632096525514602a575b5f80fd5b60306044565b604051901515815260200160405180910390f35b5f604e600242605e565b5f0360595750600190565b505f90565b5f82607757634e487b7160e01b5f52601260045260245ffd5b50069056fea2646970667358221220287f77a4262e88659e3fb402138d2ee6a7ff9ba86bae487a95aa28156367d09c64736f6c63430008140033"
362            }
363        }"#;
364        let state_override: StateOverride = serde_json::from_str(s).unwrap();
365        let acc =
366            state_override.get(&address!("0000000000000000000000000000000000000124")).unwrap();
367        assert!(acc.code.is_some());
368    }
369
370    #[test]
371    #[cfg(feature = "serde")]
372    fn test_state_override_state_diff() {
373        let s = r#"{
374                "0x1b5212AF6b76113afD94cD2B5a78a73B7d7A8222": {
375                    "balance": "0x39726378b58c400000",
376                    "stateDiff": {}
377                },
378                "0xdAC17F958D2ee523a2206206994597C13D831ec7": {
379                    "stateDiff": {
380                        "0xede27e4e7f3676edbf125879f17a896d6507958df3d57bda6219f1880cae8a41": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
381                    }
382                }
383            }"#;
384        let state_override: StateOverride = serde_json::from_str(s).unwrap();
385        let acc =
386            state_override.get(&address!("1b5212AF6b76113afD94cD2B5a78a73B7d7A8222")).unwrap();
387        assert!(acc.state_diff.is_some());
388    }
389
390    #[test]
391    fn test_set_code_in_place() {
392        let mut account_override = AccountOverride::default();
393        let code = Bytes::from(vec![0x60, 0x60, 0x60, 0x60]);
394        account_override.set_code(code.clone());
395        assert_eq!(account_override.code, Some(code));
396    }
397
398    #[test]
399    fn test_set_state_in_place() {
400        let mut account_override = AccountOverride::default();
401        let state: B256HashMap<B256> = vec![(B256::ZERO, B256::ZERO)].into_iter().collect();
402        account_override.set_state(state.clone());
403        assert_eq!(account_override.state, Some(state));
404    }
405
406    #[test]
407    fn test_set_state_diff_in_place() {
408        let mut account_override = AccountOverride::default();
409        let state_diff: B256HashMap<B256> = vec![(B256::ZERO, B256::ZERO)].into_iter().collect();
410        account_override.set_state_diff(state_diff.clone());
411        assert_eq!(account_override.state_diff, Some(state_diff));
412    }
413
414    #[test]
415    fn test_set_balance_in_place() {
416        let mut account_override = AccountOverride::default();
417        let balance = U256::from(1000);
418        account_override.set_balance(balance);
419        assert_eq!(account_override.balance, Some(balance));
420    }
421
422    #[test]
423    fn test_set_nonce_in_place() {
424        let mut account_override = AccountOverride::default();
425        let nonce = 42;
426        account_override.set_nonce(nonce);
427        assert_eq!(account_override.nonce, Some(nonce));
428    }
429
430    #[test]
431    fn test_set_move_precompile_to_in_place() {
432        let mut account_override = AccountOverride::default();
433        let address = address!("0000000000000000000000000000000000000001");
434        account_override.set_move_precompile_to(address);
435        assert_eq!(account_override.move_precompile_to, Some(address));
436    }
437
438    #[test]
439    fn test_evm_overrides_new() {
440        let state = StateOverride::default();
441        let block: Box<BlockOverrides> = Box::default();
442
443        let evm_overrides = EvmOverrides::new(Some(state.clone()), Some(block.clone()));
444
445        assert!(evm_overrides.has_state());
446        assert!(evm_overrides.has_block());
447        assert_eq!(evm_overrides.state.unwrap(), state);
448        assert_eq!(*evm_overrides.block.unwrap(), *block);
449    }
450
451    #[test]
452    fn test_evm_overrides_state() {
453        let state = StateOverride::default();
454        let evm_overrides = EvmOverrides::state(Some(state.clone()));
455
456        assert!(evm_overrides.has_state());
457        assert!(!evm_overrides.has_block());
458        assert_eq!(evm_overrides.state.unwrap(), state);
459    }
460
461    #[test]
462    fn test_evm_overrides_block() {
463        let block: Box<BlockOverrides> = Box::default();
464        let evm_overrides = EvmOverrides::block(Some(block.clone()));
465
466        assert!(!evm_overrides.has_state());
467        assert!(evm_overrides.has_block());
468        assert_eq!(*evm_overrides.block.unwrap(), *block);
469    }
470
471    #[test]
472    fn test_evm_overrides_with_state() {
473        let state = StateOverride::default();
474        let mut evm_overrides = EvmOverrides::default();
475
476        assert!(!evm_overrides.has_state());
477
478        evm_overrides = evm_overrides.with_state(state.clone());
479
480        assert!(evm_overrides.has_state());
481        assert_eq!(evm_overrides.state.unwrap(), state);
482    }
483
484    #[test]
485    fn test_evm_overrides_with_block() {
486        let block: Box<BlockOverrides> = Box::default();
487        let mut evm_overrides = EvmOverrides::default();
488
489        assert!(!evm_overrides.has_block());
490
491        evm_overrides = evm_overrides.with_block(block.clone());
492
493        assert!(evm_overrides.has_block());
494        assert_eq!(*evm_overrides.block.unwrap(), *block);
495    }
496}