pallet_revive/evm/api/state_overrides.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use super::Bytes;
19use alloc::collections::BTreeMap;
20use codec::{Decode, Encode};
21use ethereum_types::*;
22use scale_info::TypeInfo;
23use serde::{Deserialize, Serialize};
24
25/// A mapping from account addresses to their state overrides, used to temporarily modify account
26/// state during `eth_call` and similar simulation methods without affecting on-chain data.
27///
28/// Each entry maps an [`Address`] to a [`StateOverride`] that specifies which parts of the
29/// account's state to replace for the duration of the call.
30///
31/// Conforms to the [Geth state override set specification](https://geth.ethereum.org/docs/interacting-with-geth/rpc/objects#state-override-set).
32#[derive(
33 Debug, Default, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq,
34)]
35pub struct StateOverrideSet(pub BTreeMap<Address, StateOverride>);
36
37impl core::ops::Deref for StateOverrideSet {
38 type Target = BTreeMap<Address, StateOverride>;
39
40 fn deref(&self) -> &Self::Target {
41 &self.0
42 }
43}
44
45impl core::ops::DerefMut for StateOverrideSet {
46 fn deref_mut(&mut self) -> &mut Self::Target {
47 &mut self.0
48 }
49}
50
51/// Specifies how an account's storage should be overridden during a simulated call.
52///
53/// The Geth state override specification mandates that `state` and `stateDiff` are mutually
54/// exclusive. This enum encodes that constraint at the type level.
55#[derive(Debug, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq)]
56#[serde(rename_all = "camelCase")]
57pub enum StorageOverride {
58 /// Completely replaces the account's storage with the provided mapping. Any existing slots
59 /// not present in the mapping are effectively zeroed out.
60 State(BTreeMap<H256, H256>),
61 /// Patches individual storage slots without affecting the rest of the account's storage.
62 /// Only the specified slots are modified; all other existing slots remain unchanged.
63 StateDiff(BTreeMap<H256, H256>),
64}
65
66/// Per-account state overrides applied during `eth_call` and similar simulation methods.
67///
68/// All fields are optional. Only the fields that are set will be overridden; the rest of the
69/// account's state is read from the chain as normal.
70///
71/// Conforms to the [Geth state override object specification](https://geth.ethereum.org/docs/interacting-with-geth/rpc/objects#state-override-set).
72#[derive(
73 Debug, Default, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq,
74)]
75#[serde(rename_all = "camelCase")]
76pub struct StateOverride {
77 /// Fake balance to set for the account before executing the call.
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub balance: Option<U256>,
80 /// Fake nonce to set for the account before executing the call.
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub nonce: Option<U256>,
83 /// Fake EVM bytecode to inject into the account before executing the call.
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub code: Option<Bytes>,
86 /// Storage override specifying either a full replacement or a partial diff. These two modes
87 /// are mutually exclusive per the Geth specification.
88 #[serde(flatten)]
89 pub storage: Option<StorageOverride>,
90 /// Moves the precompile at the account's address to the specified address. Useful for
91 /// overriding a precompile's code with custom logic while still being able to invoke the
92 /// original precompile at a different address.
93 #[serde(skip_serializing_if = "Option::is_none")]
94 pub move_precompile_to_address: Option<Address>,
95}