Skip to main content

zksync_vm2/instruction_handlers/
storage.rs

1use zksync_vm2_interface::{opcodes, Tracer};
2
3use super::common::{boilerplate, boilerplate_ext};
4use crate::{
5    addressing_modes::{
6        Arguments, Destination, Register1, Register2, Source, SLOAD_COST, SSTORE_COST,
7    },
8    instruction::ExecutionStatus,
9    Instruction, VirtualMachine, World,
10};
11
12fn sstore<T: Tracer, W: World<T>>(
13    vm: &mut VirtualMachine<T, W>,
14    world: &mut W,
15    tracer: &mut T,
16) -> ExecutionStatus {
17    boilerplate_ext::<opcodes::StorageWrite, _, _>(vm, world, tracer, |vm, args, world, tracer| {
18        let key = Register1::get(args, &mut vm.state);
19        let value = Register2::get(args, &mut vm.state);
20
21        let refund = vm.world_diff.write_storage(
22            world,
23            tracer,
24            vm.state.current_frame.address,
25            key,
26            value,
27            vm.state.transaction_number,
28        );
29
30        assert!(refund <= SSTORE_COST);
31        vm.state.current_frame.gas += refund;
32    })
33}
34
35fn sstore_transient<T: Tracer, W: World<T>>(
36    vm: &mut VirtualMachine<T, W>,
37    world: &mut W,
38    tracer: &mut T,
39) -> ExecutionStatus {
40    boilerplate::<opcodes::TransientStorageWrite, _, _>(vm, world, tracer, |vm, args| {
41        let key = Register1::get(args, &mut vm.state);
42        let value = Register2::get(args, &mut vm.state);
43
44        vm.world_diff
45            .write_transient_storage(vm.state.current_frame.address, key, value);
46    })
47}
48
49fn sload<T: Tracer, W: World<T>>(
50    vm: &mut VirtualMachine<T, W>,
51    world: &mut W,
52    tracer: &mut T,
53) -> ExecutionStatus {
54    boilerplate_ext::<opcodes::StorageRead, _, _>(vm, world, tracer, |vm, args, world, tracer| {
55        let key = Register1::get(args, &mut vm.state);
56
57        let (value, refund) = vm.world_diff.read_storage(
58            world,
59            tracer,
60            vm.state.current_frame.address,
61            key,
62            vm.state.transaction_number,
63        );
64
65        assert!(refund <= SLOAD_COST);
66        vm.state.current_frame.gas += refund;
67
68        Register1::set(args, &mut vm.state, value);
69    })
70}
71
72fn sload_transient<T: Tracer, W: World<T>>(
73    vm: &mut VirtualMachine<T, W>,
74    world: &mut W,
75    tracer: &mut T,
76) -> ExecutionStatus {
77    boilerplate::<opcodes::TransientStorageRead, _, _>(vm, world, tracer, |vm, args| {
78        let key = Register1::get(args, &mut vm.state);
79        let value = vm
80            .world_diff
81            .read_transient_storage(vm.state.current_frame.address, key);
82
83        Register1::set(args, &mut vm.state, value);
84    })
85}
86
87impl<T: Tracer, W: World<T>> Instruction<T, W> {
88    /// Creates a [`StorageWrite`](opcodes::StorageWrite) instruction with the provided params.
89    pub fn from_storage_write(src1: Register1, src2: Register2, arguments: Arguments) -> Self {
90        Self {
91            handler: sstore,
92            arguments: arguments.write_source(&src1).write_source(&src2),
93        }
94    }
95
96    /// Creates a [`TransientStorageWrite`](opcodes::TransientStorageWrite) instruction with the provided params.
97    pub fn from_transient_storage_write(
98        src1: Register1,
99        src2: Register2,
100        arguments: Arguments,
101    ) -> Self {
102        Self {
103            handler: sstore_transient,
104            arguments: arguments.write_source(&src1).write_source(&src2),
105        }
106    }
107
108    /// Creates a [`StorageRead`](opcodes::StorageRead) instruction with the provided params.
109    pub fn from_storage_read(src: Register1, dst: Register1, arguments: Arguments) -> Self {
110        Self {
111            handler: sload,
112            arguments: arguments.write_source(&src).write_destination(&dst),
113        }
114    }
115
116    /// Creates a [`TransientStorageRead`](opcodes::TransientStorageRead) instruction with the provided params.
117    pub fn from_transient_storage_read(
118        src: Register1,
119        dst: Register1,
120        arguments: Arguments,
121    ) -> Self {
122        Self {
123            handler: sload_transient,
124            arguments: arguments.write_source(&src).write_destination(&dst),
125        }
126    }
127}