pallet_revive/vm/evm/instructions/
control.rs1use super::Context;
19use crate::vm::Ext;
20use revm::{
21 interpreter::{
22 gas as revm_gas,
23 interpreter_action::InterpreterAction,
24 interpreter_types::{Jumps, LoopControl, RuntimeFlag, StackTr},
25 InstructionResult, Interpreter,
26 },
27 primitives::{Bytes, U256},
28};
29
30pub fn jump<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
34 gas_legacy!(context.interpreter, revm_gas::MID);
35 let Some([target]) = <_ as StackTr>::popn(&mut context.interpreter.stack) else {
36 context.interpreter.halt(InstructionResult::StackUnderflow);
37 return;
38 };
39 jump_inner(context.interpreter, target);
40}
41
42pub fn jumpi<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
46 gas_legacy!(context.interpreter, revm_gas::HIGH);
47 let Some([target, cond]) = <_ as StackTr>::popn(&mut context.interpreter.stack) else {
48 context.interpreter.halt(InstructionResult::StackUnderflow);
49 return;
50 };
51
52 if !cond.is_zero() {
53 jump_inner(context.interpreter, target);
54 }
55}
56
57#[inline(always)]
58fn jump_inner(
62 interpreter: &mut Interpreter<impl revm::interpreter::interpreter_types::InterpreterTypes>,
63 target: U256,
64) {
65 let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
66 if !interpreter.bytecode.is_valid_legacy_jump(target) {
67 interpreter.halt(InstructionResult::InvalidJump);
68 return;
69 }
70 interpreter.bytecode.absolute_jump(target);
72}
73
74pub fn jumpdest<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
78 gas_legacy!(context.interpreter, revm_gas::JUMPDEST);
79}
80
81pub fn pc<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
85 gas_legacy!(context.interpreter, revm_gas::BASE);
86 push!(context.interpreter, U256::from(context.interpreter.bytecode.pc() - 1));
88}
89
90#[inline]
91fn return_inner<'a, E: Ext>(
95 interpreter: &mut Interpreter<crate::vm::evm::EVMInterpreter<'a, E>>,
96 instruction_result: InstructionResult,
97) {
98 let Some([offset, len]) = <_ as StackTr>::popn(&mut interpreter.stack) else {
101 interpreter.halt(InstructionResult::StackUnderflow);
102 return;
103 };
104 let len = as_usize_or_fail!(interpreter, len);
105 let mut output = Bytes::default();
107 if len != 0 {
108 let offset = as_usize_or_fail!(interpreter, offset);
109 resize_memory!(interpreter, offset, len);
110 output = interpreter.memory.slice_len(offset, len).to_vec().into()
111 }
112
113 interpreter.bytecode.set_action(InterpreterAction::new_return(
114 instruction_result,
115 output,
116 interpreter.gas,
117 ));
118}
119
120pub fn ret<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
124 return_inner(context.interpreter, InstructionResult::Return);
125}
126
127pub fn revert<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
129 check!(context.interpreter, BYZANTIUM);
130 return_inner(context.interpreter, InstructionResult::Revert);
131}
132
133pub fn stop<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
135 context.interpreter.halt(InstructionResult::Stop);
136}
137
138pub fn invalid<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
140 context.interpreter.halt(InstructionResult::InvalidFEOpcode);
141}
142
143pub fn unknown<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
145 context.interpreter.halt(InstructionResult::OpcodeNotFound);
146}