cfx_rpc_eth_types/
state.rs1use 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
36pub type RpcStateOverride = HashMap<Address, RpcAccountOverride>;
38
39#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
41#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
42pub struct RpcAccountOverride {
43 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub balance: Option<U256>,
46 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub nonce: Option<U64>,
49 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub code: Option<RpcBytes>,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub state: Option<HashMap<H256, H256>>,
56 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub state_diff: Option<HashMap<H256, H256>>,
60 #[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#[derive(Debug, Clone, Default)]
113pub struct EvmOverrides {
114 pub state: Option<StateOverride>,
116 pub block: Option<Box<BlockOverrides>>,
121}
122
123impl EvmOverrides {
124 pub const fn new(
126 state: Option<StateOverride>, block: Option<Box<BlockOverrides>>,
127 ) -> Self {
128 Self { state, block }
129 }
130
131 pub const fn state(state: Option<StateOverride>) -> Self {
133 Self { state, block: None }
134 }
135
136 pub const fn block(block: Option<Box<BlockOverrides>>) -> Self {
138 Self { state: None, block }
139 }
140
141 pub const fn has_state(&self) -> bool { self.state.is_some() }
143
144 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 pub fn with_state(mut self, state: StateOverride) -> Self {
153 self.state = Some(state);
154 self
155 }
156
157 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}