Advanced Storage

Icon Link高级存储

Icon Link嵌套存储集合

通过使用 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 {},
}

请注意,需要进行存储初始化才能实现这一点。

Icon LinkStorageVec<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();

Icon LinkStorageString 存储在 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();

Icon LinkStorageBytes 存储在 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();

Icon Link存储命名空间

如果希望存储中的值位于不同的位置,例如在加载代码时避免与另一个合约的存储发生冲突,可以使用命名空间注解为插槽计算添加盐。

#[namespace(example_namespace)]
storage {

Icon Link手动存储管理

可以直接利用标准库中提供的 std::storage::storage_api::writestd::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)
    }
}
 
Icon InfoCircle

注意:虽然这些函数可以用于任何数据类型,但它们主要用于数组,因为数组尚未在 storage 块中受到支持。但请注意,所有 数据类型都可以作为 StorageMap<K, V> 中的键和/或值的类型使用,没有任何限制。