diff --git a/stylus-sdk/src/storage/mod.rs b/stylus-sdk/src/storage/mod.rs index 27fd2df2..1aa3b1ad 100644 --- a/stylus-sdk/src/storage/mod.rs +++ b/stylus-sdk/src/storage/mod.rs @@ -26,6 +26,7 @@ use alloy_sol_types::sol_data::{ByteCount, IntBitCount, SupportedFixedBytes, Sup use cfg_if::cfg_if; use core::marker::PhantomData; use stylus_core::*; +use traits::StorageUtils; pub use array::StorageArray; pub use bytes::{StorageBytes, StorageString}; @@ -199,17 +200,19 @@ macro_rules! gen_int_checked_ops { }; } -impl StorageUint +impl StorageUtils for StorageUint where IntBitCount: SupportedInt, { + type Value = Uint; + /// Gets the underlying [`alloy_primitives::Uint`] in persistent storage. - pub fn get(&self) -> Uint { + fn get(&self) -> Uint { unsafe { Storage::get_uint(self.__stylus_host.clone(), self.slot, self.offset.into()) } } /// Sets the underlying [`alloy_primitives::Uint`] in persistent storage. - pub fn set(&mut self, value: Uint) { + fn set(&mut self, value: Uint) { unsafe { Storage::set_uint( self.__stylus_host.clone(), @@ -219,7 +222,12 @@ where ) }; } +} +impl StorageUint +where + IntBitCount: SupportedInt, +{ gen_int_wrap_ops! { /// Add to the underlying value, wrapping around if overflow. /// Returns the new value. @@ -368,17 +376,19 @@ where } } -impl StorageSigned +impl StorageUtils for StorageSigned where IntBitCount: SupportedInt, { + type Value = Signed; + /// Gets the underlying [`Signed`] in persistent storage. - pub fn get(&self) -> Signed { + fn get(&self) -> Signed { unsafe { Storage::get_signed(self.__stylus_host.clone(), self.slot, self.offset.into()) } } /// Gets the underlying [`Signed`] in persistent storage. - pub fn set(&mut self, value: Signed) { + fn set(&mut self, value: Signed) { unsafe { Storage::set_signed( self.__stylus_host.clone(), @@ -463,14 +473,16 @@ impl HostAccess for StorageFixedBytes { } } -impl StorageFixedBytes { +impl StorageUtils for StorageFixedBytes { + type Value = FixedBytes; + /// Gets the underlying [`FixedBytes`] in persistent storage. - pub fn get(&self) -> FixedBytes { + fn get(&self) -> FixedBytes { unsafe { Storage::get(self.__stylus_host.clone(), self.slot, self.offset.into()) } } /// Gets the underlying [`FixedBytes`] in persistent storage. - pub fn set(&mut self, value: FixedBytes) { + fn set(&mut self, value: FixedBytes) { unsafe { Storage::set( self.__stylus_host.clone(), @@ -589,16 +601,18 @@ where } } -impl StorageBool { +impl StorageUtils for StorageBool { + type Value = bool; + /// Gets the underlying [`bool`] in persistent storage. - pub fn get(&self) -> bool { + fn get(&self) -> bool { let data = unsafe { Storage::get_byte(self.__stylus_host.clone(), self.slot, self.offset.into()) }; data != 0 } /// Gets the underlying [`bool`] in persistent storage. - pub fn set(&mut self, value: bool) { + fn set(&mut self, value: bool) { unsafe { Storage::set_byte( self.__stylus_host.clone(), @@ -689,16 +703,18 @@ where } } -impl StorageAddress { +impl StorageUtils for StorageAddress { + type Value = Address; + /// Gets the underlying [`Address`] in persistent storage. - pub fn get(&self) -> Address { + fn get(&self) -> Address { unsafe { Storage::get::<20>(self.__stylus_host.clone(), self.slot, self.offset.into()).into() } } /// Gets the underlying [`Address`] in persistent storage. - pub fn set(&mut self, value: Address) { + fn set(&mut self, value: Address) { unsafe { Storage::set::<20>( self.__stylus_host.clone(), @@ -792,16 +808,18 @@ where } } -impl StorageBlockNumber { +impl StorageUtils for StorageBlockNumber { + type Value = BlockNumber; + /// Gets the underlying [`BlockNumber`] in persistent storage. - pub fn get(&self) -> BlockNumber { + fn get(&self) -> BlockNumber { let data = unsafe { Storage::get::<8>(self.__stylus_host.clone(), self.slot, self.offset.into()) }; u64::from_be_bytes(data.0) } /// Sets the underlying [`BlockNumber`] in persistent storage. - pub fn set(&mut self, value: BlockNumber) { + fn set(&mut self, value: BlockNumber) { let value = FixedBytes::from(value.to_be_bytes()); unsafe { Storage::set::<8>( @@ -895,14 +913,16 @@ where } } -impl StorageBlockHash { +impl StorageUtils for StorageBlockHash { + type Value = BlockHash; + /// Gets the underlying [`BlockHash`] in persistent storage. - pub fn get(&self) -> BlockHash { + fn get(&self) -> BlockHash { Storage::get_word(self.__stylus_host.clone(), self.slot) } /// Sets the underlying [`BlockHash`] in persistent storage. - pub fn set(&mut self, value: BlockHash) { + fn set(&mut self, value: BlockHash) { unsafe { Storage::set_word(self.__stylus_host.clone(), self.slot, value) } } } @@ -945,6 +965,22 @@ impl From for BlockHash { } } +/// StorageUtils implementation for PhantomData +/// PhantomData doesn't actually store anything, so these are no-ops +impl StorageUtils for PhantomData { + type Value = (); // PhantomData doesn't store any actual value + + /// PhantomData doesn't store anything, so get returns unit + fn get(&self) -> Self::Value { + () + } + + /// PhantomData doesn't store anything, so set is a no-op + fn set(&mut self, _value: Self::Value) { + // No-op: PhantomData doesn't actually store data + } +} + /// We implement `StorageType` for `PhantomData` so that storage types can be generic. impl StorageType for PhantomData { type Wraps<'a> diff --git a/stylus-sdk/src/storage/traits.rs b/stylus-sdk/src/storage/traits.rs index 7edf4fbb..fcb97dee 100644 --- a/stylus-sdk/src/storage/traits.rs +++ b/stylus-sdk/src/storage/traits.rs @@ -11,6 +11,18 @@ use derivative::Derivative; use crate::host::VM; +/// Utils trait for Storage types. +pub trait StorageUtils { + /// The type stored in persistent storage. + type Value; + + /// Gets the underlying value in persistent storage. + fn get(&self) -> Self::Value; + + /// Sets the underlying value in persistent storage. + fn set(&mut self, value: Self::Value); +} + /// Accessor trait that lets a type be used in persistent storage. /// Users can implement this trait to add novel data structures to their contract definitions. /// The Stylus SDK by default provides only solidity types, which are represented [`the same way`].