1use crate::{
2 Call,
3 evm::{Context, Evm, EvmResult, EvmYield, HaltReason},
4 state::State,
5};
6
7pub mod basic;
8pub mod calls;
9pub mod chain;
10pub mod logs;
11pub mod stack;
12pub mod store;
13
14fn invalid(evm: &mut Evm, _: &Context, _: &Call, _: &mut dyn State) -> EvmResult<()> {
15 let op = evm.code.get(evm.pc).copied().unwrap_or_default();
16 Err(EvmYield::Halt(HaltReason::BadOpcode(op)))
17}
18
19pub fn text(code: &[u8]) -> Vec<String> {
20 let mut ret = Vec::with_capacity(code.len());
21 let mut pc = 0;
22 while pc < code.len() {
23 let op = code[pc];
24 let name = OPS[op as usize];
25 let data = match op {
26 0x60..0x80 => {
27 let len = op as usize - 0x60 + 1; let lo = (pc + 1).min(code.len());
29 let hi = (pc + 1 + len).min(code.len());
30 pc += len;
31 Some(hex::encode(&code[lo..hi]))
32 }
33 _ => None,
34 };
35 let data = data.map(|d| format!(" [{d}]")).unwrap_or_default();
36 ret.push(format!("{pc:04x}: {name:16}{data}"));
37 pc += 1;
38 }
39 ret
40}
41
42pub fn dispatch<S: State>(
43 op: u8,
44 evm: &mut Evm,
45 ctx: &Context,
46 call: &Call,
47 state: &mut S,
48) -> EvmResult<()> {
49 match op {
50 0x00 => basic::stop(evm),
51 0x01 => basic::add(evm),
52 0x02 => basic::mul(evm),
53 0x03 => basic::sub(evm),
54 0x04 => basic::div(evm),
55 0x05 => basic::sdiv(evm),
56 0x06 => basic::r#mod(evm),
57 0x07 => basic::smod(evm),
58 0x08 => basic::addmod(evm),
59 0x09 => basic::mulmod(evm),
60 0x0A => basic::exp(evm),
61 0x0B => basic::signextend(evm),
62 0x10 => basic::lt(evm),
63 0x11 => basic::gt(evm),
64 0x12 => basic::slt(evm),
65 0x13 => basic::sgt(evm),
66 0x14 => basic::eq(evm),
67 0x15 => basic::iszero(evm),
68 0x16 => basic::and(evm),
69 0x17 => basic::or(evm),
70 0x18 => basic::xor(evm),
71 0x19 => basic::not(evm),
72 0x1A => basic::byte(evm),
73 0x1B => basic::shl(evm),
74 0x1C => basic::shr(evm),
75 0x1D => basic::sar(evm),
76 0x1E => basic::clz(evm),
77 0x20 => basic::hash(evm, state),
78 0x30 => chain::address(evm, ctx, call, state),
79 0x31 => chain::balance(evm, ctx, call, state),
80 0x32 => chain::origin(evm, ctx, call, state),
81 0x33 => chain::caller(evm, ctx, call, state),
82 0x34 => chain::callvalue(evm, ctx, call, state),
83 0x35 => chain::calldataload(evm, ctx, call, state),
84 0x36 => chain::calldatasize(evm, ctx, call, state),
85 0x37 => chain::calldatacopy(evm, ctx, call, state),
86 0x38 => chain::codesize(evm, ctx, call, state),
87 0x39 => chain::codecopy(evm, ctx, call, state),
88 0x3A => chain::gasprice(evm, ctx, call, state),
89 0x3B => chain::extcodesize(evm, ctx, call, state),
90 0x3C => chain::extcodecopy(evm, ctx, call, state),
91 0x3D => chain::returndatasize(evm, ctx, call, state),
92 0x3E => chain::returndatacopy(evm, ctx, call, state),
93 0x3F => chain::extcodehash(evm, ctx, call, state),
94 0x40 => chain::blockhash(evm, ctx, call, state),
95 0x41 => chain::coinbase(evm, ctx, call, state),
96 0x42 => chain::timestamp(evm, ctx, call, state),
97 0x43 => chain::number(evm, ctx, call, state),
98 0x44 => chain::prevrandao(evm, ctx, call, state),
99 0x45 => chain::gaslimit(evm, ctx, call, state),
100 0x46 => chain::chainid(evm, ctx, call, state),
101 0x47 => chain::selfbalance(evm, ctx, call, state),
102 0x48 => chain::basefee(evm, ctx, call, state),
103 0x49 => chain::blobhash(evm, ctx, call, state),
104 0x4A => chain::blobbasefee(evm, ctx, call, state),
105 0x50 => store::pop(evm, ctx, call, state),
106 0x51 => store::mload(evm, ctx, call, state),
107 0x52 => store::mstore(evm, ctx, call, state),
108 0x53 => store::mstore8(evm, ctx, call, state),
109 0x54 => store::sload(evm, ctx, call, state),
110 0x55 => store::sstore(evm, ctx, call, state),
111 0x56 => store::jump(evm, ctx, call, state),
112 0x57 => store::jumpi(evm, ctx, call, state),
113 0x58 => store::pc(evm, ctx, call, state),
114 0x59 => store::msize(evm, ctx, call, state),
115 0x5A => store::gas(evm, ctx, call, state),
116 0x5B => store::jumpdest(evm, ctx, call, state),
117 0x5C => store::tload(evm, ctx, call, state),
118 0x5D => store::tstore(evm, ctx, call, state),
119 0x5E => store::mcopy(evm, ctx, call, state),
120 0x5F..=0x7F => stack::push(evm, ctx, call, state),
121 0x80..=0x8F => stack::dup(evm, ctx, call, state),
122 0x90..=0x9F => stack::swap(evm, ctx, call, state),
123 0xA0..=0xA4 => logs::log(evm, ctx, call, state),
124 0xF0 => calls::create(evm, ctx, call, state),
125 0xF1 => calls::call(evm, ctx, call, state),
126 0xF2 => calls::callcode(evm, ctx, call, state),
127 0xF3 => calls::r#return(evm, ctx, call, state),
128 0xF4 => calls::delegatecall(evm, ctx, call, state),
129 0xF5 => calls::create2(evm, ctx, call, state),
130 0xFA => calls::staticcall(evm, ctx, call, state),
131 0xFD => calls::revert(evm, ctx, call, state),
132 0xFF => calls::selfdestruct(evm, ctx, call, state),
133 _ => invalid(evm, ctx, call, state),
134 }
135}
136
137pub const OPS: [&str; 256] = [
138 "STOP",
140 "ADD",
141 "MUL",
142 "SUB",
143 "DIV",
144 "SDIV",
145 "MOD",
146 "SMOD",
147 "ADDMOD",
148 "MULMOD",
149 "EXP",
150 "SIGNEXTEND",
151 "INVALID/0x0C",
152 "INVALID/0x0D",
153 "INVALID/0x0E",
154 "INVALID/0x0F",
155 "LT",
157 "GT",
158 "SLT",
159 "SGT",
160 "EQ",
161 "ISZERO",
162 "AND",
163 "OR",
164 "XOR",
165 "NOT",
166 "BYTE",
167 "SHL",
168 "SHR",
169 "SAR",
170 "CLZ",
171 "INVALID/0x1F",
173 "KECCAK256",
175 "INVALID/0x21",
176 "INVALID/0x22",
177 "INVALID/0x23",
178 "INVALID/0x24",
179 "INVALID/0x25",
180 "INVALID/0x26",
181 "INVALID/0x27",
182 "INVALID/0x28",
183 "INVALID/0x29",
184 "INVALID/0x2A",
185 "INVALID/0x2B",
186 "INVALID/0x2C",
187 "INVALID/0x2D",
188 "INVALID/0x2E",
189 "INVALID/0x2F",
190 "ADDRESS",
192 "BALANCE",
193 "ORIGIN",
194 "CALLER",
195 "CALLVALUE",
196 "CALLDATALOAD",
197 "CALLDATASIZE",
198 "CALLDATACOPY",
199 "CODESIZE",
200 "CODECOPY",
201 "GASPRICE",
202 "EXTCODESIZE",
203 "EXTCODECOPY",
204 "RETURNDATASIZE",
205 "RETURNDATACOPY",
206 "EXTCODEHASH",
207 "BLOCKHASH",
209 "COINBASE",
210 "TIMESTAMP",
211 "NUMBER",
212 "DIFFICULTY",
213 "GASLIMIT",
214 "CHAINID",
215 "SELFBALANCE",
216 "BASEFEE",
217 "BLOBHASH",
218 "BLOBBASEFEE",
219 "INVALID/0x4B",
220 "INVALID/0x4C",
221 "INVALID/0x4D",
222 "INVALID/0x4E",
223 "INVALID/0x4F",
224 "POP",
226 "MLOAD",
227 "MSTORE",
228 "MSTORE8",
229 "SLOAD",
230 "SSTORE",
231 "JUMP",
232 "JUMPI",
233 "PC",
234 "MSIZE",
235 "GAS",
236 "JUMPDEST",
237 "TLOAD",
238 "TSTORE",
239 "MCOPY",
240 "PUSH0",
241 "PUSH1",
243 "PUSH2",
244 "PUSH3",
245 "PUSH4",
246 "PUSH5",
247 "PUSH6",
248 "PUSH7",
249 "PUSH8",
250 "PUSH9",
251 "PUSH10",
252 "PUSH11",
253 "PUSH12",
254 "PUSH13",
255 "PUSH14",
256 "PUSH15",
257 "PUSH16",
258 "PUSH17",
260 "PUSH18",
261 "PUSH19",
262 "PUSH20",
263 "PUSH21",
264 "PUSH22",
265 "PUSH23",
266 "PUSH24",
267 "PUSH25",
268 "PUSH26",
269 "PUSH27",
270 "PUSH28",
271 "PUSH29",
272 "PUSH30",
273 "PUSH31",
274 "PUSH32",
275 "DUP1",
277 "DUP2",
278 "DUP3",
279 "DUP4",
280 "DUP5",
281 "DUP6",
282 "DUP7",
283 "DUP8",
284 "DUP9",
285 "DUP10",
286 "DUP11",
287 "DUP12",
288 "DUP13",
289 "DUP14",
290 "DUP15",
291 "DUP16",
292 "SWAP1",
294 "SWAP2",
295 "SWAP3",
296 "SWAP4",
297 "SWAP5",
298 "SWAP6",
299 "SWAP7",
300 "SWAP8",
301 "SWAP9",
302 "SWAP10",
303 "SWAP11",
304 "SWAP12",
305 "SWAP13",
306 "SWAP14",
307 "SWAP15",
308 "SWAP16",
309 "LOG0",
311 "LOG1",
312 "LOG2",
313 "LOG3",
314 "LOG4",
315 "INVALID/0xA5",
316 "INVALID/0xA6",
317 "INVALID/0xA7",
318 "INVALID/0xA8",
319 "INVALID/0xA9",
320 "INVALID/0xAA",
321 "INVALID/0xAB",
322 "INVALID/0xAC",
323 "INVALID/0xAD",
324 "INVALID/0xAE",
325 "INVALID/0xAF",
326 "INVALID/0xB0",
328 "INVALID/0xB1",
329 "INVALID/0xB2",
330 "INVALID/0xB3",
331 "INVALID/0xB4",
332 "INVALID/0xB5",
333 "INVALID/0xB6",
334 "INVALID/0xB7",
335 "INVALID/0xB8",
336 "INVALID/0xB9",
337 "INVALID/0xBA",
338 "INVALID/0xBB",
339 "INVALID/0xBC",
340 "INVALID/0xBD",
341 "INVALID/0xBE",
342 "INVALID/0xBF",
343 "INVALID/0xC0",
345 "INVALID/0xC1",
346 "INVALID/0xC2",
347 "INVALID/0xC3",
348 "INVALID/0xC4",
349 "INVALID/0xC5",
350 "INVALID/0xC6",
351 "INVALID/0xC7",
352 "INVALID/0xC8",
353 "INVALID/0xC9",
354 "INVALID/0xCA",
355 "INVALID/0xCB",
356 "INVALID/0xCC",
357 "INVALID/0xCD",
358 "INVALID/0xCE",
359 "INVALID/0xCF",
360 "INVALID/0xD0",
362 "INVALID/0xD1",
363 "INVALID/0xD2",
364 "INVALID/0xD3",
365 "INVALID/0xD4",
366 "INVALID/0xD5",
367 "INVALID/0xD6",
368 "INVALID/0xD7",
369 "INVALID/0xD8",
370 "INVALID/0xD9",
371 "INVALID/0xDA",
372 "INVALID/0xDB",
373 "INVALID/0xDC",
374 "INVALID/0xDD",
375 "INVALID/0xDE",
376 "INVALID/0xDF",
377 "INVALID/0xE0",
379 "INVALID/0xE1",
380 "INVALID/0xE2",
381 "INVALID/0xE3",
382 "INVALID/0xE4",
383 "INVALID/0xE5",
384 "INVALID/0xE6",
385 "INVALID/0xE7",
386 "INVALID/0xE8",
387 "INVALID/0xE9",
388 "INVALID/0xEA",
389 "INVALID/0xEB",
390 "INVALID/0xEC",
391 "INVALID/0xED",
392 "INVALID/0xEE",
393 "INVALID/0xEF",
394 "CREATE",
396 "CALL",
397 "CALLCODE",
398 "RETURN",
399 "DELEGATECALL",
400 "CREATE2",
401 "INVALID/0xF6",
402 "INVALID/0xF7",
403 "INVALID/0xF8",
404 "INVALID/0xF9",
405 "STATICCALL",
406 "INVALID/0xFB",
407 "INVALID/0xFC",
408 "REVERT",
409 "INVALID/0xFE",
410 "SELFDESTRUCT",
411];
412
413#[cfg(test)]
414pub mod tests {
415 use yevm_misc::buf::Buf;
416
417 use crate::{
418 Acc, Call, Head, Int,
419 evm::Context,
420 state::{Account, State},
421 trace::Event,
422 };
423
424 pub fn ctx() -> Context {
425 Context {
426 origin: Acc::ZERO,
427 is_static: false,
428 depth: 0,
429 this: Acc::ZERO,
430 }
431 }
432
433 pub fn call() -> Call {
434 Call {
435 by: Acc::ZERO,
436 to: Some(Acc::ONE),
437 gas: 0,
438 eth: Int::ZERO,
439 data: vec![].into(),
440 }
441 }
442
443 pub fn state() -> Empty {
444 Empty
445 }
446
447 #[derive(Default)]
448 pub struct Empty;
449
450 impl State for Empty {
451 fn get(&mut self, _: &Acc, _: &Int) -> Option<(Int, Int)> {
452 None
453 }
454 fn put(&mut self, _: &Acc, _: &Int, _: Int) -> Option<Int> {
455 None
456 }
457 fn init(&mut self, _: &Acc, _: &Int, _: Int) {}
458 fn tget(&mut self, _: &Acc, _: &Int) -> Option<Int> {
459 None
460 }
461 fn tput(&mut self, _: Acc, _: Int, _: Int) -> Option<Int> {
462 None
463 }
464 fn inc_nonce(&mut self, _: &Acc, _: Int) -> Int {
465 Int::ZERO
466 }
467 fn set_value(&mut self, _: &Acc, _: Int) -> Int {
468 Int::ZERO
469 }
470 fn set_code(&mut self, _: &Acc, _: Buf, _: Int) -> Int {
471 Int::ZERO
472 }
473 fn balance(&mut self, _: &Acc) -> Option<Int> {
474 None
475 }
476 fn nonce(&mut self, _: &Acc) -> Option<Int> {
477 None
478 }
479 fn code(&mut self, _: &Acc) -> Option<(Buf, Int)> {
480 None
481 }
482 fn acc(&mut self, _: &Acc) -> Option<Account> {
483 None
484 }
485 fn merge(&mut self, _: &Acc, _: Account) {}
486 fn is_cold_acc(&self, _: &Acc) -> bool {
487 true
488 }
489 fn is_cold_key(&self, _: &Acc, _: &Int) -> bool {
490 true
491 }
492 fn warm_acc(&mut self, _: &Acc) -> bool {
493 false
494 }
495 fn warm_key(&mut self, _: &Acc, _: &Int) -> bool {
496 false
497 }
498 fn create(&mut self, _: Acc, _: Account) {}
499 fn destroy(&mut self, _: &Acc) {}
500 fn created(&self) -> Vec<Acc> {
501 vec![]
502 }
503 fn destroyed(&self) -> Vec<Acc> {
504 vec![]
505 }
506 fn head(&self, _: u64) -> Option<Head> {
507 None
508 }
509 fn hash(&mut self, _: u64, _: Int) {}
510 fn auth(&self, _: &Acc) -> Option<Acc> {
511 None
512 }
513 fn log(&mut self, _: Buf, _: Vec<Int>) {}
514 fn emit(&mut self, _: Event) -> usize {
515 0
516 }
517 fn set_auth(&mut self, _: &Acc, _: &Acc) {}
518 fn apply(&mut self) {}
519 }
520}