1use alloc::{rc::Rc, vec::Vec};
2
3use primitive_types::{H160, H256, U256};
4use sha3::{Digest, Keccak256};
5
6use crate::error::ExitError;
7
8pub trait GasState {
10 fn gas(&self) -> U256;
11}
12
13#[derive(Clone, Debug)]
15pub struct RuntimeState {
16 pub context: Context,
18 pub transaction_context: Rc<TransactionContext>,
20 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#[derive(Clone, Debug)]
44pub struct Context {
45 pub address: H160,
47 pub caller: H160,
49 pub apparent_value: U256,
51}
52
53#[derive(Clone, Debug)]
54pub struct TransactionContext {
55 pub gas_price: U256,
57 pub origin: H160,
59}
60
61#[derive(Clone, Debug)]
63pub struct Transfer {
64 pub source: H160,
66 pub target: H160,
68 pub value: U256,
70}
71
72#[derive(Clone, Debug)]
74pub struct Log {
75 pub address: H160,
76 pub topics: Vec<H256>,
77 pub data: Vec<u8>,
78}
79
80#[derive(Clone, Debug)]
82pub enum SetCodeOrigin {
83 Transaction,
84 Subcall(H160),
85}
86
87#[auto_impl::auto_impl(&, Box)]
88pub trait RuntimeEnvironment {
89 fn block_hash(&self, number: U256) -> H256;
91 fn block_number(&self) -> U256;
93 fn block_coinbase(&self) -> H160;
95 fn block_timestamp(&self) -> U256;
97 fn block_difficulty(&self) -> U256;
99 fn block_randomness(&self) -> Option<H256>;
101 fn block_gas_limit(&self) -> U256;
103 fn block_base_fee_per_gas(&self) -> U256;
105 fn chain_id(&self) -> U256;
107}
108
109#[auto_impl::auto_impl(&, Box)]
110pub trait RuntimeBaseBackend {
111 fn balance(&self, address: H160) -> U256;
113 fn code_size(&self, address: H160) -> U256 {
115 U256::from(self.code(address).len())
116 }
117 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 fn code(&self, address: H160) -> Vec<u8>;
127 fn storage(&self, address: H160, index: H256) -> H256;
129 fn transient_storage(&self, address: H160, index: H256) -> H256;
131
132 fn exists(&self, address: H160) -> bool;
134 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 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
152pub trait RuntimeBackend: RuntimeBaseBackend {
155 fn original_storage(&self, address: H160, index: H256) -> H256;
157 fn deleted(&self, address: H160) -> bool;
159 fn created(&self, address: H160) -> bool;
161 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 fn mark_hot(&mut self, address: H160, kind: TouchKind);
169 fn mark_storage_hot(&mut self, address: H160, index: H256);
170 fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError>;
172 fn set_transient_storage(
174 &mut self,
175 address: H160,
176 index: H256,
177 value: H256,
178 ) -> Result<(), ExitError>;
179 fn log(&mut self, log: Log) -> Result<(), ExitError>;
181 fn mark_delete_reset(&mut self, address: H160);
183 fn mark_create(&mut self, address: H160);
185 fn reset_storage(&mut self, address: H160);
187 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 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 fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError>;
204}