Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clear() to StorageKey api #5284

Merged
merged 12 commits into from
Nov 24, 2023
33 changes: 33 additions & 0 deletions sway-lib-std/src/storage/storage_key.sw
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,39 @@ impl<T> StorageKey<T> {
write(self.slot, self.offset, value);
}

/// Clears the value at `self`.
///
/// # Number of Storage Accesses
///
/// * Clears: `1`
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let r: StorageKey<u64> = StorageKey {
/// slot: 0x0000000000000000000000000000000000000000000000000000000000000000,
/// offset: 2,
/// field_id: 0x0000000000000000000000000000000000000000000000000000000000000000,
/// };
/// r.write(42);
///
/// let cleared = r.clear();
/// assert(cleared);
/// }
/// ```
#[storage(write)]
pub fn clear(self) -> bool {
if __size_of::<T>() == 0 {
// If the generic doesn't have a size, this is an empty struct and nothing can be stored at the slot.
// This clears the length value for StorageVec, StorageString, and StorageBytes
// or any other Storage type.
clear::<u64>(self.field_id, 0)
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
} else {
clear::<T>(self.slot, self.offset)
}
}

/// Create a new `StorageKey`.
///
/// # Arguments
Expand Down
28 changes: 0 additions & 28 deletions sway-lib-std/src/storage/storage_vec.sw
Original file line number Diff line number Diff line change
Expand Up @@ -481,34 +481,6 @@ impl<V> StorageKey<StorageVec<V>> {
read::<u64>(self.field_id, 0).unwrap_or(0) == 0
}

/// Sets the len to zero.
///
/// # Number of Storage Accesses
///
/// * Clears: `1`
///
/// # Examples
///
/// ```sway
/// use std::storage::storage_vec::*;
///
/// storage {
/// vec: StorageVec<u64> = StorageVec {}
/// }
///
/// fn foo() {
/// assert(0 == storage.vec.len());
/// storage.vec.push(5);
/// assert(1 == storage.vec.len());
/// storage.vec.clear();
/// assert(0 == storage.vec.len());
/// }
/// ```
#[storage(write)]
pub fn clear(self) {
let _ = clear::<u64>(self.field_id, 0);
}

/// Swaps two elements.
///
/// # Arguments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ category = "compile"

# check: $()Storage write after external contract interaction in function or method "withdraw". Consider making all storage writes before calling another contract
# check: $()Storage write after external contract interaction in function or method "withdraw". Consider making all storage writes before calling another contract
expected_warnings = 4
expected_warnings = 5
15 changes: 15 additions & 0 deletions test/src/sdk-harness/test_projects/storage_access/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,18 @@ async fn maps_in_struct_access() {
(None, None)
);
}

#[tokio::test]
async fn clears_storage_key() {
let methods = test_storage_access_instance().await.methods();

assert_eq!(
methods
.clears_storage_key()
.call()
.await
.unwrap()
.value,
true
);
}
17 changes: 16 additions & 1 deletion test/src/sdk-harness/test_projects/storage_access/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
contract;

use std::hash::*;
use std::{constants::ZERO_B256, hash::*};

struct M {
u: b256,
Expand Down Expand Up @@ -108,6 +108,9 @@ abi ExperimentalStorageTest {

#[storage(read, write)]
fn map_in_struct_write(key: (u64, u64), value: (u64, u64));

#[storage(read, write)]
fn clears_storage_key() -> bool;
}

impl ExperimentalStorageTest for Contract {
Expand Down Expand Up @@ -226,4 +229,16 @@ impl ExperimentalStorageTest for Contract {
storage.s2.map0.insert(key.0, value.0);
storage.s2.map1.insert(key.1, value.1);
}

#[storage(read, write)]
fn clears_storage_key() -> bool {
let key = StorageKey::<u64>::new(ZERO_B256, 0, ZERO_B256);
key.write(42);

assert(key.read() == 42);
let cleared = key.clear();
assert(cleared);
assert(key.try_read().is_none());
cleared
}
}
Loading