1#[macro_use]
4pub mod macros;
5pub mod arithmetic;
7pub mod bitwise;
9pub mod block_info;
11pub mod contract;
13pub mod control;
15pub mod host;
17pub mod i256;
19pub mod memory;
21pub mod stack;
23pub mod system;
25pub mod tx_info;
27pub mod utility;
29
30use primitives::hardfork::SpecId;
31
32use crate::{gas, interpreter_types::InterpreterTypes, Host, InstructionContext};
33
34#[derive(Debug)]
36pub struct Instruction<W: InterpreterTypes, H: ?Sized> {
37 fn_: fn(InstructionContext<'_, H, W>),
38 static_gas: u64,
39}
40
41impl<W: InterpreterTypes, H: Host + ?Sized> Instruction<W, H> {
42 #[inline]
44 pub const fn new(fn_: fn(InstructionContext<'_, H, W>), static_gas: u64) -> Self {
45 Self { fn_, static_gas }
46 }
47
48 #[inline]
50 pub const fn unknown() -> Self {
51 Self {
52 fn_: control::unknown,
53 static_gas: 0,
54 }
55 }
56
57 #[inline(always)]
59 pub fn execute(self, ctx: InstructionContext<'_, H, W>) {
60 (self.fn_)(ctx)
61 }
62
63 #[inline(always)]
65 pub const fn static_gas(&self) -> u64 {
66 self.static_gas
67 }
68}
69
70impl<W: InterpreterTypes, H: Host + ?Sized> Copy for Instruction<W, H> {}
71impl<W: InterpreterTypes, H: Host + ?Sized> Clone for Instruction<W, H> {
72 fn clone(&self) -> Self {
73 *self
74 }
75}
76
77pub type InstructionTable<W, H> = [Instruction<W, H>; 256];
79
80#[inline]
82pub const fn instruction_table<WIRE: InterpreterTypes, H: Host>() -> [Instruction<WIRE, H>; 256] {
83 const { instruction_table_impl::<WIRE, H>() }
84}
85
86#[inline]
88pub fn instruction_table_gas_changes_spec<WIRE: InterpreterTypes, H: Host>(
89 spec: SpecId,
90) -> [Instruction<WIRE, H>; 256] {
91 use bytecode::opcode::*;
92 use SpecId::*;
93 let mut table = instruction_table();
94
95 if spec.is_enabled_in(TANGERINE) {
96 table[SLOAD as usize].static_gas = 200;
98 table[BALANCE as usize].static_gas = 400;
99 table[EXTCODESIZE as usize].static_gas = 700;
100 table[EXTCODECOPY as usize].static_gas = 700;
101 table[CALL as usize].static_gas = 700;
102 table[CALLCODE as usize].static_gas = 700;
103 table[DELEGATECALL as usize].static_gas = 700;
104 table[STATICCALL as usize].static_gas = 700;
105 table[SELFDESTRUCT as usize].static_gas = 5000;
106 }
107
108 if spec.is_enabled_in(ISTANBUL) {
109 table[SLOAD as usize].static_gas = gas::ISTANBUL_SLOAD_GAS;
111 table[BALANCE as usize].static_gas = 700;
112 table[EXTCODEHASH as usize].static_gas = 700;
113 }
114
115 if spec.is_enabled_in(BERLIN) {
116 table[SLOAD as usize].static_gas = gas::WARM_STORAGE_READ_COST;
118 table[BALANCE as usize].static_gas = gas::WARM_STORAGE_READ_COST;
119 table[EXTCODESIZE as usize].static_gas = gas::WARM_STORAGE_READ_COST;
120 table[EXTCODEHASH as usize].static_gas = gas::WARM_STORAGE_READ_COST;
121 table[EXTCODECOPY as usize].static_gas = gas::WARM_STORAGE_READ_COST;
122 table[CALL as usize].static_gas = gas::WARM_STORAGE_READ_COST;
123 table[CALLCODE as usize].static_gas = gas::WARM_STORAGE_READ_COST;
124 table[DELEGATECALL as usize].static_gas = gas::WARM_STORAGE_READ_COST;
125 table[STATICCALL as usize].static_gas = gas::WARM_STORAGE_READ_COST;
126 }
127
128 table
129}
130
131const fn instruction_table_impl<WIRE: InterpreterTypes, H: Host>() -> [Instruction<WIRE, H>; 256] {
132 use bytecode::opcode::*;
133 let mut table = [Instruction::unknown(); 256];
134
135 table[STOP as usize] = Instruction::new(control::stop, 0);
136 table[ADD as usize] = Instruction::new(arithmetic::add, 3);
137 table[MUL as usize] = Instruction::new(arithmetic::mul, 5);
138 table[SUB as usize] = Instruction::new(arithmetic::sub, 3);
139 table[DIV as usize] = Instruction::new(arithmetic::div, 5);
140 table[SDIV as usize] = Instruction::new(arithmetic::sdiv, 5);
141 table[MOD as usize] = Instruction::new(arithmetic::rem, 5);
142 table[SMOD as usize] = Instruction::new(arithmetic::smod, 5);
143 table[ADDMOD as usize] = Instruction::new(arithmetic::addmod, 8);
144 table[MULMOD as usize] = Instruction::new(arithmetic::mulmod, 8);
145 table[EXP as usize] = Instruction::new(arithmetic::exp, gas::EXP); table[SIGNEXTEND as usize] = Instruction::new(arithmetic::signextend, 5);
147
148 table[LT as usize] = Instruction::new(bitwise::lt, 3);
149 table[GT as usize] = Instruction::new(bitwise::gt, 3);
150 table[SLT as usize] = Instruction::new(bitwise::slt, 3);
151 table[SGT as usize] = Instruction::new(bitwise::sgt, 3);
152 table[EQ as usize] = Instruction::new(bitwise::eq, 3);
153 table[ISZERO as usize] = Instruction::new(bitwise::iszero, 3);
154 table[AND as usize] = Instruction::new(bitwise::bitand, 3);
155 table[OR as usize] = Instruction::new(bitwise::bitor, 3);
156 table[XOR as usize] = Instruction::new(bitwise::bitxor, 3);
157 table[NOT as usize] = Instruction::new(bitwise::not, 3);
158 table[BYTE as usize] = Instruction::new(bitwise::byte, 3);
159 table[SHL as usize] = Instruction::new(bitwise::shl, 3);
160 table[SHR as usize] = Instruction::new(bitwise::shr, 3);
161 table[SAR as usize] = Instruction::new(bitwise::sar, 3);
162 table[CLZ as usize] = Instruction::new(bitwise::clz, 5);
163
164 table[KECCAK256 as usize] = Instruction::new(system::keccak256, gas::KECCAK256);
165
166 table[ADDRESS as usize] = Instruction::new(system::address, 2);
167 table[BALANCE as usize] = Instruction::new(host::balance, 20);
168 table[ORIGIN as usize] = Instruction::new(tx_info::origin, 2);
169 table[CALLER as usize] = Instruction::new(system::caller, 2);
170 table[CALLVALUE as usize] = Instruction::new(system::callvalue, 2);
171 table[CALLDATALOAD as usize] = Instruction::new(system::calldataload, 3);
172 table[CALLDATASIZE as usize] = Instruction::new(system::calldatasize, 2);
173 table[CALLDATACOPY as usize] = Instruction::new(system::calldatacopy, 3);
174 table[CODESIZE as usize] = Instruction::new(system::codesize, 2);
175 table[CODECOPY as usize] = Instruction::new(system::codecopy, 3);
176
177 table[GASPRICE as usize] = Instruction::new(tx_info::gasprice, 2);
178 table[EXTCODESIZE as usize] = Instruction::new(host::extcodesize, 20);
179 table[EXTCODECOPY as usize] = Instruction::new(host::extcodecopy, 20);
180 table[RETURNDATASIZE as usize] = Instruction::new(system::returndatasize, 2);
181 table[RETURNDATACOPY as usize] = Instruction::new(system::returndatacopy, 3);
182 table[EXTCODEHASH as usize] = Instruction::new(host::extcodehash, 400);
183 table[BLOCKHASH as usize] = Instruction::new(host::blockhash, 20);
184 table[COINBASE as usize] = Instruction::new(block_info::coinbase, 2);
185 table[TIMESTAMP as usize] = Instruction::new(block_info::timestamp, 2);
186 table[NUMBER as usize] = Instruction::new(block_info::block_number, 2);
187 table[DIFFICULTY as usize] = Instruction::new(block_info::difficulty, 2);
188 table[GASLIMIT as usize] = Instruction::new(block_info::gaslimit, 2);
189 table[CHAINID as usize] = Instruction::new(block_info::chainid, 2);
190 table[SELFBALANCE as usize] = Instruction::new(host::selfbalance, 5);
191 table[BASEFEE as usize] = Instruction::new(block_info::basefee, 2);
192 table[BLOBHASH as usize] = Instruction::new(tx_info::blob_hash, 3);
193 table[BLOBBASEFEE as usize] = Instruction::new(block_info::blob_basefee, 2);
194
195 table[POP as usize] = Instruction::new(stack::pop, 2);
196 table[MLOAD as usize] = Instruction::new(memory::mload, 3);
197 table[MSTORE as usize] = Instruction::new(memory::mstore, 3);
198 table[MSTORE8 as usize] = Instruction::new(memory::mstore8, 3);
199 table[SLOAD as usize] = Instruction::new(host::sload, 50);
200 table[SSTORE as usize] = Instruction::new(host::sstore, 0);
203 table[JUMP as usize] = Instruction::new(control::jump, 8);
204 table[JUMPI as usize] = Instruction::new(control::jumpi, 10);
205 table[PC as usize] = Instruction::new(control::pc, 2);
206 table[MSIZE as usize] = Instruction::new(memory::msize, 2);
207 table[GAS as usize] = Instruction::new(system::gas, 2);
208 table[JUMPDEST as usize] = Instruction::new(control::jumpdest, 1);
209 table[TLOAD as usize] = Instruction::new(host::tload, 100);
210 table[TSTORE as usize] = Instruction::new(host::tstore, 100);
211 table[MCOPY as usize] = Instruction::new(memory::mcopy, 3); table[PUSH0 as usize] = Instruction::new(stack::push0, 2);
214 table[PUSH1 as usize] = Instruction::new(stack::push::<1, _, _>, 3);
215 table[PUSH2 as usize] = Instruction::new(stack::push::<2, _, _>, 3);
216 table[PUSH3 as usize] = Instruction::new(stack::push::<3, _, _>, 3);
217 table[PUSH4 as usize] = Instruction::new(stack::push::<4, _, _>, 3);
218 table[PUSH5 as usize] = Instruction::new(stack::push::<5, _, _>, 3);
219 table[PUSH6 as usize] = Instruction::new(stack::push::<6, _, _>, 3);
220 table[PUSH7 as usize] = Instruction::new(stack::push::<7, _, _>, 3);
221 table[PUSH8 as usize] = Instruction::new(stack::push::<8, _, _>, 3);
222 table[PUSH9 as usize] = Instruction::new(stack::push::<9, _, _>, 3);
223 table[PUSH10 as usize] = Instruction::new(stack::push::<10, _, _>, 3);
224 table[PUSH11 as usize] = Instruction::new(stack::push::<11, _, _>, 3);
225 table[PUSH12 as usize] = Instruction::new(stack::push::<12, _, _>, 3);
226 table[PUSH13 as usize] = Instruction::new(stack::push::<13, _, _>, 3);
227 table[PUSH14 as usize] = Instruction::new(stack::push::<14, _, _>, 3);
228 table[PUSH15 as usize] = Instruction::new(stack::push::<15, _, _>, 3);
229 table[PUSH16 as usize] = Instruction::new(stack::push::<16, _, _>, 3);
230 table[PUSH17 as usize] = Instruction::new(stack::push::<17, _, _>, 3);
231 table[PUSH18 as usize] = Instruction::new(stack::push::<18, _, _>, 3);
232 table[PUSH19 as usize] = Instruction::new(stack::push::<19, _, _>, 3);
233 table[PUSH20 as usize] = Instruction::new(stack::push::<20, _, _>, 3);
234 table[PUSH21 as usize] = Instruction::new(stack::push::<21, _, _>, 3);
235 table[PUSH22 as usize] = Instruction::new(stack::push::<22, _, _>, 3);
236 table[PUSH23 as usize] = Instruction::new(stack::push::<23, _, _>, 3);
237 table[PUSH24 as usize] = Instruction::new(stack::push::<24, _, _>, 3);
238 table[PUSH25 as usize] = Instruction::new(stack::push::<25, _, _>, 3);
239 table[PUSH26 as usize] = Instruction::new(stack::push::<26, _, _>, 3);
240 table[PUSH27 as usize] = Instruction::new(stack::push::<27, _, _>, 3);
241 table[PUSH28 as usize] = Instruction::new(stack::push::<28, _, _>, 3);
242 table[PUSH29 as usize] = Instruction::new(stack::push::<29, _, _>, 3);
243 table[PUSH30 as usize] = Instruction::new(stack::push::<30, _, _>, 3);
244 table[PUSH31 as usize] = Instruction::new(stack::push::<31, _, _>, 3);
245 table[PUSH32 as usize] = Instruction::new(stack::push::<32, _, _>, 3);
246
247 table[DUP1 as usize] = Instruction::new(stack::dup::<1, _, _>, 3);
248 table[DUP2 as usize] = Instruction::new(stack::dup::<2, _, _>, 3);
249 table[DUP3 as usize] = Instruction::new(stack::dup::<3, _, _>, 3);
250 table[DUP4 as usize] = Instruction::new(stack::dup::<4, _, _>, 3);
251 table[DUP5 as usize] = Instruction::new(stack::dup::<5, _, _>, 3);
252 table[DUP6 as usize] = Instruction::new(stack::dup::<6, _, _>, 3);
253 table[DUP7 as usize] = Instruction::new(stack::dup::<7, _, _>, 3);
254 table[DUP8 as usize] = Instruction::new(stack::dup::<8, _, _>, 3);
255 table[DUP9 as usize] = Instruction::new(stack::dup::<9, _, _>, 3);
256 table[DUP10 as usize] = Instruction::new(stack::dup::<10, _, _>, 3);
257 table[DUP11 as usize] = Instruction::new(stack::dup::<11, _, _>, 3);
258 table[DUP12 as usize] = Instruction::new(stack::dup::<12, _, _>, 3);
259 table[DUP13 as usize] = Instruction::new(stack::dup::<13, _, _>, 3);
260 table[DUP14 as usize] = Instruction::new(stack::dup::<14, _, _>, 3);
261 table[DUP15 as usize] = Instruction::new(stack::dup::<15, _, _>, 3);
262 table[DUP16 as usize] = Instruction::new(stack::dup::<16, _, _>, 3);
263
264 table[SWAP1 as usize] = Instruction::new(stack::swap::<1, _, _>, 3);
265 table[SWAP2 as usize] = Instruction::new(stack::swap::<2, _, _>, 3);
266 table[SWAP3 as usize] = Instruction::new(stack::swap::<3, _, _>, 3);
267 table[SWAP4 as usize] = Instruction::new(stack::swap::<4, _, _>, 3);
268 table[SWAP5 as usize] = Instruction::new(stack::swap::<5, _, _>, 3);
269 table[SWAP6 as usize] = Instruction::new(stack::swap::<6, _, _>, 3);
270 table[SWAP7 as usize] = Instruction::new(stack::swap::<7, _, _>, 3);
271 table[SWAP8 as usize] = Instruction::new(stack::swap::<8, _, _>, 3);
272 table[SWAP9 as usize] = Instruction::new(stack::swap::<9, _, _>, 3);
273 table[SWAP10 as usize] = Instruction::new(stack::swap::<10, _, _>, 3);
274 table[SWAP11 as usize] = Instruction::new(stack::swap::<11, _, _>, 3);
275 table[SWAP12 as usize] = Instruction::new(stack::swap::<12, _, _>, 3);
276 table[SWAP13 as usize] = Instruction::new(stack::swap::<13, _, _>, 3);
277 table[SWAP14 as usize] = Instruction::new(stack::swap::<14, _, _>, 3);
278 table[SWAP15 as usize] = Instruction::new(stack::swap::<15, _, _>, 3);
279 table[SWAP16 as usize] = Instruction::new(stack::swap::<16, _, _>, 3);
280
281 table[LOG0 as usize] = Instruction::new(host::log::<0, _>, gas::LOG);
282 table[LOG1 as usize] = Instruction::new(host::log::<1, _>, gas::LOG);
283 table[LOG2 as usize] = Instruction::new(host::log::<2, _>, gas::LOG);
284 table[LOG3 as usize] = Instruction::new(host::log::<3, _>, gas::LOG);
285 table[LOG4 as usize] = Instruction::new(host::log::<4, _>, gas::LOG);
286
287 table[CREATE as usize] = Instruction::new(contract::create::<_, false, _>, 0);
288 table[CALL as usize] = Instruction::new(contract::call, 40);
289 table[CALLCODE as usize] = Instruction::new(contract::call_code, 40);
290 table[RETURN as usize] = Instruction::new(control::ret, 0);
291 table[DELEGATECALL as usize] = Instruction::new(contract::delegate_call, 40);
292 table[CREATE2 as usize] = Instruction::new(contract::create::<_, true, _>, 0);
293
294 table[STATICCALL as usize] = Instruction::new(contract::static_call, 40);
295 table[REVERT as usize] = Instruction::new(control::revert, 0);
296 table[INVALID as usize] = Instruction::new(control::invalid, 0);
297 table[SELFDESTRUCT as usize] = Instruction::new(host::selfdestruct, 0);
298 table
299}
300
301#[cfg(test)]
302mod tests {
303 use super::instruction_table;
304 use crate::{host::DummyHost, interpreter::EthInterpreter};
305 use bytecode::opcode::*;
306
307 #[test]
308 fn all_instructions_and_opcodes_used() {
309 let unknown_instruction = 0x0C_usize;
311 let instr_table = instruction_table::<EthInterpreter, DummyHost>();
312
313 let unknown_istr = instr_table[unknown_instruction];
314 for (i, instr) in instr_table.iter().enumerate() {
315 let is_opcode_unknown = OpCode::new(i as u8).is_none();
316 let is_instr_unknown = std::ptr::fn_addr_eq(instr.fn_, unknown_istr.fn_);
318 assert_eq!(
319 is_instr_unknown, is_opcode_unknown,
320 "Opcode 0x{i:X?} is not handled",
321 );
322 }
323 }
324}