evm_runtime/eval/
mod.rs

1#[macro_use]
2mod macros;
3mod system;
4
5use crate::{CallScheme, ExitReason, Handler, Opcode, Runtime};
6use alloc::vec::Vec;
7use core::cmp::min;
8use primitive_types::{H160, H256, U256};
9
10pub enum Control<H: Handler> {
11	Continue,
12	CallInterrupt(H::CallInterrupt),
13	CreateInterrupt(H::CreateInterrupt),
14	Exit(ExitReason),
15}
16
17fn handle_other<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) -> Control<H> {
18	match handler.other(opcode, &mut state.machine) {
19		Ok(()) => Control::Continue,
20		Err(e) => Control::Exit(e.into()),
21	}
22}
23
24pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) -> Control<H> {
25	match opcode {
26		Opcode::SHA3 => system::sha3(state),
27		Opcode::ADDRESS => system::address(state),
28		Opcode::BALANCE => system::balance(state, handler),
29		Opcode::SELFBALANCE => system::selfbalance(state, handler),
30		Opcode::ORIGIN => system::origin(state, handler),
31		Opcode::CALLER => system::caller(state),
32		Opcode::CALLVALUE => system::callvalue(state),
33		Opcode::GASPRICE => system::gasprice(state, handler),
34		Opcode::EXTCODESIZE => system::extcodesize(state, handler),
35		Opcode::EXTCODEHASH => system::extcodehash(state, handler),
36		Opcode::EXTCODECOPY => system::extcodecopy(state, handler),
37		Opcode::RETURNDATASIZE => system::returndatasize(state),
38		Opcode::RETURNDATACOPY => system::returndatacopy(state),
39		Opcode::BLOCKHASH => system::blockhash(state, handler),
40		Opcode::COINBASE => system::coinbase(state, handler),
41		Opcode::TIMESTAMP => system::timestamp(state, handler),
42		Opcode::NUMBER => system::number(state, handler),
43		Opcode::DIFFICULTY => system::prevrandao(state, handler),
44		Opcode::GASLIMIT => system::gaslimit(state, handler),
45		Opcode::SLOAD => system::sload(state, handler),
46		Opcode::SSTORE => system::sstore(state, handler),
47		Opcode::GAS => system::gas(state, handler),
48		Opcode::TLOAD => system::tload(state, handler),
49		Opcode::TSTORE => system::tstore(state, handler),
50		Opcode::LOG0 => system::log(state, 0, handler),
51		Opcode::LOG1 => system::log(state, 1, handler),
52		Opcode::LOG2 => system::log(state, 2, handler),
53		Opcode::LOG3 => system::log(state, 3, handler),
54		Opcode::LOG4 => system::log(state, 4, handler),
55		Opcode::SUICIDE => system::suicide(state, handler),
56		Opcode::CREATE => system::create(state, false, handler),
57		Opcode::CREATE2 => system::create(state, true, handler),
58		Opcode::CALL => system::call(state, CallScheme::Call, handler),
59		Opcode::CALLCODE => system::call(state, CallScheme::CallCode, handler),
60		Opcode::DELEGATECALL => system::call(state, CallScheme::DelegateCall, handler),
61		Opcode::STATICCALL => system::call(state, CallScheme::StaticCall, handler),
62		Opcode::CHAINID => system::chainid(state, handler),
63		Opcode::BASEFEE => system::base_fee(state, handler),
64		_ => handle_other(state, opcode, handler),
65	}
66}
67
68pub fn finish_create(
69	runtime: &mut Runtime,
70	reason: ExitReason,
71	address: Option<H160>,
72	return_data: Vec<u8>,
73) -> Result<(), ExitReason> {
74	runtime.return_data_buffer = return_data;
75	let create_address: H256 = address.map(|a| a.into()).unwrap_or_default();
76
77	match reason {
78		ExitReason::Succeed(_) => {
79			runtime.machine.stack_mut().push(create_address)?;
80			Ok(())
81		}
82		ExitReason::Revert(_) => {
83			runtime.machine.stack_mut().push(H256::default())?;
84			Ok(())
85		}
86		ExitReason::Error(_) => {
87			runtime.machine.stack_mut().push(H256::default())?;
88			Ok(())
89		}
90		ExitReason::Fatal(e) => {
91			runtime.machine.stack_mut().push(H256::default())?;
92			Err(e.into())
93		}
94	}
95}
96
97pub fn finish_call(
98	runtime: &mut Runtime,
99	out_len: U256,
100	out_offset: U256,
101	reason: ExitReason,
102	return_data: Vec<u8>,
103) -> Result<(), ExitReason> {
104	runtime.return_data_buffer = return_data;
105	let target_len = min(out_len, U256::from(runtime.return_data_buffer.len()));
106
107	match reason {
108		ExitReason::Succeed(_) => {
109			match runtime.machine.memory_mut().copy_large(
110				out_offset,
111				U256::zero(),
112				target_len,
113				&runtime.return_data_buffer[..],
114			) {
115				Ok(()) => {
116					let value = H256::from(U256::one().to_big_endian());
117					runtime.machine.stack_mut().push(value)?;
118					Ok(())
119				}
120				Err(_) => {
121					runtime.machine.stack_mut().push(H256::default())?;
122					Ok(())
123				}
124			}
125		}
126		ExitReason::Revert(_) => {
127			runtime.machine.stack_mut().push(H256::default())?;
128
129			let _ = runtime.machine.memory_mut().copy_large(
130				out_offset,
131				U256::zero(),
132				target_len,
133				&runtime.return_data_buffer[..],
134			);
135
136			Ok(())
137		}
138		ExitReason::Error(_) => {
139			runtime.machine.stack_mut().push(H256::default())?;
140
141			Ok(())
142		}
143		ExitReason::Fatal(e) => {
144			runtime.machine.stack_mut().push(H256::default())?;
145
146			Err(e.into())
147		}
148	}
149}