From 2cf6e724d3f3fc4b56a9fa05e26ad70432b386cf Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 6 Sep 2023 18:21:57 -0600 Subject: [PATCH 1/3] improve docs --- stylus-sdk/Cargo.toml | 1 + stylus-sdk/src/abi/export.rs | 4 ++- stylus-sdk/src/call/traits.rs | 6 ++-- stylus-sdk/src/contract.rs | 4 +-- stylus-sdk/src/evm.rs | 2 +- stylus-sdk/src/storage/cache.rs | 6 ++-- stylus-sdk/src/storage/eager.rs | 2 ++ stylus-sdk/src/storage/mod.rs | 48 ++++++++++++++++---------------- stylus-sdk/src/storage/traits.rs | 14 ++++++---- stylus-sdk/src/storage/vec.rs | 6 +++- 10 files changed, 54 insertions(+), 39 deletions(-) diff --git a/stylus-sdk/Cargo.toml b/stylus-sdk/Cargo.toml index 6a0923e3..5590a699 100644 --- a/stylus-sdk/Cargo.toml +++ b/stylus-sdk/Cargo.toml @@ -36,3 +36,4 @@ default = ["storage-cache"] export-abi = ["debug", "regex", "stylus-proc/export-abi"] debug = [] storage-cache = ["fnv"] +docs = [] diff --git a/stylus-sdk/src/abi/export.rs b/stylus-sdk/src/abi/export.rs index 4a19427f..6d78f6a8 100644 --- a/stylus-sdk/src/abi/export.rs +++ b/stylus-sdk/src/abi/export.rs @@ -7,11 +7,13 @@ use regex::Regex; /// Trait for storage types so that users can print a Solidity interface to the console. /// This is auto-derived via the [`external`] marco when the `export-abi` feature is enabled. +/// +/// [`external`]: stylus-proc::external pub trait GenerateAbi { /// The interface's name. const NAME: &'static str; - /// How to format the ABI. Analogous to [`Display`]. + /// How to format the ABI. Analogous to [`Display`](std::fmt::Display). fn fmt_abi(f: &mut fmt::Formatter<'_>) -> fmt::Result; } diff --git a/stylus-sdk/src/call/traits.rs b/stylus-sdk/src/call/traits.rs index d8d6b653..a91c510e 100644 --- a/stylus-sdk/src/call/traits.rs +++ b/stylus-sdk/src/call/traits.rs @@ -20,7 +20,9 @@ pub trait StaticCallContext: CallContext {} /// /// # Safety /// -/// The type must contain a [`TopLevelStorage`] to prevent aliasing in cases of reentrancy. +/// The type must contain a [`TopLevelStorage`][TLS] to prevent aliasing in cases of reentrancy. +/// +/// [TLS]: crate::storage::TopLevelStorage pub unsafe trait MutatingCallContext: CallContext { /// Amount of ETH in wei to give the other contract. fn value(&self) -> U256; @@ -28,7 +30,7 @@ pub unsafe trait MutatingCallContext: CallContext { /// Trait for calling the `write` methods of other contracts. /// Users should rarely implement this trait outside of proc macros. -/// Note: any implementations of this must return zero for [`MutableCallContext::value`]. +/// Note: any implementations of this must return zero for [`MutatingCallContext::value`]. pub trait NonPayableCallContext: MutatingCallContext {} impl CallContext for () { diff --git a/stylus-sdk/src/contract.rs b/stylus-sdk/src/contract.rs index 70080373..e1a92bce 100644 --- a/stylus-sdk/src/contract.rs +++ b/stylus-sdk/src/contract.rs @@ -8,7 +8,7 @@ use crate::{ use alloy_primitives::{Address, U256}; /// Reads the invocation's calldata. -/// The [`derive(Entrypoint)`] and [`entrypoint`] macros use this under the hood. +/// The [`entrypoint`](macro@stylus_proc::entrypoint) macro uses this under the hood. pub fn args(len: usize) -> Vec { let mut input = Vec::with_capacity(len); unsafe { @@ -19,7 +19,7 @@ pub fn args(len: usize) -> Vec { } /// Writes the contract's return data. -/// The [`derive(Entrypoint)`] and [`entrypoint!`] macros use this under the hood. +/// The [`entrypoint`](macro@stylus_proc::entrypoint) macro uses this under the hood. pub fn output(data: &[u8]) { unsafe { hostio::write_result(data.as_ptr(), data.len()); diff --git a/stylus-sdk/src/evm.rs b/stylus-sdk/src/evm.rs index ca0254c7..b02139a6 100644 --- a/stylus-sdk/src/evm.rs +++ b/stylus-sdk/src/evm.rs @@ -11,7 +11,7 @@ fn emit_log(bytes: &[u8], topics: usize) { } /// Emits an EVM log from its raw topics and data. -/// Most users should prefer the alloy-typed [`emit_log`]. +/// Most users should prefer the alloy-typed [`raw_log`]. pub fn raw_log(topics: &[B256], data: &[u8]) -> Result<(), &'static str> { if topics.len() > 4 { return Err("too many topics"); diff --git a/stylus-sdk/src/storage/cache.rs b/stylus-sdk/src/storage/cache.rs index 63ea2efa..17770369 100644 --- a/stylus-sdk/src/storage/cache.rs +++ b/stylus-sdk/src/storage/cache.rs @@ -11,8 +11,10 @@ use lazy_static::lazy_static; /// /// This is intended for most use cases. However, one may opt-out /// of this behavior by turning off default features and not enabling -/// the `storage-cache` feature. Doing so will provide the [`EagerStorage`] type -/// for managing state in the absence of caching. +/// the `storage-cache` feature. Doing so will provide the [`EagerStorage`] +/// type for managing state in the absence of caching. +/// +/// [`EagerStorage`]: super::EagerStorage pub struct StorageCache(HashMap); /// Represents the EVM word at a given key. diff --git a/stylus-sdk/src/storage/eager.rs b/stylus-sdk/src/storage/eager.rs index 72364e38..9e8d335e 100644 --- a/stylus-sdk/src/storage/eager.rs +++ b/stylus-sdk/src/storage/eager.rs @@ -10,6 +10,8 @@ use alloy_primitives::{B256, U256}; /// `storage-cache` feature flag, which will provide the [`StorageCache`] type. /// /// Note that individual primitive types may still include efficient caching. +/// +/// [`StorageCache`]: super::StorageCache pub struct EagerStorage; impl GlobalStorage for EagerStorage { diff --git a/stylus-sdk/src/storage/mod.rs b/stylus-sdk/src/storage/mod.rs index cbec9be0..11b1ec86 100644 --- a/stylus-sdk/src/storage/mod.rs +++ b/stylus-sdk/src/storage/mod.rs @@ -8,7 +8,7 @@ use core::{cell::OnceCell, marker::PhantomData, ops::Deref}; pub use array::StorageArray; pub use bytes::{StorageBytes, StorageString}; -pub use map::StorageMap; +pub use map::{StorageMap, StorageKey}; pub use traits::{ Erase, GlobalStorage, SimpleStorageType, StorageGuard, StorageGuardMut, StorageType, TopLevelStorage, @@ -18,7 +18,7 @@ pub use vec::StorageVec; #[cfg(feature = "storage-cache")] pub use cache::StorageCache; -#[cfg(not(feature = "storage-cache"))] +#[cfg(any(not(feature = "storage-cache"), feature = "docs"))] pub use eager::EagerStorage; mod array; @@ -30,7 +30,7 @@ mod vec; #[cfg(feature = "storage-cache")] mod cache; -#[cfg(not(feature = "storage-cache"))] +#[cfg(any(not(feature = "storage-cache"), feature = "docs"))] mod eager; #[cfg(feature = "storage-cache")] @@ -69,26 +69,25 @@ fn overwrite_cell(cell: &mut OnceCell, value: T) { macro_rules! alias_ints { ($($name:ident, $signed_name:ident, $bits:expr, $limbs:expr;)*) => { $( - #[doc = concat!("Accessor for a storage-backed [`U", stringify!($bits), "`].")] + #[doc = concat!("Accessor for a storage-backed [`alloy_primitives::aliases::U", stringify!($bits), "`].")] pub type $name = StorageUint<$bits, $limbs>; - #[doc = concat!("Accessor for a storage-backed [`I", stringify!($bits), "`].")] + #[doc = concat!("Accessor for a storage-backed [`alloy_primitives::aliases::I", stringify!($bits), "`].")] pub type $signed_name = StorageSigned<$bits, $limbs>; )* }; } macro_rules! alias_bytes { - ($($name:ident, $bytes:expr;)*) => { + ($($name:ident, $bits:expr, $bytes:expr;)*) => { $( - #[doc = concat!("Accessor for a storage-backed [`B", stringify!($bytes), "`].")] + #[doc = concat!("Accessor for a storage-backed [`alloy_primitives::aliases::B", stringify!($bits), "`].")] pub type $name = StorageFixedBytes<$bytes>; )* }; } alias_ints! { - StorageU0, StorageI0, 0, 0; StorageU1, StorageI1, 1, 1; StorageU8, StorageI8, 8, 1; StorageU16, StorageI16, 16, 1; @@ -101,20 +100,20 @@ alias_ints! { } alias_bytes! { - StorageB0, 0; - StorageB8, 1; - StorageB16, 2; - StorageB32, 4; - StorageB64, 8; - StorageB96, 12; - StorageB128, 16; - StorageB160, 20; - StorageB192, 24; - StorageB224, 28; - StorageB256, 32; -} - -/// Accessor for a storage-backed [`Uint`]. + StorageB8, 8, 1; + StorageB16, 16, 2; + StorageB32, 32, 4; + StorageB64, 64, 8; + StorageB96, 96, 12; + StorageB128, 128, 16; + StorageB160, 160, 20; + StorageB192, 192, 24; + StorageB224, 224, 28; + StorageB256, 256, 32; +} + +/// Accessor for a storage-backed [`alloy_primitives::Uint`]. +/// /// Note: in the future `L` won't be needed. // TODO: drop L after SupportedInt provides LIMBS (waiting for clarity reasons) #[derive(Debug)] @@ -125,12 +124,12 @@ pub struct StorageUint { } impl StorageUint { - /// Gets the underlying [`Uint`] in persistent storage. + /// Gets the underlying [`alloy_primitives::Uint`] in persistent storage. pub fn get(&self) -> Uint { **self } - /// Sets the underlying [`Uint`] in persistent storage. + /// Sets the underlying [`alloy_primitives::Uint`] in persistent storage. pub fn set(&mut self, value: Uint) { overwrite_cell(&mut self.cached, value); unsafe { Storage::set_uint(self.slot, self.offset.into(), value) }; @@ -189,6 +188,7 @@ impl From> for Uint { } /// Accessor for a storage-backed [`Signed`]. +/// /// Note: in the future `L` won't be needed. // TODO: drop L after SupportedInt provides LIMBS (waiting for clarity reasons) #[derive(Debug)] diff --git a/stylus-sdk/src/storage/traits.rs b/stylus-sdk/src/storage/traits.rs index 53936c74..27c8c4e0 100644 --- a/stylus-sdk/src/storage/traits.rs +++ b/stylus-sdk/src/storage/traits.rs @@ -13,7 +13,7 @@ use derivative::Derivative; /// 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`]. /// -/// [`the same way`]: https://docs.soliditylang.org/en/v0.8.15/internals/layout_in_storage.html +/// [`the same way`]: https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html pub trait StorageType: Sized { /// For primative types, this is the type being stored. /// For collections, this is the [`StorageType`] being collected. @@ -31,10 +31,11 @@ pub trait StorageType: Sized { /// set this to 32 and return the full size in [`StorageType::new`]. /// /// For implementing collections, see how Solidity slots are assigned for [`Arrays and Maps`] and their - /// Stylus equivalents [`StorageVec`] and [`StorageMap`]. - /// For multi-word, but still-fixed-size types, see the implementations for structs and [`StorageArray`]. + /// Stylus equivalents [`StorageVec`](super::StorageVec) and [`StorageMap`](super::StorageMap). + /// For multi-word, but still fixed-size types, see the implementations for structs + /// and [`StorageArray`](super::StorageArray). /// - /// [`Arrays and Maps`]: https://docs.soliditylang.org/en/v0.8.15/internals/layout_in_storage.html#mappings-and-dynamic-arrays + /// [`Arrays and Maps`]: https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays const SLOT_BYTES: usize = 32; /// The number of words this type must fill. For primitives this is always 0. @@ -66,7 +67,7 @@ pub trait StorageType: Sized { } /// Trait for accessors that can be used to completely erase their underlying value. -/// Note that some collections, like [`StorageMap`], don't implement this trait. +/// Note that some collections, like [`StorageMap`](super::StorageMap), don't implement this trait. pub trait Erase: StorageType { /// Erase the value from persistent storage. fn erase(&mut self); @@ -174,7 +175,8 @@ impl<'a, T: 'a> DerefMut for StorageGuardMut<'a, T> { } /// Trait for managing access to persistent storage. -/// Notable implementations include the [`StorageCache`] and [`EagerStorage`] types. +/// Notable implementations include the [`StorageCache`](super::StorageCache) +/// and [`EagerStorage`](super::EagerStorage) types. pub trait GlobalStorage { /// Retrieves `N ≤ 32` bytes from persistent storage, performing [`SLOAD`]'s only as needed. /// The bytes are read from slot `key`, starting `offset` bytes from the left. diff --git a/stylus-sdk/src/storage/vec.rs b/stylus-sdk/src/storage/vec.rs index a5846443..4ae0c7f5 100644 --- a/stylus-sdk/src/storage/vec.rs +++ b/stylus-sdk/src/storage/vec.rs @@ -61,6 +61,7 @@ impl StorageVec { } /// Gets an accessor to the element at a given index, if it exists. + /// /// Note: the accessor is protected by a [`StorageGuard`], which restricts /// its lifetime to that of `&self`. pub fn getter(&self, index: impl TryInto) -> Option> { @@ -69,6 +70,7 @@ impl StorageVec { } /// Gets a mutable accessor to the element at a given index, if it exists. + /// /// Note: the accessor is protected by a [`StorageGuardMut`], which restricts /// its lifetime to that of `&mut self`. pub fn setter(&mut self, index: impl TryInto) -> Option> { @@ -112,7 +114,7 @@ impl StorageVec { Some(store.load_mut()) } - /// Like [`std::Vec::push`], but returns a mutable accessor to the new slot. + /// Like [`std::vec::Vec::push`], but returns a mutable accessor to the new slot. /// This enables pushing elements without constructing them first. /// /// # Example @@ -151,6 +153,7 @@ impl StorageVec { } /// Shortens the vector, keeping the first `len` elements. + /// /// Note: this method does not erase any underlying storage. pub fn truncate(&mut self, len: usize) { if len < self.len() { @@ -190,6 +193,7 @@ impl<'a, S: SimpleStorageType<'a>> StorageVec { } /// Removes and returns the last element of the vector, if it exists. + /// /// Note: the underlying storage slot is erased when all elements in a word are freed. pub fn pop(&mut self) -> Option> { let store = unsafe { self.shrink()?.into_raw() }; From 5e849604c27018e7fc495341f9c8e59fdd91feb0 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 6 Sep 2023 18:22:47 -0600 Subject: [PATCH 2/3] bump version number --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f57e0f3..241b1eaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -434,7 +434,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.2.1" +version = "0.2.2" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -450,7 +450,7 @@ dependencies = [ [[package]] name = "stylus-sdk" -version = "0.2.1" +version = "0.2.2" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index a393615c..2790b0dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["stylus-sdk", "stylus-proc"] resolver = "2" [workspace.package] -version = "0.2.1" +version = "0.2.2" edition = "2021" authors = ["Offchain Labs"] license = "MIT OR Apache-2.0" From 42102bd22a132ebb772b8420351266a17ce004f6 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 6 Sep 2023 18:29:01 -0600 Subject: [PATCH 3/3] cargo fmt --- stylus-sdk/src/storage/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylus-sdk/src/storage/mod.rs b/stylus-sdk/src/storage/mod.rs index 11b1ec86..2b4894f4 100644 --- a/stylus-sdk/src/storage/mod.rs +++ b/stylus-sdk/src/storage/mod.rs @@ -8,7 +8,7 @@ use core::{cell::OnceCell, marker::PhantomData, ops::Deref}; pub use array::StorageArray; pub use bytes::{StorageBytes, StorageString}; -pub use map::{StorageMap, StorageKey}; +pub use map::{StorageKey, StorageMap}; pub use traits::{ Erase, GlobalStorage, SimpleStorageType, StorageGuard, StorageGuardMut, StorageType, TopLevelStorage,