Skip to main content

zksync_vm2/instruction_handlers/
near_call.rs

1use 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    /// Creates a [`NearCall`](opcodes::NearCall) instruction with the provided params.
40    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}