zksync_vm2_interface/
state_interface.rs

1use primitive_types::{H160, U256};
2
3/// Public interface of the VM state. Encompasses both read and write methods.
4pub trait StateInterface {
5    /// Reads a register with the specified zero-based index. Returns a value together with a pointer flag.
6    fn read_register(&self, register: u8) -> (U256, bool);
7    /// Sets a register with the specified zero-based index
8    fn set_register(&mut self, register: u8, value: U256, is_pointer: bool);
9
10    /// Returns a mutable handle to the current call frame.
11    fn current_frame(&mut self) -> impl CallframeInterface + '_;
12    /// Returns the total number of call frames.
13    fn number_of_callframes(&self) -> usize;
14    /// Returns a mutable handle to a call frame with the specified index, where
15    /// zero is the current frame, one is the frame before that etc.
16    fn callframe(&mut self, n: usize) -> impl CallframeInterface + '_;
17
18    /// Reads a single byte from the specified heap at the specified 0-based offset.
19    fn read_heap_byte(&self, heap: HeapId, offset: u32) -> u8;
20    /// Reads an entire `U256` word in the big-endian order from the specified heap / `offset`
21    /// (which is the index of the most significant byte of the read value).
22    fn read_heap_u256(&self, heap: HeapId, offset: u32) -> U256;
23    /// Writes an entire `U256` word in the big-endian order to the specified heap at the specified `offset`
24    /// (which is the index of the most significant byte of the written value).
25    fn write_heap_u256(&mut self, heap: HeapId, offset: u32, value: U256);
26
27    /// Returns current execution flags.
28    fn flags(&self) -> Flags;
29    /// Sets current execution flags.
30    fn set_flags(&mut self, flags: Flags);
31
32    /// Returns the currently set 0-based transaction number.
33    fn transaction_number(&self) -> u16;
34    /// Sets the current transaction number.
35    fn set_transaction_number(&mut self, value: u16);
36
37    /// Returns the value of the context register.
38    fn context_u128_register(&self) -> u128;
39    /// Sets the value of the context register.
40    fn set_context_u128_register(&mut self, value: u128);
41
42    /// Iterates over storage slots read or written during VM execution.
43    fn get_storage_state(&self) -> impl Iterator<Item = ((H160, U256), U256)>;
44
45    /// Iterates over all transient storage slots set during VM execution.
46    fn get_transient_storage_state(&self) -> impl Iterator<Item = ((H160, U256), U256)>;
47    /// Gets value of the specified transient storage slot.
48    fn get_transient_storage(&self, address: H160, slot: U256) -> U256;
49    /// Sets value of the specified transient storage slot.
50    fn write_transient_storage(&mut self, address: H160, slot: U256, value: U256);
51
52    /// Iterates over events emitted during VM execution.
53    fn events(&self) -> impl Iterator<Item = Event>;
54    /// Iterates over L2-to-L1 logs emitted during VM execution.
55    fn l2_to_l1_logs(&self) -> impl Iterator<Item = L2ToL1Log>;
56
57    /// Gets the current amount of published pubdata.
58    fn pubdata(&self) -> i32;
59    /// Sets the current amount of published pubdata.
60    fn set_pubdata(&mut self, value: i32);
61}
62
63/// State interface with access to global state like storage.
64pub trait GlobalStateInterface: StateInterface {
65    /// Gets value of the specified storage slot.
66    fn get_storage(&mut self, address: H160, slot: U256) -> U256;
67}
68
69/// VM execution flags. See the EraVM reference for more details.
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
71pub struct Flags {
72    /// "Less than" flag.
73    pub less_than: bool,
74    /// "Equal" flag.
75    pub equal: bool,
76    /// "Greater than" flag.
77    pub greater: bool,
78}
79
80/// Public interface of an EraVM call frame.
81pub trait CallframeInterface {
82    /// Address of the storage context associated with this frame. For delegate calls, this address is inherited from the calling contract;
83    /// otherwise, it's the same as [`Self::code_address()`].
84    fn address(&self) -> H160;
85    /// Sets the address of the executing contract.
86    fn set_address(&mut self, address: H160);
87    /// Address of the contract being executed.
88    fn code_address(&self) -> H160;
89    /// Sets the address of the contract being executed. Does not cause the contract at the specified address get loaded per se, just updates
90    /// the value used internally by the VM (e.g., returned by the [`CodeAddress`](crate::opcodes::CodeAddress) opcode).
91    fn set_code_address(&mut self, address: H160);
92    /// Address of the calling contract. Respects delegate and mimic calls.
93    fn caller(&self) -> H160;
94    /// Sets the address of the calling contract.
95    fn set_caller(&mut self, address: H160);
96
97    /// Returns the current program counter (i.e., 0-based index of the instruction being executed).
98    /// During panic this returns `None`.
99    fn program_counter(&self) -> Option<u16>;
100    /// Sets the program counter.
101    /// The VM will execute an invalid instruction if you jump out of the program.
102    fn set_program_counter(&mut self, value: u16);
103
104    /// Returns the program counter that the parent frame should continue from if this frame fails.
105    fn exception_handler(&self) -> u16;
106    /// Sets the exception handler as specified [above](Self::exception_handler()).
107    fn set_exception_handler(&mut self, value: u16);
108
109    /// Checks whether the call is static.
110    fn is_static(&self) -> bool;
111    /// Checks whether the call is executed in kernel mode.
112    fn is_kernel(&self) -> bool;
113
114    /// Returns the remaining amount of gas.
115    fn gas(&self) -> u32;
116    /// Sets the remaining amount of gas.
117    fn set_gas(&mut self, new_gas: u32);
118
119    /// Returns the context value for this call. This context is accessible via [`ContextU128`](crate::opcodes::ContextU128) opcode.
120    fn context_u128(&self) -> u128;
121    /// Sets the context value for this call.
122    fn set_context_u128(&mut self, value: u128);
123
124    /// Checks whether this frame corresponds to a near call.
125    fn is_near_call(&self) -> bool;
126
127    /// Reads the specified stack slot. Returns a value together with a pointer flag.
128    fn read_stack(&self, index: u16) -> (U256, bool);
129    /// Sets the value and pointer flag for the specified stack slot.
130    fn write_stack(&mut self, index: u16, value: U256, is_pointer: bool);
131
132    /// Returns the stack pointer.
133    fn stack_pointer(&self) -> u16;
134    /// Sets the stack pointer.
135    fn set_stack_pointer(&mut self, value: u16);
136
137    /// Returns ID of the main heap used in this call.
138    fn heap(&self) -> HeapId;
139    /// Returns the main heap boundary (number of paid bytes).
140    fn heap_bound(&self) -> u32;
141    /// Sets the main heap boundary.
142    fn set_heap_bound(&mut self, value: u32);
143
144    /// Returns ID of the auxiliary heap used in this call.
145    fn aux_heap(&self) -> HeapId;
146    /// Returns the auxiliary heap boundary (number of paid bytes).
147    fn aux_heap_bound(&self) -> u32;
148    /// Sets the auxiliary heap boundary.
149    fn set_aux_heap_bound(&mut self, value: u32);
150
151    /// Reads a word from the bytecode of the executing contract.
152    fn read_contract_code(&self, slot: u16) -> U256;
153}
154
155/// Identifier of a VM heap.
156///
157/// EraVM docs sometimes refer to heaps as *heap pages*; docs in these crate don't to avoid confusion with internal heap structure.
158#[derive(Copy, Clone, PartialEq, Debug)]
159pub struct HeapId(u32);
160
161impl HeapId {
162    /// Identifier of the calldata heap used by the first executed program (i.e., the bootloader).
163    pub const FIRST_CALLDATA: Self = Self(1);
164    /// Identifier of the heap used by the first executed program (i.e., the bootloader).
165    pub const FIRST: Self = Self(2);
166    /// Identifier of the auxiliary heap used by the first executed program (i.e., the bootloader)
167    pub const FIRST_AUX: Self = Self(3);
168
169    /// Only for dealing with external data structures, never use internally.
170    #[doc(hidden)]
171    pub const fn from_u32_unchecked(value: u32) -> Self {
172        Self(value)
173    }
174
175    /// Converts this ID to an integer value.
176    pub const fn as_u32(self) -> u32 {
177        self.0
178    }
179}
180
181/// Event emitted by EraVM.
182///
183/// There is no address field because nobody is interested in events that don't come
184/// from the event writer, so we simply do not record events coming from anywhere else.
185#[derive(Debug, Clone, Copy, PartialEq)]
186pub struct Event {
187    /// Event key.
188    pub key: U256,
189    /// Event value.
190    pub value: U256,
191    /// Is this event first in a chain of events?
192    pub is_first: bool,
193    /// Shard identifier (currently, always set to 0).
194    pub shard_id: u8,
195    /// 0-based index of a transaction that has emitted this event.
196    pub tx_number: u16,
197}
198
199/// L2-to-L1 log emitted by EraVM.
200#[derive(Debug, Clone, Copy, PartialEq)]
201pub struct L2ToL1Log {
202    /// Log key.
203    pub key: U256,
204    /// Log value.
205    pub value: U256,
206    /// Is this a service log?
207    pub is_service: bool,
208    /// Address of the contract that has emitted this log.
209    pub address: H160,
210    /// Shard identifier (currently, always set to 0).
211    pub shard_id: u8,
212    /// 0-based index of a transaction that has emitted this event.
213    pub tx_number: u16,
214}
215
216#[cfg(test)]
217pub(crate) mod testonly {
218    use primitive_types::{H160, U256};
219
220    use super::{
221        CallframeInterface, Event, Flags, GlobalStateInterface, HeapId, L2ToL1Log, StateInterface,
222    };
223
224    #[derive(Debug)]
225    pub(crate) struct DummyState;
226
227    impl StateInterface for DummyState {
228        fn read_register(&self, _: u8) -> (U256, bool) {
229            unimplemented!()
230        }
231
232        fn set_register(&mut self, _: u8, _: U256, _: bool) {
233            unimplemented!()
234        }
235
236        fn current_frame(&mut self) -> impl CallframeInterface + '_ {
237            DummyState
238        }
239
240        fn number_of_callframes(&self) -> usize {
241            unimplemented!()
242        }
243
244        fn callframe(&mut self, _: usize) -> impl CallframeInterface + '_ {
245            DummyState
246        }
247
248        fn read_heap_byte(&self, _: HeapId, _: u32) -> u8 {
249            unimplemented!()
250        }
251
252        fn read_heap_u256(&self, _: HeapId, _: u32) -> U256 {
253            unimplemented!()
254        }
255
256        fn write_heap_u256(&mut self, _: HeapId, _: u32, _: U256) {
257            unimplemented!()
258        }
259
260        fn flags(&self) -> Flags {
261            unimplemented!()
262        }
263
264        fn set_flags(&mut self, _: Flags) {
265            unimplemented!()
266        }
267
268        fn transaction_number(&self) -> u16 {
269            unimplemented!()
270        }
271
272        fn set_transaction_number(&mut self, _: u16) {
273            unimplemented!()
274        }
275
276        fn context_u128_register(&self) -> u128 {
277            unimplemented!()
278        }
279
280        fn set_context_u128_register(&mut self, _: u128) {
281            unimplemented!()
282        }
283
284        fn get_storage_state(&self) -> impl Iterator<Item = ((H160, U256), U256)> {
285            std::iter::empty()
286        }
287
288        fn get_transient_storage_state(&self) -> impl Iterator<Item = ((H160, U256), U256)> {
289            std::iter::empty()
290        }
291
292        fn get_transient_storage(&self, _: H160, _: U256) -> U256 {
293            unimplemented!()
294        }
295
296        fn write_transient_storage(&mut self, _: H160, _: U256, _: U256) {
297            unimplemented!()
298        }
299
300        fn events(&self) -> impl Iterator<Item = Event> {
301            std::iter::empty()
302        }
303
304        fn l2_to_l1_logs(&self) -> impl Iterator<Item = L2ToL1Log> {
305            std::iter::empty()
306        }
307
308        fn pubdata(&self) -> i32 {
309            unimplemented!()
310        }
311
312        fn set_pubdata(&mut self, _: i32) {
313            unimplemented!()
314        }
315    }
316
317    impl GlobalStateInterface for DummyState {
318        fn get_storage(&mut self, _: H160, _: U256) -> U256 {
319            unimplemented!()
320        }
321    }
322
323    impl CallframeInterface for DummyState {
324        fn address(&self) -> H160 {
325            unimplemented!()
326        }
327
328        fn set_address(&mut self, _: H160) {
329            unimplemented!()
330        }
331
332        fn code_address(&self) -> H160 {
333            unimplemented!()
334        }
335
336        fn set_code_address(&mut self, _: H160) {
337            unimplemented!()
338        }
339
340        fn caller(&self) -> H160 {
341            unimplemented!()
342        }
343
344        fn set_caller(&mut self, _: H160) {
345            unimplemented!()
346        }
347
348        fn program_counter(&self) -> Option<u16> {
349            unimplemented!()
350        }
351
352        fn set_program_counter(&mut self, _: u16) {
353            unimplemented!()
354        }
355
356        fn exception_handler(&self) -> u16 {
357            unimplemented!()
358        }
359
360        fn set_exception_handler(&mut self, _: u16) {
361            unimplemented!()
362        }
363
364        fn is_static(&self) -> bool {
365            unimplemented!()
366        }
367
368        fn is_kernel(&self) -> bool {
369            unimplemented!()
370        }
371
372        fn gas(&self) -> u32 {
373            unimplemented!()
374        }
375
376        fn set_gas(&mut self, _: u32) {
377            unimplemented!()
378        }
379
380        fn context_u128(&self) -> u128 {
381            unimplemented!()
382        }
383
384        fn set_context_u128(&mut self, _: u128) {
385            unimplemented!()
386        }
387
388        fn is_near_call(&self) -> bool {
389            unimplemented!()
390        }
391
392        fn read_stack(&self, _: u16) -> (U256, bool) {
393            unimplemented!()
394        }
395
396        fn write_stack(&mut self, _: u16, _: U256, _: bool) {
397            unimplemented!()
398        }
399
400        fn stack_pointer(&self) -> u16 {
401            unimplemented!()
402        }
403
404        fn set_stack_pointer(&mut self, _: u16) {
405            unimplemented!()
406        }
407
408        fn heap(&self) -> HeapId {
409            unimplemented!()
410        }
411
412        fn heap_bound(&self) -> u32 {
413            unimplemented!()
414        }
415
416        fn set_heap_bound(&mut self, _: u32) {
417            unimplemented!()
418        }
419
420        fn aux_heap(&self) -> HeapId {
421            unimplemented!()
422        }
423
424        fn aux_heap_bound(&self) -> u32 {
425            unimplemented!()
426        }
427
428        fn set_aux_heap_bound(&mut self, _: u32) {
429            unimplemented!()
430        }
431
432        fn read_contract_code(&self, _: u16) -> U256 {
433            unimplemented!()
434        }
435    }
436}