evm_interpreter/
runtime.rs

1use alloc::{rc::Rc, vec::Vec};
2
3use primitive_types::{H160, H256, U256};
4use sha3::{Digest, Keccak256};
5
6use crate::error::ExitError;
7
8/// Gas state.
9pub trait GasState {
10	fn gas(&self) -> U256;
11}
12
13/// Runtime state.
14#[derive(Clone, Debug)]
15pub struct RuntimeState {
16	/// Runtime context.
17	pub context: Context,
18	/// Transaction context.
19	pub transaction_context: Rc<TransactionContext>,
20	/// Return data buffer.
21	pub retbuf: Vec<u8>,
22}
23
24impl AsRef<Self> for RuntimeState {
25	fn as_ref(&self) -> &Self {
26		self
27	}
28}
29
30impl AsMut<Self> for RuntimeState {
31	fn as_mut(&mut self) -> &mut Self {
32		self
33	}
34}
35
36impl GasState for RuntimeState {
37	fn gas(&self) -> U256 {
38		U256::zero()
39	}
40}
41
42/// Context of the runtime.
43#[derive(Clone, Debug)]
44pub struct Context {
45	/// Execution address.
46	pub address: H160,
47	/// Caller of the EVM.
48	pub caller: H160,
49	/// Apparent value of the EVM.
50	pub apparent_value: U256,
51}
52
53#[derive(Clone, Debug)]
54pub struct TransactionContext {
55	/// Gas price.
56	pub gas_price: U256,
57	/// Origin.
58	pub origin: H160,
59}
60
61/// Transfer from source to target, with given value.
62#[derive(Clone, Debug)]
63pub struct Transfer {
64	/// Source address.
65	pub source: H160,
66	/// Target address.
67	pub target: H160,
68	/// Transfer value.
69	pub value: U256,
70}
71
72/// Log
73#[derive(Clone, Debug)]
74pub struct Log {
75	pub address: H160,
76	pub topics: Vec<H256>,
77	pub data: Vec<u8>,
78}
79
80// Identify if the origin of set_code() comes from a transact or subcall.
81#[derive(Clone, Debug)]
82pub enum SetCodeOrigin {
83	Transaction,
84	Subcall(H160),
85}
86
87#[auto_impl::auto_impl(&, Box)]
88pub trait RuntimeEnvironment {
89	/// Get environmental block hash.
90	fn block_hash(&self, number: U256) -> H256;
91	/// Get environmental block number.
92	fn block_number(&self) -> U256;
93	/// Get environmental coinbase.
94	fn block_coinbase(&self) -> H160;
95	/// Get environmental block timestamp.
96	fn block_timestamp(&self) -> U256;
97	/// Get environmental block difficulty.
98	fn block_difficulty(&self) -> U256;
99	/// Get environmental block randomness.
100	fn block_randomness(&self) -> Option<H256>;
101	/// Get environmental gas limit.
102	fn block_gas_limit(&self) -> U256;
103	/// Environmental block base fee.
104	fn block_base_fee_per_gas(&self) -> U256;
105	/// Get environmental chain ID.
106	fn chain_id(&self) -> U256;
107}
108
109#[auto_impl::auto_impl(&, Box)]
110pub trait RuntimeBaseBackend {
111	/// Get balance of address.
112	fn balance(&self, address: H160) -> U256;
113	/// Get code size of address.
114	fn code_size(&self, address: H160) -> U256 {
115		U256::from(self.code(address).len())
116	}
117	/// Get code hash of address.
118	fn code_hash(&self, address: H160) -> H256 {
119		if !self.is_empty(address) {
120			H256::from_slice(&Keccak256::digest(&self.code(address)[..]))
121		} else {
122			H256::default()
123		}
124	}
125	/// Get code of address.
126	fn code(&self, address: H160) -> Vec<u8>;
127	/// Get storage value of address at index.
128	fn storage(&self, address: H160, index: H256) -> H256;
129	/// Get transient storage value of address at index.
130	fn transient_storage(&self, address: H160, index: H256) -> H256;
131
132	/// Check whether an address exists. Used pre EIP161.
133	fn exists(&self, address: H160) -> bool;
134	/// Check whether an address is empty. Used after EIP161. Note that the meaning is opposite.
135	fn is_empty(&self, address: H160) -> bool {
136		self.balance(address) == U256::zero()
137			&& self.code_size(address) == U256::zero()
138			&& self.nonce(address) == U256::zero()
139	}
140
141	/// Get the current nonce of an account.
142	fn nonce(&self, address: H160) -> U256;
143}
144
145#[derive(Debug, Clone, Eq, PartialEq)]
146pub enum TouchKind {
147	StateChange,
148	Coinbase,
149	Access,
150}
151
152/// The distinguish between `RuntimeBaseBackend` and `RuntimeBackend` is for the implementation of
153/// overlays.
154pub trait RuntimeBackend: RuntimeBaseBackend {
155	/// Get original storage value of address at index.
156	fn original_storage(&self, address: H160, index: H256) -> H256;
157	/// Check whether an address has already been deleted.
158	fn deleted(&self, address: H160) -> bool;
159	/// Check whether an address has already been created in the transaction.
160	fn created(&self, address: H160) -> bool;
161	/// Checks if the address or (address, index) pair has been previously accessed.
162	fn is_cold(&self, address: H160, index: Option<H256>) -> bool;
163	fn is_hot(&self, address: H160, index: Option<H256>) -> bool {
164		!self.is_cold(address, index)
165	}
166
167	/// Mark an address or (address, index) pair as hot.
168	fn mark_hot(&mut self, address: H160, kind: TouchKind);
169	fn mark_storage_hot(&mut self, address: H160, index: H256);
170	/// Set storage value of address at index.
171	fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError>;
172	/// Set transient storage value of address at index, transient storage gets discarded after every transaction. (see EIP-1153)
173	fn set_transient_storage(
174		&mut self,
175		address: H160,
176		index: H256,
177		value: H256,
178	) -> Result<(), ExitError>;
179	/// Create a log owned by address with given topics and data.
180	fn log(&mut self, log: Log) -> Result<(), ExitError>;
181	/// Mark an address to be deleted and its balance to be reset.
182	fn mark_delete_reset(&mut self, address: H160);
183	// Mark an address as created in the current transaction.
184	fn mark_create(&mut self, address: H160);
185	/// Fully delete storages of an account.
186	fn reset_storage(&mut self, address: H160);
187	/// Set code of an account.
188	fn set_code(
189		&mut self,
190		address: H160,
191		code: Vec<u8>,
192		origin: SetCodeOrigin,
193	) -> Result<(), ExitError>;
194	fn deposit(&mut self, target: H160, value: U256);
195	fn withdrawal(&mut self, source: H160, value: U256) -> Result<(), ExitError>;
196	/// Initiate a transfer.
197	fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> {
198		self.withdrawal(transfer.source, transfer.value)?;
199		self.deposit(transfer.target, transfer.value);
200		Ok(())
201	}
202	/// Increase the nonce value.
203	fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError>;
204}