zksync_vm2/instruction_handlers/
storage.rs1use 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 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 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 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 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}