revm_interpreter/
instructions.rs

1//! EVM opcode implementations.
2
3#[macro_use]
4pub mod macros;
5pub mod arithmetic;
6pub mod bitwise;
7pub mod block_info;
8pub mod contract;
9pub mod control;
10pub mod data;
11pub mod host;
12pub mod i256;
13pub mod memory;
14pub mod stack;
15pub mod system;
16pub mod tx_info;
17pub mod utility;
18
19use crate::{interpreter_types::InterpreterTypes, Host};
20
21/// Returns the instruction function for the given opcode and spec.
22pub const fn instruction<WIRE: InterpreterTypes, H: Host + ?Sized>(
23    opcode: u8,
24) -> crate::table::Instruction<WIRE, H> {
25    let table = instruction_table::<WIRE, H>();
26    table[opcode as usize]
27}
28
29pub const fn instruction_table<WIRE: InterpreterTypes, H: Host + ?Sized>(
30) -> [crate::table::Instruction<WIRE, H>; 256] {
31    use bytecode::opcode::*;
32    let mut table = [control::unknown as crate::table::Instruction<WIRE, H>; 256];
33
34    table[STOP as usize] = control::stop;
35    table[ADD as usize] = arithmetic::add;
36    table[MUL as usize] = arithmetic::mul;
37    table[SUB as usize] = arithmetic::sub;
38    table[DIV as usize] = arithmetic::div;
39    table[SDIV as usize] = arithmetic::sdiv;
40    table[MOD as usize] = arithmetic::rem;
41    table[SMOD as usize] = arithmetic::smod;
42    table[ADDMOD as usize] = arithmetic::addmod;
43    table[MULMOD as usize] = arithmetic::mulmod;
44    table[EXP as usize] = arithmetic::exp;
45    table[SIGNEXTEND as usize] = arithmetic::signextend;
46
47    table[LT as usize] = bitwise::lt;
48    table[GT as usize] = bitwise::gt;
49    table[SLT as usize] = bitwise::slt;
50    table[SGT as usize] = bitwise::sgt;
51    table[EQ as usize] = bitwise::eq;
52    table[ISZERO as usize] = bitwise::iszero;
53    table[AND as usize] = bitwise::bitand;
54    table[OR as usize] = bitwise::bitor;
55    table[XOR as usize] = bitwise::bitxor;
56    table[NOT as usize] = bitwise::not;
57    table[BYTE as usize] = bitwise::byte;
58    table[SHL as usize] = bitwise::shl;
59    table[SHR as usize] = bitwise::shr;
60    table[SAR as usize] = bitwise::sar;
61
62    table[KECCAK256 as usize] = system::keccak256;
63
64    table[ADDRESS as usize] = system::address;
65    table[BALANCE as usize] = host::balance;
66    table[ORIGIN as usize] = tx_info::origin;
67    table[CALLER as usize] = system::caller;
68    table[CALLVALUE as usize] = system::callvalue;
69    table[CALLDATALOAD as usize] = system::calldataload;
70    table[CALLDATASIZE as usize] = system::calldatasize;
71    table[CALLDATACOPY as usize] = system::calldatacopy;
72    table[CODESIZE as usize] = system::codesize;
73    table[CODECOPY as usize] = system::codecopy;
74
75    table[GASPRICE as usize] = tx_info::gasprice;
76    table[EXTCODESIZE as usize] = host::extcodesize;
77    table[EXTCODECOPY as usize] = host::extcodecopy;
78    table[RETURNDATASIZE as usize] = system::returndatasize;
79    table[RETURNDATACOPY as usize] = system::returndatacopy;
80    table[EXTCODEHASH as usize] = host::extcodehash;
81    table[BLOCKHASH as usize] = host::blockhash;
82    table[COINBASE as usize] = block_info::coinbase;
83    table[TIMESTAMP as usize] = block_info::timestamp;
84    table[NUMBER as usize] = block_info::block_number;
85    table[DIFFICULTY as usize] = block_info::difficulty;
86    table[GASLIMIT as usize] = block_info::gaslimit;
87    table[CHAINID as usize] = block_info::chainid;
88    table[SELFBALANCE as usize] = host::selfbalance;
89    table[BASEFEE as usize] = block_info::basefee;
90    table[BLOBHASH as usize] = tx_info::blob_hash;
91    table[BLOBBASEFEE as usize] = block_info::blob_basefee;
92
93    table[POP as usize] = stack::pop;
94    table[MLOAD as usize] = memory::mload;
95    table[MSTORE as usize] = memory::mstore;
96    table[MSTORE8 as usize] = memory::mstore8;
97    table[SLOAD as usize] = host::sload;
98    table[SSTORE as usize] = host::sstore;
99    table[JUMP as usize] = control::jump;
100    table[JUMPI as usize] = control::jumpi;
101    table[PC as usize] = control::pc;
102    table[MSIZE as usize] = memory::msize;
103    table[GAS as usize] = system::gas;
104    table[JUMPDEST as usize] = control::jumpdest_or_nop;
105    table[TLOAD as usize] = host::tload;
106    table[TSTORE as usize] = host::tstore;
107    table[MCOPY as usize] = memory::mcopy;
108
109    table[PUSH0 as usize] = stack::push0;
110    table[PUSH1 as usize] = stack::push::<1, _, _>;
111    table[PUSH2 as usize] = stack::push::<2, _, _>;
112    table[PUSH3 as usize] = stack::push::<3, _, _>;
113    table[PUSH4 as usize] = stack::push::<4, _, _>;
114    table[PUSH5 as usize] = stack::push::<5, _, _>;
115    table[PUSH6 as usize] = stack::push::<6, _, _>;
116    table[PUSH7 as usize] = stack::push::<7, _, _>;
117    table[PUSH8 as usize] = stack::push::<8, _, _>;
118    table[PUSH9 as usize] = stack::push::<9, _, _>;
119    table[PUSH10 as usize] = stack::push::<10, _, _>;
120    table[PUSH11 as usize] = stack::push::<11, _, _>;
121    table[PUSH12 as usize] = stack::push::<12, _, _>;
122    table[PUSH13 as usize] = stack::push::<13, _, _>;
123    table[PUSH14 as usize] = stack::push::<14, _, _>;
124    table[PUSH15 as usize] = stack::push::<15, _, _>;
125    table[PUSH16 as usize] = stack::push::<16, _, _>;
126    table[PUSH17 as usize] = stack::push::<17, _, _>;
127    table[PUSH18 as usize] = stack::push::<18, _, _>;
128    table[PUSH19 as usize] = stack::push::<19, _, _>;
129    table[PUSH20 as usize] = stack::push::<20, _, _>;
130    table[PUSH21 as usize] = stack::push::<21, _, _>;
131    table[PUSH22 as usize] = stack::push::<22, _, _>;
132    table[PUSH23 as usize] = stack::push::<23, _, _>;
133    table[PUSH24 as usize] = stack::push::<24, _, _>;
134    table[PUSH25 as usize] = stack::push::<25, _, _>;
135    table[PUSH26 as usize] = stack::push::<26, _, _>;
136    table[PUSH27 as usize] = stack::push::<27, _, _>;
137    table[PUSH28 as usize] = stack::push::<28, _, _>;
138    table[PUSH29 as usize] = stack::push::<29, _, _>;
139    table[PUSH30 as usize] = stack::push::<30, _, _>;
140    table[PUSH31 as usize] = stack::push::<31, _, _>;
141    table[PUSH32 as usize] = stack::push::<32, _, _>;
142
143    table[DUP1 as usize] = stack::dup::<1, _, _>;
144    table[DUP2 as usize] = stack::dup::<2, _, _>;
145    table[DUP3 as usize] = stack::dup::<3, _, _>;
146    table[DUP4 as usize] = stack::dup::<4, _, _>;
147    table[DUP5 as usize] = stack::dup::<5, _, _>;
148    table[DUP6 as usize] = stack::dup::<6, _, _>;
149    table[DUP7 as usize] = stack::dup::<7, _, _>;
150    table[DUP8 as usize] = stack::dup::<8, _, _>;
151    table[DUP9 as usize] = stack::dup::<9, _, _>;
152    table[DUP10 as usize] = stack::dup::<10, _, _>;
153    table[DUP11 as usize] = stack::dup::<11, _, _>;
154    table[DUP12 as usize] = stack::dup::<12, _, _>;
155    table[DUP13 as usize] = stack::dup::<13, _, _>;
156    table[DUP14 as usize] = stack::dup::<14, _, _>;
157    table[DUP15 as usize] = stack::dup::<15, _, _>;
158    table[DUP16 as usize] = stack::dup::<16, _, _>;
159
160    table[SWAP1 as usize] = stack::swap::<1, _, _>;
161    table[SWAP2 as usize] = stack::swap::<2, _, _>;
162    table[SWAP3 as usize] = stack::swap::<3, _, _>;
163    table[SWAP4 as usize] = stack::swap::<4, _, _>;
164    table[SWAP5 as usize] = stack::swap::<5, _, _>;
165    table[SWAP6 as usize] = stack::swap::<6, _, _>;
166    table[SWAP7 as usize] = stack::swap::<7, _, _>;
167    table[SWAP8 as usize] = stack::swap::<8, _, _>;
168    table[SWAP9 as usize] = stack::swap::<9, _, _>;
169    table[SWAP10 as usize] = stack::swap::<10, _, _>;
170    table[SWAP11 as usize] = stack::swap::<11, _, _>;
171    table[SWAP12 as usize] = stack::swap::<12, _, _>;
172    table[SWAP13 as usize] = stack::swap::<13, _, _>;
173    table[SWAP14 as usize] = stack::swap::<14, _, _>;
174    table[SWAP15 as usize] = stack::swap::<15, _, _>;
175    table[SWAP16 as usize] = stack::swap::<16, _, _>;
176
177    table[LOG0 as usize] = host::log::<0, _>;
178    table[LOG1 as usize] = host::log::<1, _>;
179    table[LOG2 as usize] = host::log::<2, _>;
180    table[LOG3 as usize] = host::log::<3, _>;
181    table[LOG4 as usize] = host::log::<4, _>;
182
183    table[DATALOAD as usize] = data::data_load;
184    table[DATALOADN as usize] = data::data_loadn;
185    table[DATASIZE as usize] = data::data_size;
186    table[DATACOPY as usize] = data::data_copy;
187
188    table[RJUMP as usize] = control::rjump;
189    table[RJUMPI as usize] = control::rjumpi;
190    table[RJUMPV as usize] = control::rjumpv;
191    table[CALLF as usize] = control::callf;
192    table[RETF as usize] = control::retf;
193    table[JUMPF as usize] = control::jumpf;
194    table[DUPN as usize] = stack::dupn;
195    table[SWAPN as usize] = stack::swapn;
196    table[EXCHANGE as usize] = stack::exchange;
197
198    table[EOFCREATE as usize] = contract::eofcreate;
199
200    table[RETURNCONTRACT as usize] = contract::return_contract;
201
202    table[CREATE as usize] = contract::create::<_, false, _>;
203    table[CALL as usize] = contract::call;
204    table[CALLCODE as usize] = contract::call_code;
205    table[RETURN as usize] = control::ret;
206    table[DELEGATECALL as usize] = contract::delegate_call;
207    table[CREATE2 as usize] = contract::create::<_, true, _>;
208
209    table[RETURNDATALOAD as usize] = system::returndataload;
210    table[EXTCALL as usize] = contract::extcall;
211    table[EXTDELEGATECALL as usize] = contract::extdelegatecall;
212    table[STATICCALL as usize] = contract::static_call;
213    table[EXTSTATICCALL as usize] = contract::extstaticcall;
214    table[REVERT as usize] = control::revert;
215    table[INVALID as usize] = control::invalid;
216    table[SELFDESTRUCT as usize] = host::selfdestruct;
217    table
218}
219
220#[cfg(test)]
221mod tests {
222    // use super::*;
223    // use crate::DummyHost;
224    // use bytecode::opcode::*;
225
226    // #[test]
227    // fn all_instructions_and_opcodes_used() {
228    //     // known unknown instruction we compare it with other instructions from table.
229    //     let unknown_instruction = 0x0C_usize;
230    //     let instr_table = instruction_table::<InterpreterTypes, DummyHost<DefaultEthereumWiring>>();
231
232    //     let unknown_istr = instr_table[unknown_instruction];
233    //     for (i, instr) in instr_table.iter().enumerate() {
234    //         let is_opcode_unknown = OpCode::new(i as u8).is_none();
235    //         let is_instr_unknown = *instr == unknown_istr;
236    //         assert_eq!(
237    //             is_instr_unknown, is_opcode_unknown,
238    //             "Opcode 0x{:X?} is not handled",
239    //             i
240    //         );
241    //     }
242    // }
243}