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