zink/storage/
mapping.rs

1//! Storage Mapping
2
3use crate::{
4    ffi,
5    storage::{StorageValue, TransientStorageValue},
6    Asm,
7};
8
9/// Storage mapping interface
10pub trait Mapping {
11    const STORAGE_SLOT: i32;
12
13    type Key: Asm;
14    type Value: StorageValue;
15
16    #[cfg(not(target_family = "wasm"))]
17    fn storage_key(key: Self::Key) -> [u8; 32];
18
19    /// Get value from storage key.
20    fn get(key: Self::Key) -> Self::Value {
21        load_key(key, Self::STORAGE_SLOT);
22        Self::Value::sload()
23    }
24
25    /// Set key and value
26    fn set(key: Self::Key, value: Self::Value) {
27        value.push();
28        load_key(key, Self::STORAGE_SLOT);
29        unsafe {
30            ffi::evm::sstore();
31        }
32    }
33}
34
35/// Transient storage mapping interface
36pub trait TransientMapping {
37    const STORAGE_SLOT: i32;
38
39    type Key: Asm;
40    type Value: TransientStorageValue;
41
42    #[cfg(not(target_family = "wasm"))]
43    fn storage_key(key: Self::Key) -> [u8; 32];
44
45    /// Get value from transient storage key.
46    fn get(key: Self::Key) -> Self::Value {
47        load_key(key, Self::STORAGE_SLOT);
48        Self::Value::tload()
49    }
50
51    /// Set key and value in transient storage
52    fn set(key: Self::Key, value: Self::Value) {
53        value.push();
54        load_key(key, Self::STORAGE_SLOT);
55        unsafe {
56            ffi::evm::tstore();
57        }
58    }
59}
60
61/// Load storage key to stack
62pub fn load_key(key: impl Asm, index: i32) {
63    unsafe {
64        ffi::label_reserve_mem_32();
65
66        // write key to memory
67        key.push();
68        ffi::evm::push0();
69        ffi::evm::mstore();
70
71        // write index to memory
72        index.push();
73        ffi::asm::push_u8(0x20);
74        ffi::evm::mstore();
75
76        // hash key
77        ffi::asm::push_u8(0x40);
78        ffi::evm::push0();
79        ffi::evm::keccak256();
80    }
81}