From 68e6a225df5b84d552a709211ddf8523fc894714 Mon Sep 17 00:00:00 2001 From: Turan Ege Caner Date: Fri, 6 Dec 2024 13:33:24 +0700 Subject: [PATCH] removable storage array for contract address --- Scarb.lock | 7 ++ crates/storage/Scarb.toml | 19 ++++ crates/storage/src/lib.cairo | 1 + crates/storage/src/storage_array.cairo | 150 +++++++++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 crates/storage/Scarb.toml create mode 100644 crates/storage/src/lib.cairo create mode 100644 crates/storage/src/storage_array.cairo diff --git a/Scarb.lock b/Scarb.lock index ee7292a..bc61a2a 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -105,6 +105,13 @@ dependencies = [ "snforge_scarb_plugin", ] +[[package]] +name = "storage" +version = "0.1.0" +dependencies = [ + "snforge_std", +] + [[package]] name = "token" version = "0.1.0" diff --git a/crates/storage/Scarb.toml b/crates/storage/Scarb.toml new file mode 100644 index 0000000..a46f308 --- /dev/null +++ b/crates/storage/Scarb.toml @@ -0,0 +1,19 @@ +[package] +name = "storage" +version = "0.1.0" +edition = "2024_07" + +[dependencies] +starknet.workspace = true + +[dev-dependencies] +snforge_std.workspace = true + +[[target.starknet-contract]] +sierra = true + +[tool] +fmt.workspace = true + +[lib] +name= "storage" \ No newline at end of file diff --git a/crates/storage/src/lib.cairo b/crates/storage/src/lib.cairo new file mode 100644 index 0000000..a0940d7 --- /dev/null +++ b/crates/storage/src/lib.cairo @@ -0,0 +1 @@ +pub mod storage_array; diff --git a/crates/storage/src/storage_array.cairo b/crates/storage/src/storage_array.cairo new file mode 100644 index 0000000..94dda24 --- /dev/null +++ b/crates/storage/src/storage_array.cairo @@ -0,0 +1,150 @@ +use core::num::traits::Zero; +use starknet::ContractAddress; +use starknet::storage::{ + Map, Mutable, StoragePath, StoragePathEntry, StoragePointerReadAccess, + StoragePointerWriteAccess, +}; + +pub trait StorageArrayTrait { + type ElementType; + fn get(self: T, index: u64) -> Option>; + fn at(self: T, index: u64) -> StoragePath; + fn len(self: T) -> u64; +} + +pub trait MutableStorageArrayTrait { + type ElementType; + fn get(self: T, index: u64) -> Option>>; + fn at(self: T, index: u64) -> StoragePath>; + fn len(self: T) -> u64; + fn append(self: T) -> StoragePath>; + fn delete(self: T, index: u64); + fn clear(self: T); +} + +//******************************************************** +// StorageArray for ContractAddress +//******************************************************** +#[starknet::storage_node] +pub struct StorageArrayContractAddress { + vec: Map, + len: u64, +} + +pub impl StorageArrayContractAddressImpl of StorageArrayTrait< + StoragePath, +> { + type ElementType = ContractAddress; + fn get( + self: StoragePath, index: u64, + ) -> Option> { + let vec_len = self.len.read(); + if index < vec_len { + return Option::Some(self.vec.entry(index)); + } + Option::None + } + + fn at( + self: StoragePath, index: u64, + ) -> StoragePath { + assert!(index < self.len.read(), "Index out of bounds"); + self.vec.entry(index) + } + + fn len(self: StoragePath) -> u64 { + self.len.read() + } +} + +pub impl MutableStorageArrayContractAddressImpl of MutableStorageArrayTrait< + StoragePath>, +> { + type ElementType = ContractAddress; + fn delete(self: StoragePath>, index: u64) { + let len = self.len.read(); + assert!(index < len, "Index out of bounds"); + let last_element_storage_path = self.vec.entry(len - 1); + if index != len - 1 { + let last_element = last_element_storage_path.read(); + self.vec.entry(index).write(last_element); + } + last_element_storage_path.write(Zero::zero()); + self.len.write(len - 1); + } + + fn append( + self: StoragePath>, + ) -> StoragePath> { + let len = self.len.read(); + self.len.write(len + 1); + self.vec.entry(len) + } + + fn get( + self: StoragePath>, index: u64, + ) -> Option>> { + let vec_len = self.len.read(); + if index < vec_len { + return Option::Some(self.vec.entry(index)); + } + Option::None + } + + fn at( + self: StoragePath>, index: u64, + ) -> StoragePath> { + assert!(index < self.len.read(), "Index out of bounds"); + self.vec.entry(index) + } + + fn len(self: StoragePath>) -> u64 { + self.len.read() + } + + fn clear(self: StoragePath>) { + self.len.write(0); + } +} + +pub impl StorageArrayContractAddressIndexView of core::ops::IndexView< + StoragePath, u64, +> { + type Target = StoragePath; + fn index(self: @StoragePath, index: u64) -> Self::Target { + (*self).at(index) + } +} + +pub impl MutableStorageArrayContractAddressIndexView of core::ops::IndexView< + StoragePath>, u64, +> { + type Target = StoragePath>; + fn index(self: @StoragePath>, index: u64) -> Self::Target { + (*self).at(index) + } +} + +pub impl ContractAddressVecToContractAddressArray of Into< + StoragePath, Array, +> { + fn into(self: StoragePath) -> Array { + let mut array = array![]; + for i in 0..self.len() { + array.append(self[i].read()); + }; + array + } +} + +pub impl MutableContractAddressVecToContractAddressArray of Into< + StoragePath>, Array, +> { + fn into(self: StoragePath>) -> Array { + let mut array = array![]; + for i in 0..self.len() { + array.append(self[i].read()); + }; + array + } +}