zink/storage/
dkmapping.rs

1//! Double key mapping
2
3use crate::{asm, storage::Value};
4
5/// Storage mapping interface
6pub trait DoubleKeyMapping {
7    const STORAGE_SLOT: i32;
8
9    type Key1: Value;
10    type Key2: Value;
11    type Value: Value;
12
13    #[cfg(not(target_family = "wasm"))]
14    fn storage_key(key1: Self::Key1, key2: Self::Key2) -> [u8; 32];
15
16    /// Get value from storage key.
17    #[inline(always)]
18    fn get(key1: Self::Key1, key2: Self::Key2) -> Self::Value {
19        load_double_key(key1, key2, Self::STORAGE_SLOT);
20        Self::Value::sload()
21    }
22
23    /// Set key and value
24    #[inline(always)]
25    fn set(key1: Self::Key1, key2: Self::Key2, value: Self::Value) {
26        value.push();
27        load_double_key(key1, key2, Self::STORAGE_SLOT);
28        unsafe {
29            asm::evm::sstore();
30        }
31    }
32}
33
34/// Transient storage mapping interface
35pub trait DoubleKeyTransientMapping {
36    const STORAGE_SLOT: i32;
37
38    type Key1: Value;
39    type Key2: Value;
40    type Value: Value;
41
42    #[cfg(not(target_family = "wasm"))]
43    fn storage_key(key1: Self::Key1, key2: Self::Key2) -> [u8; 32];
44
45    /// Get value from transient storage key.
46    #[inline(always)]
47    fn get(key1: Self::Key1, key2: Self::Key2) -> Self::Value {
48        load_double_key(key1, key2, Self::STORAGE_SLOT);
49        Self::Value::tload()
50    }
51
52    /// Set key and value in transient storage
53    #[inline(always)]
54    fn set(key1: Self::Key1, key2: Self::Key2, value: Self::Value) {
55        value.push();
56        load_double_key(key1, key2, Self::STORAGE_SLOT);
57        unsafe {
58            asm::evm::tstore();
59        }
60    }
61}
62
63/// Load storage key to stack
64#[inline(always)]
65pub fn load_double_key(key1: impl Value, key2: impl Value, index: i32) {
66    unsafe {
67        asm::label_reserve_mem_64();
68
69        // write key1 to memory
70        key1.push();
71        asm::evm::push0();
72        asm::evm::mstore();
73
74        // write index to memory
75        index.push();
76        asm::ext::push_u8(0x20);
77        asm::evm::mstore();
78
79        // hash key
80        asm::ext::push_u8(0x40);
81        asm::evm::push0();
82        asm::evm::keccak256();
83
84        // stores the hash
85        asm::evm::push0();
86        asm::evm::mstore();
87
88        // write index to memory
89        key2.push();
90        asm::ext::push_u8(0x20);
91        asm::evm::mstore();
92
93        // hash key
94        asm::ext::push_u8(0x40);
95        asm::evm::push0();
96        asm::evm::keccak256();
97    }
98}