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 ethereum_types::*;
21use pallet_revive_types::runtime_api::*;
22
23/// A mapping from account addresses to their state overrides, used to temporarily modify account
24/// state during `eth_call` and similar simulation methods without affecting on-chain data.
25///
26/// Each entry maps an [`Address`] to a [`StateOverride`] that specifies which parts of the
27/// account's state to replace for the duration of the call.
28///
29/// Conforms to the [Geth state override set specification](https://geth.ethereum.org/docs/interacting-with-geth/rpc/objects#state-override-set).
30#[derive(Debug, Default, Clone, Eq, PartialEq)]
31pub struct StateOverrideSet(pub BTreeMap<Address, StateOverride>);
32
33impl core::ops::Deref for StateOverrideSet {
34 type Target = BTreeMap<Address, StateOverride>;
35
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39}
40
41impl core::ops::DerefMut for StateOverrideSet {
42 fn deref_mut(&mut self) -> &mut Self::Target {
43 &mut self.0
44 }
45}
46
47impl From<StateOverrideSetV1> for StateOverrideSet {
48 fn from(value: StateOverrideSetV1) -> Self {
49 Self(
50 value
51 .0
52 .into_iter()
53 .map(|(address, overrides)| (address, overrides.into()))
54 .collect(),
55 )
56 }
57}
58
59/// Specifies how an account's storage should be overridden during a simulated call.
60///
61/// The Geth state override specification mandates that `state` and `stateDiff` are mutually
62/// exclusive. This enum encodes that constraint at the type level.
63#[derive(Debug, Clone, Eq, PartialEq)]
64pub enum StorageOverride {
65 /// Completely replaces the account's storage with the provided mapping. Any existing slots
66 /// not present in the mapping are effectively zeroed out.
67 State(BTreeMap<H256, H256>),
68 /// Patches individual storage slots without affecting the rest of the account's storage.
69 /// Only the specified slots are modified; all other existing slots remain unchanged.
70 StateDiff(BTreeMap<H256, H256>),
71}
72
73impl From<StorageOverrideV1> for StorageOverride {
74 fn from(value: StorageOverrideV1) -> Self {
75 match value {
76 StorageOverrideV1::State(state) => Self::State(state),
77 StorageOverrideV1::StateDiff(state_diff) => Self::StateDiff(state_diff),
78 }
79 }
80}
81
82/// Per-account state overrides applied during `eth_call` and similar simulation methods.
83///
84/// All fields are optional. Only the fields that are set will be overridden; the rest of the
85/// account's state is read from the chain as normal.
86///
87/// Conforms to the [Geth state override object specification](https://geth.ethereum.org/docs/interacting-with-geth/rpc/objects#state-override-set).
88#[derive(Debug, Default, Clone, Eq, PartialEq)]
89pub struct StateOverride {
90 /// Fake balance to set for the account before executing the call.
91 pub balance: Option<U256>,
92 /// Fake nonce to set for the account before executing the call.
93 pub nonce: Option<U256>,
94 /// Fake EVM bytecode to inject into the account before executing the call.
95 pub code: Option<Bytes>,
96 /// Storage override specifying either a full replacement or a partial diff. These two modes
97 /// are mutually exclusive per the Geth specification.
98 pub storage: Option<StorageOverride>,
99 /// Moves the precompile at the account's address to the specified address. Useful for
100 /// overriding a precompile's code with custom logic while still being able to invoke the
101 /// original precompile at a different address.
102 pub move_precompile_to_address: Option<Address>,
103}
104
105impl From<StateOverrideV1> for StateOverride {
106 fn from(value: StateOverrideV1) -> Self {
107 Self {
108 balance: value.balance,
109 nonce: value.nonce,
110 code: value.code,
111 storage: value.storage.map(Into::into),
112 move_precompile_to_address: value.move_precompile_to_address,
113 }
114 }
115}