1use alloc::{rc::Rc, vec::Vec};
4
5use primitive_types::{H160, H256, U256};
6use sha3::{Digest, Keccak256};
7
8use crate::error::ExitError;
9
10pub trait GasState {
12 fn gas(&self) -> U256;
14}
15
16#[derive(Clone, Debug)]
18pub struct RuntimeState {
19 pub context: Context,
21 pub transaction_context: Rc<TransactionContext>,
23 pub retbuf: Vec<u8>,
25}
26
27#[derive(Clone, Debug)]
29#[non_exhaustive]
30pub struct RuntimeConfig {
31 pub eip161_empty_check: bool,
33 pub eip7610_create_check_storage: bool,
35 pub eip6780_suicide_only_in_same_tx: bool,
37 pub eip3651_warm_coinbase_address: bool,
39}
40
41impl RuntimeConfig {
42 pub const fn new() -> Self {
44 Self {
45 eip161_empty_check: true,
46 eip7610_create_check_storage: true,
47 eip6780_suicide_only_in_same_tx: false,
48 eip3651_warm_coinbase_address: false,
49 }
50 }
51
52 pub const fn frontier() -> Self {
54 Self {
55 eip161_empty_check: false,
56 eip6780_suicide_only_in_same_tx: false,
57 eip7610_create_check_storage: true,
58 eip3651_warm_coinbase_address: false,
59 }
60 }
61}
62
63impl Default for RuntimeConfig {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69#[derive(Clone, Debug)]
71pub struct RuntimeStateAndConfig<'config> {
72 pub state: RuntimeState,
74 pub config: &'config RuntimeConfig,
76}
77
78static DEFAULT_RUNTIME_CONFIG: RuntimeConfig = RuntimeConfig::new();
79
80impl RuntimeStateAndConfig<'static> {
81 pub fn with_default_config(state: RuntimeState) -> Self {
83 Self {
84 state,
85 config: &DEFAULT_RUNTIME_CONFIG,
86 }
87 }
88}
89
90impl AsRef<RuntimeState> for RuntimeState {
91 fn as_ref(&self) -> &RuntimeState {
92 self
93 }
94}
95
96impl<'config> AsRef<RuntimeState> for RuntimeStateAndConfig<'config> {
97 fn as_ref(&self) -> &RuntimeState {
98 &self.state
99 }
100}
101
102impl AsMut<RuntimeState> for RuntimeState {
103 fn as_mut(&mut self) -> &mut RuntimeState {
104 self
105 }
106}
107
108impl<'config> AsMut<RuntimeState> for RuntimeStateAndConfig<'config> {
109 fn as_mut(&mut self) -> &mut RuntimeState {
110 &mut self.state
111 }
112}
113
114impl<'config> AsRef<RuntimeConfig> for RuntimeStateAndConfig<'config> {
115 fn as_ref(&self) -> &RuntimeConfig {
116 self.config
117 }
118}
119
120impl GasState for RuntimeState {
121 fn gas(&self) -> U256 {
122 U256::zero()
123 }
124}
125
126impl<'config> GasState for RuntimeStateAndConfig<'config> {
127 fn gas(&self) -> U256 {
128 U256::zero()
129 }
130}
131
132#[derive(Clone, Debug)]
134pub struct Context {
135 pub address: H160,
137 pub caller: H160,
139 pub apparent_value: U256,
141}
142
143#[derive(Clone, Debug)]
145pub struct TransactionContext {
146 pub gas_price: U256,
148 pub origin: H160,
150}
151
152#[derive(Clone, Debug)]
154pub struct Transfer {
155 pub source: H160,
157 pub target: H160,
159 pub value: U256,
161}
162
163#[derive(Clone, Debug)]
165pub struct Log {
166 pub address: H160,
168 pub topics: Vec<H256>,
170 pub data: Vec<u8>,
172}
173
174#[derive(Clone, Debug)]
176pub enum SetCodeOrigin {
177 Transaction,
179 Subcall(H160),
181}
182
183#[auto_impl::auto_impl(&, Box)]
185pub trait RuntimeEnvironment {
186 fn block_hash(&self, number: U256) -> H256;
188 fn block_number(&self) -> U256;
190 fn block_coinbase(&self) -> H160;
192 fn block_timestamp(&self) -> U256;
194 fn block_difficulty(&self) -> U256;
196 fn block_randomness(&self) -> Option<H256>;
198 fn block_gas_limit(&self) -> U256;
200 fn block_base_fee_per_gas(&self) -> U256;
202 fn blob_versioned_hash(&self, index: U256) -> H256;
204 fn blob_base_fee_per_gas(&self) -> U256;
206 fn chain_id(&self) -> U256;
208}
209
210#[auto_impl::auto_impl(&, Box)]
212pub trait RuntimeBaseBackend {
213 fn balance(&self, address: H160) -> U256;
215 fn code_size(&self, address: H160) -> U256 {
217 U256::from(self.code(address).len())
218 }
219 fn code_hash(&self, address: H160) -> H256 {
223 if self.exists(address) {
224 H256::from_slice(&Keccak256::digest(&self.code(address)[..]))
225 } else {
226 H256::default()
227 }
228 }
229 fn code(&self, address: H160) -> Vec<u8>;
231 fn storage(&self, address: H160, index: H256) -> H256;
233 fn transient_storage(&self, address: H160, index: H256) -> H256;
235
236 fn exists(&self, address: H160) -> bool;
241 fn can_create(&self, address: H160) -> bool {
243 self.code_size(address) == U256::zero() && self.nonce(address) == U256::zero()
244 }
245
246 fn nonce(&self, address: H160) -> U256;
248}
249
250#[derive(Debug, Clone, Eq, PartialEq)]
252pub enum TouchKind {
253 StateChange,
255 Coinbase,
257 Access,
259}
260
261pub trait RuntimeBackend: RuntimeBaseBackend {
264 fn original_storage(&self, address: H160, index: H256) -> H256;
266 fn deleted(&self, address: H160) -> bool;
268 fn created(&self, address: H160) -> bool;
270 fn is_cold(&self, address: H160, index: Option<H256>) -> bool;
272 fn is_hot(&self, address: H160, index: Option<H256>) -> bool {
274 !self.is_cold(address, index)
275 }
276
277 fn mark_hot(&mut self, address: H160, kind: TouchKind);
279 fn mark_storage_hot(&mut self, address: H160, index: H256);
281 fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError>;
283 fn set_transient_storage(
285 &mut self,
286 address: H160,
287 index: H256,
288 value: H256,
289 ) -> Result<(), ExitError>;
290 fn log(&mut self, log: Log) -> Result<(), ExitError>;
292 fn mark_delete_reset(&mut self, address: H160);
294 fn mark_create(&mut self, address: H160);
296 fn reset_storage(&mut self, address: H160);
298 fn set_code(
300 &mut self,
301 address: H160,
302 code: Vec<u8>,
303 origin: SetCodeOrigin,
304 ) -> Result<(), ExitError>;
305 fn deposit(&mut self, target: H160, value: U256);
307 fn withdrawal(&mut self, source: H160, value: U256) -> Result<(), ExitError>;
309 fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> {
311 self.withdrawal(transfer.source, transfer.value)?;
312 self.deposit(transfer.target, transfer.value);
313 Ok(())
314 }
315 fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError>;
317}