Mappings in Solidity are hash tables that store data as key-value pairs, where the key can be any of the built-in data types supported by Ethereum.
Here we will give you the example of mapping in Stylus Rust SDK.
Maps are created with the syntax StorageMap<keyType, StorageType>
(rust syntax) or mapping(keyType => valueType)
(solidity syntax).
If you define with rust syntax, the keyType should be the type from alloy_primitives
, valueType can be be any type from StorageType
.
If you define with solidity syntax, the keyType can be any built-in value type, bytes, string, or any contract, valueType can be any type including another mapping or an array.
Mappings are not iterable.
src/lib.rs
1// Allow `cargo stylus export-abi` to generate a main function.
2#![cfg_attr(not(feature = "export-abi"), no_main)]
3extern crate alloc;
4
5/// Import items from the SDK. The prelude contains common traits and macros.
6use stylus_sdk::{prelude::*, alloy_primitives::{Address, U256}};
7use stylus_sdk::storage::{*};
8
9#[storage]
10#[entrypoint]
11pub struct Mapping {
12 my_map: StorageMap<Address, StorageBool>,
13 my_nested_map: StorageMap<U256, StorageMap<Address, StorageBool>>,
14}
15
16// You can also define mapping storage using the Solidity syntax.
17// sol_storage! {
18// #[entrypoint]
19// pub struct Mapping {
20// mapping(address => bool) my_map;
21// mapping(uint256 => mapping(address => bool)) my_nested_map;
22// }
23// }
24
25
26/// Declare that `Mapping` is a contract with the following external methods.
27#[public]
28impl Mapping {
29
30 // First is the simple map ========================================
31
32 pub fn get_my_map(&self, target: Address) -> bool {
33 // Mapping always returns a value.
34 // If the value was never set, it will return the default value.
35 self.my_map.get(target)
36 }
37
38 pub fn set_my_map(&mut self, target: Address, new_value: bool) {
39 // Update the value at this address
40 self.my_map.setter(target).set(new_value);
41 }
42
43 pub fn remove_my_map(&mut self, target: Address) {
44 // Reset the value to the default value.
45 self.my_map.delete(target);
46 }
47
48 // Next is the nested map ========================================
49
50 pub fn get_my_nested_map(&self, index: U256, target: Address) -> bool {
51 // Mapping always returns a value.
52 // If the value was never set, it will return the default value.
53 self.my_nested_map.get(index).get(target)
54 }
55
56 pub fn set_my_nested_map(&mut self, index: U256, target: Address, new_value: bool) {
57 // Update the value at this address
58 self.my_nested_map.setter(index).setter(target).set(new_value);
59 }
60
61 pub fn remove_my_nested_map(&mut self, index: U256, target: Address) {
62 // Reset the value to the default value.
63 self.my_nested_map.setter(index).delete(target);
64 }
65}
1// Allow `cargo stylus export-abi` to generate a main function.
2#![cfg_attr(not(feature = "export-abi"), no_main)]
3extern crate alloc;
4
5/// Import items from the SDK. The prelude contains common traits and macros.
6use stylus_sdk::{prelude::*, alloy_primitives::{Address, U256}};
7use stylus_sdk::storage::{*};
8
9#[storage]
10#[entrypoint]
11pub struct Mapping {
12 my_map: StorageMap<Address, StorageBool>,
13 my_nested_map: StorageMap<U256, StorageMap<Address, StorageBool>>,
14}
15
16// You can also define mapping storage using the Solidity syntax.
17// sol_storage! {
18// #[entrypoint]
19// pub struct Mapping {
20// mapping(address => bool) my_map;
21// mapping(uint256 => mapping(address => bool)) my_nested_map;
22// }
23// }
24
25
26/// Declare that `Mapping` is a contract with the following external methods.
27#[public]
28impl Mapping {
29
30 // First is the simple map ========================================
31
32 pub fn get_my_map(&self, target: Address) -> bool {
33 // Mapping always returns a value.
34 // If the value was never set, it will return the default value.
35 self.my_map.get(target)
36 }
37
38 pub fn set_my_map(&mut self, target: Address, new_value: bool) {
39 // Update the value at this address
40 self.my_map.setter(target).set(new_value);
41 }
42
43 pub fn remove_my_map(&mut self, target: Address) {
44 // Reset the value to the default value.
45 self.my_map.delete(target);
46 }
47
48 // Next is the nested map ========================================
49
50 pub fn get_my_nested_map(&self, index: U256, target: Address) -> bool {
51 // Mapping always returns a value.
52 // If the value was never set, it will return the default value.
53 self.my_nested_map.get(index).get(target)
54 }
55
56 pub fn set_my_nested_map(&mut self, index: U256, target: Address, new_value: bool) {
57 // Update the value at this address
58 self.my_nested_map.setter(index).setter(target).set(new_value);
59 }
60
61 pub fn remove_my_nested_map(&mut self, index: U256, target: Address) {
62 // Reset the value to the default value.
63 self.my_nested_map.setter(index).delete(target);
64 }
65}
Cargo.toml
1[package]
2name = "stylus-mapping-example"
3version = "0.1.7"
4edition = "2021"
5
6[dependencies]
7alloy-primitives = "=0.7.6"
8alloy-sol-types = "=0.7.6"
9stylus-sdk = "0.6.0"
10hex = "0.4.3"
11
12[dev-dependencies]
13tokio = { version = "1.12.0", features = ["full"] }
14ethers = "2.0"
15eyre = "0.6.8"
16
17[features]
18export-abi = ["stylus-sdk/export-abi"]
19
20[lib]
21crate-type = ["lib", "cdylib"]
1[package]
2name = "stylus-mapping-example"
3version = "0.1.7"
4edition = "2021"
5
6[dependencies]
7alloy-primitives = "=0.7.6"
8alloy-sol-types = "=0.7.6"
9stylus-sdk = "0.6.0"
10hex = "0.4.3"
11
12[dev-dependencies]
13tokio = { version = "1.12.0", features = ["full"] }
14ethers = "2.0"
15eyre = "0.6.8"
16
17[features]
18export-abi = ["stylus-sdk/export-abi"]
19
20[lib]
21crate-type = ["lib", "cdylib"]