通过使用 StorageKey
,您可以拥有嵌套的存储集合,例如将 StorageString
存储在 StorageMap<K, V>
中。
例如,这里我们在一个 storage
块中声明了一些常见的嵌套存储类型:
storage {
nested_map_vec: StorageMap<u64, StorageVec<u8>> = StorageMap {},
nested_map_string: StorageMap<u64, StorageString> = StorageMap {},
nested_vec_bytes: StorageVec<StorageBytes> = StorageVec {},
}
请注意,需要进行存储初始化才能实现这一点。
StorageVec<T>
存储在 StorageMap<K, V>
中 以下演示了如何将嵌套在 StorageMap<T, V>
中的 StorageVec<T>
写入:
// Setup and initialize storage for the StorageVec.
storage.nested_map_vec.try_insert(10, StorageVec {});
// Method 1: Push to the vec directly
storage.nested_map_vec.get(10).push(1u8);
storage.nested_map_vec.get(10).push(2u8);
storage.nested_map_vec.get(10).push(3u8);
// Method 2: First get the storage key and then push the values.
let storage_key_vec: StorageKey<StorageVec<u8>> = storage.nested_map_vec.get(10);
storage_key_vec.push(4u8);
storage_key_vec.push(5u8);
storage_key_vec.push(6u8);
}
#[storage(read, write)]
fn get_map_vec() {
// Method 1: Access the StorageVec directly.
let stored_val1: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val2: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val3: u8 = storage.nested_map_vec.get(10).pop().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageVec<u8>> = storage.nested_map_vec.get(10);
let stored_val4: u8 = storage_key.pop().unwrap();
let stored_val5: u8 = storage_key.pop().unwrap();
let stored_val6: u8 = storage_key.pop().unwrap();
}
#[storage(write)]
fn store_map_string() {
// Setup and initialize storage for the StorageString.
storage.nested_map_string.try_insert(10, StorageString {});
// Method 1: Store the string directly.
let my_string = String::from_ascii_str("Fuel is blazingly fast");
storage.nested_map_string.get(10).write_slice(my_string);
// Method 2: First get the storage key and then write the value.
let my_string = String::from_ascii_str("Fuel is modular");
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
storage_key.write_slice(my_string);
}
#[storage(read)]
fn get_map_string() {
// Method 1: Access the string directly.
let stored_string: String = storage.nested_map_string.get(10).read_slice().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
let stored_string: String = storage_key.read_slice().unwrap();
}
#[storage(write)]
fn store_vec() {
// Setup Bytes to store
let mut my_bytes = Bytes::new();
my_bytes.push(1u8);
my_bytes.push(2u8);
my_bytes.push(3u8);
// Setup and initialize storage for the StorageBytes.
storage.nested_vec_bytes.push(StorageBytes {});
// Method 1: Store the bytes by accessing StorageBytes directly.
storage
.nested_vec_bytes
.get(0)
.unwrap()
.write_slice(my_bytes);
// Method 2: First get the storage key and then write the bytes.
let storage_key: StorageKey<StorageBytes> = storage.nested_vec_bytes.get(0).unwrap();
storage_key.write_slice(my_bytes);
以下演示了如何从嵌套在 StorageMap<T, V>
中的 StorageVec<T>
中读取:
// Method 1: Access the StorageVec directly.
let stored_val1: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val2: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val3: u8 = storage.nested_map_vec.get(10).pop().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageVec<u8>> = storage.nested_map_vec.get(10);
let stored_val4: u8 = storage_key.pop().unwrap();
let stored_val5: u8 = storage_key.pop().unwrap();
let stored_val6: u8 = storage_key.pop().unwrap();
}
#[storage(write)]
fn store_map_string() {
// Setup and initialize storage for the StorageString.
storage.nested_map_string.try_insert(10, StorageString {});
// Method 1: Store the string directly.
let my_string = String::from_ascii_str("Fuel is blazingly fast");
storage.nested_map_string.get(10).write_slice(my_string);
// Method 2: First get the storage key and then write the value.
let my_string = String::from_ascii_str("Fuel is modular");
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
storage_key.write_slice(my_string);
}
#[storage(read)]
fn get_map_string() {
// Method 1: Access the string directly.
let stored_string: String = storage.nested_map_string.get(10).read_slice().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
let stored_string: String = storage_key.read_slice().unwrap();
}
#[storage(write)]
fn store_vec() {
// Setup Bytes to store
let mut my_bytes = Bytes::new();
my_bytes.push(1u8);
my_bytes.push(2u8);
my_bytes.push(3u8);
// Setup and initialize storage for the StorageBytes.
storage.nested_vec_bytes.push(StorageBytes {});
// Method 1: Store the bytes by accessing StorageBytes directly.
storage
.nested_vec_bytes
.get(0)
.unwrap()
.write_slice(my_bytes);
// Method 2: First get the storage key and then write the bytes.
let storage_key: StorageKey<StorageBytes> = storage.nested_vec_bytes.get(0).unwrap();
storage_key.write_slice(my_bytes);
}
#[storage(read, write)]
fn get_vec() {
// Method 1: Access the stored bytes directly.
let stored_bytes: Bytes = storage.nested_vec_bytes.get(0).unwrap().read_slice().unwrap();
// Method 2: First get the storage key and then access the stored bytes.
let storage_key: StorageKey<StorageBytes> = storage.nested_vec_bytes.get(0).unwrap();
let stored_bytes: Bytes = storage_key.read_slice().unwrap();
StorageString
存储在 StorageMap<K, V>
中 以下演示了如何将嵌套在 StorageMap<T, V>
中的 StorageString
写入:
// Setup and initialize storage for the StorageString.
storage.nested_map_string.try_insert(10, StorageString {});
// Method 1: Store the string directly.
let my_string = String::from_ascii_str("Fuel is blazingly fast");
storage.nested_map_string.get(10).write_slice(my_string);
// Method 2: First get the storage key and then write the value.
let my_string = String::from_ascii_str("Fuel is modular");
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
storage_key.write_slice(my_string);
以下演示了如何从嵌套在 StorageMap<T, V>
中的 StorageString
中读取:
// Method 1: Access the string directly.
let stored_string: String = storage.nested_map_string.get(10).read_slice().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
let stored_string: String = storage_key.read_slice().unwrap();
StorageBytes
存储在 StorageVec<T>
中 以下演示了如何将嵌套在 StorageVec<T>
中的 StorageBytes
写入:
// Setup and initialize storage for the StorageVec.
storage.nested_map_vec.try_insert(10, StorageVec {});
// Method 1: Push to the vec directly
storage.nested_map_vec.get(10).push(1u8);
storage.nested_map_vec.get(10).push(2u8);
storage.nested_map_vec.get(10).push(3u8);
// Method 2: First get the storage key and then push the values.
let storage_key_vec: StorageKey<StorageVec<u8>> = storage.nested_map_vec.get(10);
storage_key_vec.push(4u8);
storage_key_vec.push(5u8);
storage_key_vec.push(6u8);
}
#[storage(read, write)]
fn get_map_vec() {
// Method 1: Access the StorageVec directly.
let stored_val1: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val2: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val3: u8 = storage.nested_map_vec.get(10).pop().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageVec<u8>> = storage.nested_map_vec.get(10);
let stored_val4: u8 = storage_key.pop().unwrap();
let stored_val5: u8 = storage_key.pop().unwrap();
let stored_val6: u8 = storage_key.pop().unwrap();
}
#[storage(write)]
fn store_map_string() {
// Setup and initialize storage for the StorageString.
storage.nested_map_string.try_insert(10, StorageString {});
// Method 1: Store the string directly.
let my_string = String::from_ascii_str("Fuel is blazingly fast");
storage.nested_map_string.get(10).write_slice(my_string);
// Method 2: First get the storage key and then write the value.
let my_string = String::from_ascii_str("Fuel is modular");
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
storage_key.write_slice(my_string);
}
#[storage(read)]
fn get_map_string() {
// Method 1: Access the string directly.
let stored_string: String = storage.nested_map_string.get(10).read_slice().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
let stored_string: String = storage_key.read_slice().unwrap();
}
#[storage(write)]
fn store_vec() {
// Setup Bytes to store
let mut my_bytes = Bytes::new();
my_bytes.push(1u8);
my_bytes.push(2u8);
my_bytes.push(3u8);
// Setup and initialize storage for the StorageBytes.
storage.nested_vec_bytes.push(StorageBytes {});
// Method 1: Store the bytes by accessing StorageBytes directly.
storage
.nested_vec_bytes
.get(0)
.unwrap()
.write_slice(my_bytes);
// Method 2: First get the storage key and then write the bytes.
let storage_key: StorageKey<StorageBytes> = storage.nested_vec_bytes.get(0).unwrap();
storage_key.write_slice(my_bytes);
以下演示了如何从嵌套在 StorageVec<T>
中的 StorageBytes
中读取:
// Method 1: Access the StorageVec directly.
let stored_val1: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val2: u8 = storage.nested_map_vec.get(10).pop().unwrap();
let stored_val3: u8 = storage.nested_map_vec.get(10).pop().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageVec<u8>> = storage.nested_map_vec.get(10);
let stored_val4: u8 = storage_key.pop().unwrap();
let stored_val5: u8 = storage_key.pop().unwrap();
let stored_val6: u8 = storage_key.pop().unwrap();
}
#[storage(write)]
fn store_map_string() {
// Setup and initialize storage for the StorageString.
storage.nested_map_string.try_insert(10, StorageString {});
// Method 1: Store the string directly.
let my_string = String::from_ascii_str("Fuel is blazingly fast");
storage.nested_map_string.get(10).write_slice(my_string);
// Method 2: First get the storage key and then write the value.
let my_string = String::from_ascii_str("Fuel is modular");
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
storage_key.write_slice(my_string);
}
#[storage(read)]
fn get_map_string() {
// Method 1: Access the string directly.
let stored_string: String = storage.nested_map_string.get(10).read_slice().unwrap();
// Method 2: First get the storage key and then access the value.
let storage_key: StorageKey<StorageString> = storage.nested_map_string.get(10);
let stored_string: String = storage_key.read_slice().unwrap();
}
#[storage(write)]
fn store_vec() {
// Setup Bytes to store
let mut my_bytes = Bytes::new();
my_bytes.push(1u8);
my_bytes.push(2u8);
my_bytes.push(3u8);
// Setup and initialize storage for the StorageBytes.
storage.nested_vec_bytes.push(StorageBytes {});
// Method 1: Store the bytes by accessing StorageBytes directly.
storage
.nested_vec_bytes
.get(0)
.unwrap()
.write_slice(my_bytes);
// Method 2: First get the storage key and then write the bytes.
let storage_key: StorageKey<StorageBytes> = storage.nested_vec_bytes.get(0).unwrap();
storage_key.write_slice(my_bytes);
}
#[storage(read, write)]
fn get_vec() {
// Method 1: Access the stored bytes directly.
let stored_bytes: Bytes = storage.nested_vec_bytes.get(0).unwrap().read_slice().unwrap();
// Method 2: First get the storage key and then access the stored bytes.
let storage_key: StorageKey<StorageBytes> = storage.nested_vec_bytes.get(0).unwrap();
let stored_bytes: Bytes = storage_key.read_slice().unwrap();
如果希望存储中的值位于不同的位置,例如在加载代码时避免与另一个合约的存储发生冲突,可以使用命名空间注解为插槽计算添加盐。
#[namespace(example_namespace)]
storage {
可以直接利用标准库中提供的 std::storage::storage_api::write
和 std::storage::storage_api::read
函数来利用 FuelVM 存储操作。使用这种方法,您将不得不手动分配用于存储的内部键。示例如下:
contract;
use std::storage::storage_api::{read, write};
abi StorageExample {
#[storage(write)]
fn store_something(amount: u64);
#[storage(read)]
fn get_something() -> u64;
}
const STORAGE_KEY: b256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
impl StorageExample for Contract {
#[storage(write)]
fn store_something(amount: u64) {
write(STORAGE_KEY, 0, amount);
}
#[storage(read)]
fn get_something() -> u64 {
let value: Option<u64> = read::<u64>(STORAGE_KEY, 0);
value.unwrap_or(0)
}
}
注意:虽然这些函数可以用于任何数据类型,但它们主要用于数组,因为数组尚未在
storage
块中受到支持。但请注意,所有 数据类型都可以作为StorageMap<K, V>
中的键和/或值的类型使用,没有任何限制。