1use crate::{
2 gas,
3 interpreter::Interpreter,
4 interpreter_types::{
5 EofCodeInfo, Immediates, InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag,
6 StackTr, SubRoutineStack,
7 },
8 Host, InstructionResult, InterpreterAction, InterpreterResult,
9};
10use primitives::{Bytes, U256};
11
12pub fn rjump<WIRE: InterpreterTypes, H: ?Sized>(
13 interpreter: &mut Interpreter<WIRE>,
14 _host: &mut H,
15) {
16 require_eof!(interpreter);
17 gas!(interpreter, gas::BASE);
18 let offset = interpreter.bytecode.read_i16() as isize;
19 interpreter.bytecode.relative_jump(offset + 2);
22}
23
24pub fn rjumpi<WIRE: InterpreterTypes, H: Host + ?Sized>(
25 interpreter: &mut Interpreter<WIRE>,
26 _host: &mut H,
27) {
28 require_eof!(interpreter);
29 gas!(interpreter, gas::CONDITION_JUMP_GAS);
30 popn!([condition], interpreter);
31 let mut offset = 2;
34 if !condition.is_zero() {
35 offset += interpreter.bytecode.read_i16() as isize;
36 }
37
38 interpreter.bytecode.relative_jump(offset);
39}
40
41pub fn rjumpv<WIRE: InterpreterTypes, H: Host + ?Sized>(
42 interpreter: &mut Interpreter<WIRE>,
43 _host: &mut H,
44) {
45 require_eof!(interpreter);
46 gas!(interpreter, gas::CONDITION_JUMP_GAS);
47 popn!([case], interpreter);
48 let case = as_isize_saturated!(case);
49
50 let max_index = interpreter.bytecode.read_u8() as isize;
51 let mut offset = (max_index + 1) * 2 + 1;
54
55 if case <= max_index {
56 offset += interpreter.bytecode.read_offset_i16(1 + case * 2) as isize;
57 }
58 interpreter.bytecode.relative_jump(offset);
59}
60
61pub fn jump<WIRE: InterpreterTypes, H: Host + ?Sized>(
62 interpreter: &mut Interpreter<WIRE>,
63 _host: &mut H,
64) {
65 gas!(interpreter, gas::MID);
66 popn!([target], interpreter);
67 jump_inner(interpreter, target);
68}
69
70pub fn jumpi<WIRE: InterpreterTypes, H: Host + ?Sized>(
71 interpreter: &mut Interpreter<WIRE>,
72 _host: &mut H,
73) {
74 gas!(interpreter, gas::HIGH);
75 popn!([target, cond], interpreter);
76
77 if !cond.is_zero() {
78 jump_inner(interpreter, target);
79 }
80}
81
82#[inline]
83fn jump_inner<WIRE: InterpreterTypes>(interpreter: &mut Interpreter<WIRE>, target: U256) {
84 let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
85 if !interpreter.bytecode.is_valid_legacy_jump(target) {
86 interpreter
87 .control
88 .set_instruction_result(InstructionResult::InvalidJump);
89 return;
90 }
91 interpreter.bytecode.absolute_jump(target);
93}
94
95pub fn jumpdest_or_nop<WIRE: InterpreterTypes, H: Host + ?Sized>(
96 interpreter: &mut Interpreter<WIRE>,
97 _host: &mut H,
98) {
99 gas!(interpreter, gas::JUMPDEST);
100}
101
102pub fn callf<WIRE: InterpreterTypes, H: Host + ?Sized>(
103 interpreter: &mut Interpreter<WIRE>,
104 _host: &mut H,
105) {
106 require_eof!(interpreter);
107 gas!(interpreter, gas::LOW);
108
109 let idx = interpreter.bytecode.read_u16() as usize;
110 let Some(types) = interpreter.bytecode.code_info(idx) else {
112 panic!("Invalid EOF in execution, expecting correct intermediate in callf")
113 };
114
115 if interpreter.stack.len() + (types.max_stack_size - types.inputs as u16) as usize > 1024 {
118 interpreter
119 .control
120 .set_instruction_result(InstructionResult::StackOverflow);
121 return;
122 }
123
124 if !(interpreter
127 .sub_routine
128 .push(interpreter.bytecode.pc() + 2, idx))
129 {
130 interpreter
131 .control
132 .set_instruction_result(InstructionResult::SubRoutineStackOverflow);
133 return;
134 };
135 let pc = interpreter
136 .bytecode
137 .code_section_pc(idx)
138 .expect("Invalid code section index");
139 interpreter.bytecode.absolute_jump(pc);
140}
141
142pub fn retf<WIRE: InterpreterTypes, H: Host + ?Sized>(
143 interpreter: &mut Interpreter<WIRE>,
144 _host: &mut H,
145) {
146 require_eof!(interpreter);
147 gas!(interpreter, gas::RETF_GAS);
148
149 let Some(jump) = interpreter.sub_routine.pop() else {
150 panic!("Expected function frame")
151 };
152
153 interpreter.bytecode.absolute_jump(jump);
154}
155
156pub fn jumpf<WIRE: InterpreterTypes, H: Host + ?Sized>(
157 interpreter: &mut Interpreter<WIRE>,
158 _host: &mut H,
159) {
160 require_eof!(interpreter);
161 gas!(interpreter, gas::LOW);
162
163 let idx = interpreter.bytecode.read_u16() as usize;
164
165 let types = interpreter
167 .bytecode
168 .code_info(idx)
169 .expect("Invalid code section index");
170
171 if interpreter.stack.len() + (types.max_stack_size - types.inputs as u16) as usize > 1024 {
174 interpreter
175 .control
176 .set_instruction_result(InstructionResult::StackOverflow);
177 return;
178 }
179 interpreter.sub_routine.set_routine_idx(idx);
180 let pc = interpreter
181 .bytecode
182 .code_section_pc(idx)
183 .expect("Invalid code section index");
184 interpreter.bytecode.absolute_jump(pc);
185}
186
187pub fn pc<WIRE: InterpreterTypes, H: Host + ?Sized>(
188 interpreter: &mut Interpreter<WIRE>,
189 _host: &mut H,
190) {
191 gas!(interpreter, gas::BASE);
192 push!(interpreter, U256::from(interpreter.bytecode.pc() - 1));
194}
195
196#[inline]
197fn return_inner(
198 interpreter: &mut Interpreter<impl InterpreterTypes>,
199 instruction_result: InstructionResult,
200) {
201 popn!([offset, len], interpreter);
204 let len = as_usize_or_fail!(interpreter, len);
205 let mut output = Bytes::default();
207 if len != 0 {
208 let offset = as_usize_or_fail!(interpreter, offset);
209 resize_memory!(interpreter, offset, len);
210 output = interpreter.memory.slice_len(offset, len).to_vec().into()
211 }
212
213 let gas = *interpreter.control.gas();
214 interpreter.control.set_next_action(
215 InterpreterAction::Return {
216 result: InterpreterResult {
217 output,
218 gas,
219 result: instruction_result,
220 },
221 },
222 instruction_result,
223 );
224}
225
226pub fn ret<WIRE: InterpreterTypes, H: Host + ?Sized>(
227 interpreter: &mut Interpreter<WIRE>,
228 _host: &mut H,
229) {
230 return_inner(interpreter, InstructionResult::Return);
231}
232
233pub fn revert<WIRE: InterpreterTypes, H: Host + ?Sized>(
235 interpreter: &mut Interpreter<WIRE>,
236 _host: &mut H,
237) {
238 check!(interpreter, BYZANTIUM);
239 return_inner(interpreter, InstructionResult::Revert);
240}
241
242pub fn stop<WIRE: InterpreterTypes, H: Host + ?Sized>(
244 interpreter: &mut Interpreter<WIRE>,
245 _host: &mut H,
246) {
247 interpreter
248 .control
249 .set_instruction_result(InstructionResult::Stop);
250}
251
252pub fn invalid<WIRE: InterpreterTypes, H: Host + ?Sized>(
254 interpreter: &mut Interpreter<WIRE>,
255 _host: &mut H,
256) {
257 interpreter
258 .control
259 .set_instruction_result(InstructionResult::InvalidFEOpcode);
260}
261
262pub fn unknown<WIRE: InterpreterTypes, H: Host + ?Sized>(
264 interpreter: &mut Interpreter<WIRE>,
265 _host: &mut H,
266) {
267 interpreter
268 .control
269 .set_instruction_result(InstructionResult::OpcodeNotFound);
270}
271
272#[cfg(test)]
273mod test {
274 use super::*;
275 use crate::interpreter::SubRoutineReturnFrame;
276 use crate::{host::DummyHost, instruction_table, interpreter::EthInterpreter};
277 use bytecode::opcode::{CALLF, JUMPF, NOP, RETF, RJUMP, RJUMPI, RJUMPV, STOP};
278 use bytecode::{
279 eof::{CodeInfo, Eof},
280 Bytecode,
281 };
282 use primitives::bytes;
283 use std::sync::Arc;
284
285 #[test]
286 fn rjump() {
287 let bytecode = Bytecode::new_raw(Bytes::from(&[RJUMP, 0x00, 0x02, STOP, STOP]));
288 let mut interpreter = Interpreter::<EthInterpreter>::default().with_bytecode(bytecode);
289
290 interpreter.runtime_flag.is_eof = true;
291 let table = instruction_table();
292 let mut host = DummyHost;
293
294 interpreter.step(&table, &mut host);
295 assert_eq!(interpreter.bytecode.pc(), 5)
296 }
297
298 #[test]
299 fn rjumpi() {
300 let bytecode = Bytecode::new_raw(Bytes::from(&[
301 RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP,
302 ]));
303 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
304
305 interpreter.runtime_flag.is_eof = true;
306 let table = instruction_table();
307 let mut host = DummyHost;
308
309 let _ = interpreter.stack.push(U256::from(1));
310 let _ = interpreter.stack.push(U256::from(0));
311
312 interpreter.step(&table, &mut host);
314 assert_eq!(interpreter.bytecode.pc(), 3);
315 interpreter.step(&table, &mut host);
317 assert_eq!(interpreter.bytecode.pc(), 7);
318 }
319
320 #[test]
321 fn rjumpv() {
322 let bytecode = Bytecode::new_raw(Bytes::from(&[
323 RJUMPV,
324 0x01, 0x00, 0x01,
327 0x00, 0x02,
329 NOP,
330 NOP,
331 NOP,
332 RJUMP,
333 0xFF,
334 (-12i8) as u8,
335 STOP,
336 ]));
337 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
338
339 interpreter.runtime_flag.is_eof = true;
340 let table = instruction_table();
341 let mut host = DummyHost;
342
343 let _ = interpreter.stack.push(U256::from(10));
345 interpreter.step(&table, &mut host);
346 assert_eq!(interpreter.bytecode.pc(), 6);
347
348 interpreter.step(&table, &mut host);
350 interpreter.step(&table, &mut host);
351 interpreter.step(&table, &mut host);
352 interpreter.step(&table, &mut host);
353 assert_eq!(interpreter.bytecode.pc(), 0);
354
355 let _ = interpreter.stack.push(U256::from(0));
357 interpreter.step(&table, &mut host);
358 assert_eq!(interpreter.bytecode.pc(), 7);
359
360 interpreter.step(&table, &mut host);
362 interpreter.step(&table, &mut host);
363 interpreter.step(&table, &mut host);
364 assert_eq!(interpreter.bytecode.pc(), 0);
365
366 let _ = interpreter.stack.push(U256::from(1));
368 interpreter.step(&table, &mut host);
369 assert_eq!(interpreter.bytecode.pc(), 8);
370 }
371
372 fn dummy_eof() -> Eof {
373 let bytes = bytes!("ef000101000402000100010400000000800000fe");
374 Eof::decode(bytes).unwrap()
375 }
376
377 fn eof_setup(bytes1: Bytes, bytes2: Bytes) -> Interpreter {
378 eof_setup_with_types(bytes1, bytes2, CodeInfo::default())
379 }
380
381 fn eof_setup_with_types(bytes1: Bytes, bytes2: Bytes, types: CodeInfo) -> Interpreter {
383 let mut eof = dummy_eof();
384
385 eof.body.code_section.clear();
386 eof.body.code_info.clear();
387 eof.header.code_sizes.clear();
388
389 eof.header.code_sizes.push(bytes1.len() as u16);
390 eof.body.code_section.push(bytes1.len());
391 eof.body.code_info.push(CodeInfo::new(0, 0, 11));
392
393 eof.header.code_sizes.push(bytes2.len() as u16);
394 eof.body.code_section.push(bytes2.len() + bytes1.len());
395 eof.body.code_info.push(types);
396
397 eof.header.types_size = 2 * 4;
399
400 eof.body.code = Bytes::from([bytes1, bytes2].concat());
401
402 let encoded = eof.encode_slow();
405
406 let bytecode = Bytecode::Eof(Arc::new(Eof::decode(encoded).unwrap()));
407
408 Interpreter::default().with_bytecode(bytecode)
409 }
410
411 #[test]
412 fn callf_retf_stop() {
413 let table = instruction_table();
414 let mut host = DummyHost;
415
416 let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]);
417 let bytes2 = Bytes::from([RETF]);
418 let mut interpreter = eof_setup(bytes1, bytes2.clone());
419 interpreter.runtime_flag.is_eof = true;
420 let base_pc = interpreter.bytecode.pc();
421
422 interpreter.step(&table, &mut host);
424
425 assert_eq!(interpreter.sub_routine.current_code_idx, 1);
426 assert_eq!(
427 interpreter.sub_routine.return_stack[0],
428 SubRoutineReturnFrame::new(0, 3 + base_pc)
429 );
430 assert_eq!(interpreter.bytecode.pc() - base_pc, 4);
432
433 interpreter.step(&table, &mut host);
435
436 assert_eq!(interpreter.sub_routine.current_code_idx, 0);
437 assert_eq!(interpreter.sub_routine.return_stack, Vec::new());
438 assert_eq!(interpreter.bytecode.pc() - base_pc, 3);
440
441 interpreter.step(&table, &mut host);
443 assert_eq!(
444 interpreter.control.instruction_result,
445 InstructionResult::Stop
446 );
447 }
448
449 #[test]
450 fn callf_stop() {
451 let table = instruction_table();
452 let mut host = DummyHost;
453
454 let bytes1 = Bytes::from([CALLF, 0x00, 0x01]);
455 let bytes2 = Bytes::from([STOP]);
456 let mut interpreter = eof_setup(bytes1, bytes2.clone());
457 interpreter.runtime_flag.is_eof = true;
458 let base_pc = interpreter.bytecode.pc();
459
460 interpreter.step(&table, &mut host);
462
463 assert_eq!(interpreter.sub_routine.current_code_idx, 1);
464 assert_eq!(
465 interpreter.sub_routine.return_stack[0],
466 SubRoutineReturnFrame::new(0, 3 + base_pc)
467 );
468 assert_eq!(interpreter.bytecode.pc(), 3 + base_pc);
470
471 interpreter.step(&table, &mut host);
473 assert_eq!(
474 interpreter.control.instruction_result,
475 InstructionResult::Stop
476 );
477 }
478
479 #[test]
480 fn callf_stack_overflow() {
481 let table = instruction_table();
482 let mut host = DummyHost;
483
484 let bytes1 = Bytes::from([CALLF, 0x00, 0x01]);
485 let bytes2 = Bytes::from([STOP]);
486 let mut interpreter =
487 eof_setup_with_types(bytes1, bytes2.clone(), CodeInfo::new(0, 0, 1023));
488 interpreter.runtime_flag.is_eof = true;
489
490 let _ = interpreter.stack.push(U256::from(0));
493 let _ = interpreter.stack.push(U256::from(0));
494
495 interpreter.step(&table, &mut host);
497
498 assert_eq!(
500 interpreter.control.instruction_result,
501 InstructionResult::StackOverflow
502 );
503 }
504
505 #[test]
506 fn jumpf_stop() {
507 let table = instruction_table();
508 let mut host = DummyHost;
509
510 let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]);
511 let bytes2 = Bytes::from([STOP]);
512 let mut interpreter = eof_setup(bytes1, bytes2.clone());
513 interpreter.runtime_flag.is_eof = true;
514 let base_pc = interpreter.bytecode.pc();
515
516 interpreter.step(&table, &mut host);
518
519 assert_eq!(interpreter.sub_routine.current_code_idx, 1);
521 assert!(interpreter.sub_routine.return_stack.is_empty());
522 assert_eq!(interpreter.bytecode.pc(), 3 + base_pc);
524
525 interpreter.step(&table, &mut host);
527 assert_eq!(
528 interpreter.control.instruction_result,
529 InstructionResult::Stop
530 );
531 }
532
533 #[test]
534 fn jumpf_stack_overflow() {
535 let table = instruction_table();
536 let mut host = DummyHost;
537
538 let bytes1 = Bytes::from([JUMPF, 0x00, 0x01, STOP]);
539 let bytes2 = Bytes::from([STOP]);
540 let mut interpreter =
541 eof_setup_with_types(bytes1, bytes2.clone(), CodeInfo::new(0, 0, 1023));
542 interpreter.runtime_flag.is_eof = true;
543
544 let _ = interpreter.stack.push(U256::from(0));
547 let _ = interpreter.stack.push(U256::from(0));
548
549 interpreter.step(&table, &mut host);
551
552 assert_eq!(
554 interpreter.control.instruction_result,
555 InstructionResult::StackOverflow
556 );
557 }
558}