revm_interpreter/instructions/
control.rs

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    // In spec it is +3 but pointer is already incremented in
20    // `Interpreter::step` so for revm is +2.
21    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    // In spec it is +3 but pointer is already incremented in
32    // `Interpreter::step` so for revm is +2.
33    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    // For number of items we are adding 1 to max_index, multiply by 2 as each offset is 2 bytes
52    // and add 1 for max_index itself. Note that revm already incremented the instruction pointer
53    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    // SAFETY: `is_valid_jump` ensures that `dest` is in bounds.
92    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    // Get target types
111    let Some(types) = interpreter.bytecode.code_info(idx) else {
112        panic!("Invalid EOF in execution, expecting correct intermediate in callf")
113    };
114
115    // Check max stack height for target code section.
116    // Safe to subtract as max_stack_height is always more than inputs.
117    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    // Push current idx and PC to the callf stack.
125    // PC is incremented by 2 to point to the next instruction after callf.
126    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    // Get target types
166    let types = interpreter
167        .bytecode
168        .code_info(idx)
169        .expect("Invalid code section index");
170
171    // Check max stack height for target code section.
172    // Safe to subtract as max_stack_height is always more than inputs.
173    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    // - 1 because we have already advanced the instruction pointer in `Interpreter::step`
193    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    // Zero gas cost
202    // gas!(interpreter, gas::ZERO)
203    popn!([offset, len], interpreter);
204    let len = as_usize_or_fail!(interpreter, len);
205    // Important: Offset must be ignored if len is zeros
206    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
233/// EIP-140: REVERT instruction
234pub 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
242/// Stop opcode. This opcode halts the execution.
243pub 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
252/// Invalid opcode. This opcode halts the execution.
253pub 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
262/// Unknown opcode. This opcode halts the execution.
263pub 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        // Dont jump
313        interpreter.step(&table, &mut host);
314        assert_eq!(interpreter.bytecode.pc(), 3);
315        // Jumps to last opcode
316        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, // max index, 0 and 1
325            0x00, // first x0001
326            0x01,
327            0x00, // second 0x0002
328            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        // More then max_index
344        let _ = interpreter.stack.push(U256::from(10));
345        interpreter.step(&table, &mut host);
346        assert_eq!(interpreter.bytecode.pc(), 6);
347
348        // Cleanup
349        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        // Jump to first index of vtable
356        let _ = interpreter.stack.push(U256::from(0));
357        interpreter.step(&table, &mut host);
358        assert_eq!(interpreter.bytecode.pc(), 7);
359
360        // Cleanup
361        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        // Jump to second index of vtable
367        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    /// Two code section and types section is for last code.
382    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        // added two code infos that are 4 bytes each.
398        eof.header.types_size = 2 * 4;
399
400        eof.body.code = Bytes::from([bytes1, bytes2].concat());
401
402        // encoding EOF is done se we can generate a raw bytecode.
403        // raw bytecode is used to calculate program counter.
404        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        // CALLF
423        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        // points to second code section, at RETF opcode
431        assert_eq!(interpreter.bytecode.pc() - base_pc, 4);
432
433        // RETF
434        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        // we have returned from the second code section and next opcode is STOP
439        assert_eq!(interpreter.bytecode.pc() - base_pc, 3);
440
441        // STOP
442        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        // CALLF
461        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        // program counter points to STOP of second code section.
469        assert_eq!(interpreter.bytecode.pc(), 3 + base_pc);
470
471        // STOP
472        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        // push two items so we can overflow the CALLF call.
491        // overflow happens if max_stack_size + stack.len is more than 1024
492        let _ = interpreter.stack.push(U256::from(0));
493        let _ = interpreter.stack.push(U256::from(0));
494
495        // CALLF
496        interpreter.step(&table, &mut host);
497
498        // Stack overflow
499        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        // JUMPF
517        interpreter.step(&table, &mut host);
518
519        // fails after this line
520        assert_eq!(interpreter.sub_routine.current_code_idx, 1);
521        assert!(interpreter.sub_routine.return_stack.is_empty());
522        // program counter points to STOP of second code section.
523        assert_eq!(interpreter.bytecode.pc(), 3 + base_pc);
524
525        // STOP
526        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        // push two items so we can overflow the JUMPF call.
545        // overflow happens if max_stack_size + stack.len is more than 1024
546        let _ = interpreter.stack.push(U256::from(0));
547        let _ = interpreter.stack.push(U256::from(0));
548
549        // JUMPF
550        interpreter.step(&table, &mut host);
551
552        // Stack overflow
553        assert_eq!(
554            interpreter.control.instruction_result,
555            InstructionResult::StackOverflow
556        );
557    }
558}