zksync_vm2/instruction_handlers/
near_call.rs1use zksync_vm2_interface::{opcodes, Tracer};
2
3use super::common::boilerplate;
4use crate::{
5 addressing_modes::{Arguments, Immediate1, Immediate2, Register1, Source},
6 instruction::ExecutionStatus,
7 predication::Flags,
8 Instruction, VirtualMachine, World,
9};
10
11fn near_call<T: Tracer, W: World<T>>(
12 vm: &mut VirtualMachine<T, W>,
13 world: &mut W,
14 tracer: &mut T,
15) -> ExecutionStatus {
16 boilerplate::<opcodes::NearCall, _, _>(vm, world, tracer, |vm, args| {
17 let gas_to_pass = Register1::get(args, &mut vm.state).low_u32();
18 let destination = Immediate1::get_u16(args);
19 let error_handler = Immediate2::get_u16(args);
20
21 let new_frame_gas = if gas_to_pass == 0 {
22 vm.state.current_frame.gas
23 } else {
24 gas_to_pass.min(vm.state.current_frame.gas)
25 };
26 vm.state.current_frame.push_near_call(
27 new_frame_gas,
28 error_handler,
29 vm.world_diff.snapshot(),
30 );
31
32 vm.state.flags = Flags::new(false, false, false);
33
34 vm.state.current_frame.set_pc_from_u16(destination);
35 })
36}
37
38impl<T: Tracer, W: World<T>> Instruction<T, W> {
39 pub fn from_near_call(
41 gas: Register1,
42 destination: Immediate1,
43 error_handler: Immediate2,
44 arguments: Arguments,
45 ) -> Self {
46 Self {
47 handler: near_call,
48 arguments: arguments
49 .write_source(&gas)
50 .write_source(&destination)
51 .write_source(&error_handler),
52 }
53 }
54}