cfx_rpc_eth_types/
state.rs

1// Copyright 2023-2024 Paradigm.xyz
2// This file is part of reth.
3// Reth is a modular, contributor-friendly and blazing-fast implementation of
4// the Ethereum protocol
5
6// Permission is hereby granted, free of charge, to any
7// person obtaining a copy of this software and associated
8// documentation files (the "Software"), to deal in the
9// Software without restriction, including without
10// limitation the rights to use, copy, modify, merge,
11// publish, distribute, sublicense, and/or sell copies of
12// the Software, and to permit persons to whom the Software
13// is furnished to do so, subject to the following
14// conditions:
15
16// The above copyright notice and this permission notice
17// shall be included in all copies or substantial portions
18// of the Software.
19
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
21// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
22// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
23// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
24// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
27// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28// DEALINGS IN THE SOFTWARE.
29use crate::BlockOverrides;
30use cfx_bytes::Bytes;
31use cfx_rpc_primitives::Bytes as RpcBytes;
32use cfx_types::{Address, H256, U256, U64};
33use serde::{Deserialize, Serialize};
34use std::collections::HashMap;
35
36/// A set of account overrides
37pub type RpcStateOverride = HashMap<Address, RpcAccountOverride>;
38
39/// Custom account override used in rpc call
40#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
41#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
42pub struct RpcAccountOverride {
43    /// Fake balance to set for the account before executing the call.
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub balance: Option<U256>,
46    /// Fake nonce to set for the account before executing the call.
47    #[serde(default, skip_serializing_if = "Option::is_none")]
48    pub nonce: Option<U64>,
49    /// Fake EVM bytecode to inject into the account before executing the call.
50    #[serde(default, skip_serializing_if = "Option::is_none")]
51    pub code: Option<RpcBytes>,
52    /// Fake key-value mapping to override all slots in the account storage
53    /// before executing the call.
54    #[serde(default, skip_serializing_if = "Option::is_none")]
55    pub state: Option<HashMap<H256, H256>>,
56    /// Fake key-value mapping to override individual slots in the account
57    /// storage before executing the call.
58    #[serde(default, skip_serializing_if = "Option::is_none")]
59    pub state_diff: Option<HashMap<H256, H256>>,
60    /// Moves addresses precompile into the specified address. This move is
61    /// done before the 'code' override is set. When the specified address
62    /// is not a precompile, the behaviour is undefined and different
63    /// clients might behave differently.
64    #[serde(
65        default,
66        skip_serializing_if = "Option::is_none",
67        rename = "movePrecompileToAddress"
68    )]
69    pub move_precompile_to: Option<Address>,
70}
71
72#[derive(Clone, Debug, PartialEq, Eq)]
73pub enum AccountStateOverrideMode {
74    State(HashMap<H256, H256>),
75    Diff(HashMap<H256, H256>),
76    None,
77}
78
79#[derive(Clone, Debug, PartialEq, Eq)]
80pub struct AccountOverride {
81    pub balance: Option<U256>,
82    pub nonce: Option<U64>,
83    pub code: Option<Bytes>,
84    pub state: AccountStateOverrideMode,
85    pub move_precompile_to: Option<Address>,
86}
87
88impl TryFrom<RpcAccountOverride> for AccountOverride {
89    type Error = &'static str;
90
91    fn try_from(value: RpcAccountOverride) -> Result<Self, Self::Error> {
92        Ok(Self {
93            balance: value.balance,
94            nonce: value.nonce,
95            code: value.code.map(|v| v.into()),
96            state: match (value.state, value.state_diff) {
97                (Some(state), None) => AccountStateOverrideMode::State(state),
98                (None, Some(diff)) => AccountStateOverrideMode::Diff(diff),
99                (None, None) => AccountStateOverrideMode::None,
100                _ => return Err("state and stateDiff are mutually exclusive"),
101            },
102            move_precompile_to: value.move_precompile_to,
103        })
104    }
105}
106
107pub type StateOverride = HashMap<Address, AccountOverride>;
108
109/// Helper type that bundles various overrides for EVM Execution.
110///
111/// By `Default`, no overrides are included.
112#[derive(Debug, Clone, Default)]
113pub struct EvmOverrides {
114    /// Applies overrides to the state before execution.
115    pub state: Option<StateOverride>,
116    /// Applies overrides to the block before execution.
117    ///
118    /// This is a `Box` because less common and only available in debug trace
119    /// endpoints.
120    pub block: Option<Box<BlockOverrides>>,
121}
122
123impl EvmOverrides {
124    /// Creates a new instance with the given overrides
125    pub const fn new(
126        state: Option<StateOverride>, block: Option<Box<BlockOverrides>>,
127    ) -> Self {
128        Self { state, block }
129    }
130
131    /// Creates a new instance with the given state overrides.
132    pub const fn state(state: Option<StateOverride>) -> Self {
133        Self { state, block: None }
134    }
135
136    /// Creates a new instance with the given block overrides.
137    pub const fn block(block: Option<Box<BlockOverrides>>) -> Self {
138        Self { state: None, block }
139    }
140
141    /// Returns `true` if the overrides contain state overrides.
142    pub const fn has_state(&self) -> bool { self.state.is_some() }
143
144    /// Returns `true` if the overrides contain block overrides.
145    pub const fn has_block(&self) -> bool { self.block.is_some() }
146
147    pub const fn is_none(&self) -> bool {
148        self.state.is_none() && self.block.is_none()
149    }
150
151    /// Adds state overrides to an existing instance.
152    pub fn with_state(mut self, state: StateOverride) -> Self {
153        self.state = Some(state);
154        self
155    }
156
157    /// Adds block overrides to an existing instance.
158    pub fn with_block(mut self, block: Box<BlockOverrides>) -> Self {
159        self.block = Some(block);
160        self
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167    #[cfg(feature = "serde")]
168    use cfx_types::address_util::hex_to_address;
169    use similar_asserts::assert_eq;
170
171    #[test]
172    fn test_default_account_override() {
173        let acc_override = RpcAccountOverride::default();
174        assert!(acc_override.balance.is_none());
175        assert!(acc_override.nonce.is_none());
176        assert!(acc_override.code.is_none());
177        assert!(acc_override.state.is_none());
178        assert!(acc_override.state_diff.is_none());
179    }
180
181    #[test]
182    #[cfg(feature = "serde")]
183    #[should_panic(expected = "invalid type")]
184    fn test_invalid_json_structure() {
185        let invalid_json = r#"{
186            "0x1234567890123456789012345678901234567890": {
187                "balance": true
188            }
189        }"#;
190
191        let _: RpcStateOverride = serde_json::from_str(invalid_json).unwrap();
192    }
193
194    #[test]
195    #[cfg(feature = "serde")]
196    fn test_large_values_in_override() {
197        let large_values_json = r#"{
198            "0x1234567890123456789012345678901234567890": {
199                "balance": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
200                "nonce": "0xffffffffffffffff"
201            }
202        }"#;
203
204        let state_override: RpcStateOverride =
205            serde_json::from_str(large_values_json).unwrap();
206        let acc = state_override
207            .get(
208                &hex_to_address("1234567890123456789012345678901234567890")
209                    .unwrap(),
210            )
211            .unwrap();
212        assert_eq!(acc.balance, Some(U256::MAX));
213        assert_eq!(acc.nonce, Some(U64::from(u64::MAX)));
214    }
215
216    #[test]
217    #[cfg(feature = "serde")]
218    fn test_state_override() {
219        let s = r#"{
220            "0x0000000000000000000000000000000000000124": {
221                "code": "0x6080604052348015600e575f80fd5b50600436106026575f3560e01c80632096525514602a575b5f80fd5b60306044565b604051901515815260200160405180910390f35b5f604e600242605e565b5f0360595750600190565b505f90565b5f82607757634e487b7160e01b5f52601260045260245ffd5b50069056fea2646970667358221220287f77a4262e88659e3fb402138d2ee6a7ff9ba86bae487a95aa28156367d09c64736f6c63430008140033"
222            }
223        }"#;
224        let state_override: RpcStateOverride = serde_json::from_str(s).unwrap();
225        let acc = state_override
226            .get(
227                &hex_to_address("0000000000000000000000000000000000000124")
228                    .unwrap(),
229            )
230            .unwrap();
231        assert!(acc.code.is_some());
232    }
233
234    #[test]
235    #[cfg(feature = "serde")]
236    fn test_state_override_state_diff() {
237        let s = r#"{
238                "0x1b5212AF6b76113afD94cD2B5a78a73B7d7A8222": {
239                    "balance": "0x39726378b58c400000",
240                    "stateDiff": {}
241                },
242                "0xdAC17F958D2ee523a2206206994597C13D831ec7": {
243                    "stateDiff": {
244                        "0xede27e4e7f3676edbf125879f17a896d6507958df3d57bda6219f1880cae8a41": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
245                    }
246                }
247            }"#;
248        let state_override: RpcStateOverride = serde_json::from_str(s).unwrap();
249        let acc = state_override
250            .get(
251                &hex_to_address("1b5212AF6b76113afD94cD2B5a78a73B7d7A8222")
252                    .unwrap(),
253            )
254            .unwrap();
255        assert!(acc.state_diff.is_some());
256    }
257
258    #[test]
259    fn test_evm_overrides_new() {
260        let state = StateOverride::default();
261        let block: Box<BlockOverrides> = Box::default();
262
263        let evm_overrides =
264            EvmOverrides::new(Some(state.clone()), Some(block.clone()));
265
266        assert!(evm_overrides.has_state());
267        assert!(evm_overrides.has_block());
268        assert_eq!(evm_overrides.state.unwrap(), state);
269        assert_eq!(*evm_overrides.block.unwrap(), *block);
270    }
271
272    #[test]
273    fn test_evm_overrides_state() {
274        let state = StateOverride::default();
275        let evm_overrides = EvmOverrides::state(Some(state.clone()));
276
277        assert!(evm_overrides.has_state());
278        assert!(!evm_overrides.has_block());
279        assert_eq!(evm_overrides.state.unwrap(), state);
280    }
281
282    #[test]
283    fn test_evm_overrides_block() {
284        let block: Box<BlockOverrides> = Box::default();
285        let evm_overrides = EvmOverrides::block(Some(block.clone()));
286
287        assert!(!evm_overrides.has_state());
288        assert!(evm_overrides.has_block());
289        assert_eq!(*evm_overrides.block.unwrap(), *block);
290    }
291
292    #[test]
293    fn test_evm_overrides_with_state() {
294        let state = StateOverride::default();
295        let mut evm_overrides = EvmOverrides::default();
296
297        assert!(!evm_overrides.has_state());
298
299        evm_overrides = evm_overrides.with_state(state.clone());
300
301        assert!(evm_overrides.has_state());
302        assert_eq!(evm_overrides.state.unwrap(), state);
303    }
304
305    #[test]
306    fn test_evm_overrides_with_block() {
307        let block: Box<BlockOverrides> = Box::default();
308        let mut evm_overrides = EvmOverrides::default();
309
310        assert!(!evm_overrides.has_block());
311
312        evm_overrides = evm_overrides.with_block(block.clone());
313
314        assert!(evm_overrides.has_block());
315        assert_eq!(*evm_overrides.block.unwrap(), *block);
316    }
317}