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}