diff --git a/Cargo.lock b/Cargo.lock index 2a6ee14..4396ef3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" dependencies = [ "bytes", - "cfg-if 1.0.0", + "cfg-if", "const-hex", "derive_more", "hex-literal", @@ -118,12 +118,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -136,7 +130,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen", ] @@ -146,7 +140,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "hex", "proptest", @@ -343,19 +337,12 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "mini-alloc" version = "0.5.2" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-test", - "wee_alloc", ] [[package]] @@ -582,7 +569,7 @@ version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "convert_case 0.6.0", "lazy_static", "proc-macro2", @@ -599,11 +586,12 @@ version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "derivative", "hex", "keccak-const", "lazy_static", + "mini-alloc", "paste", "regex", "sha3", @@ -695,7 +683,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -720,7 +708,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -790,40 +778,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "zeroize" version = "1.8.1" diff --git a/Cargo.toml b/Cargo.toml index 6beeede..60dda7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,5 +31,6 @@ syn-solidity = "0.7.6" convert_case = "0.6.0" # members +mini-alloc = { path = "mini-alloc" } stylus-sdk = { path = "stylus-sdk" } stylus-proc = { path = "stylus-proc", version = "0.5.2" } diff --git a/README.md b/README.md index 48da5d8..38d1698 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ sol_storage! { } } -#[external] +#[public] impl Counter { // Gets the number value from storage. pub fn number(&self) -> Result> { @@ -98,7 +98,7 @@ The Stylus SDK is just one of the building blocks in creating and deploying WebA ## License -© 2022-2023 Offchain Labs, Inc. +© 2022-2024 Offchain Labs, Inc. This project is licensed under either of diff --git a/examples/erc20/Cargo.lock b/examples/erc20/Cargo.lock index f48d99c..2b203bf 100644 --- a/examples/erc20/Cargo.lock +++ b/examples/erc20/Cargo.lock @@ -19,7 +19,7 @@ checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", "bytes", - "cfg-if 1.0.0", + "cfg-if", "const-hex", "derive_more", "hex-literal", @@ -327,12 +327,6 @@ version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -345,7 +339,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "hex", "proptest", @@ -604,7 +598,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] @@ -704,7 +698,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "once_cell", @@ -766,18 +760,11 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "mini-alloc" -version = "0.5.0" +version = "0.5.2" dependencies = [ - "cfg-if 1.0.0", - "wee_alloc", + "cfg-if", ] [[package]] @@ -1199,7 +1186,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -1221,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1252,11 +1239,11 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stylus-proc" -version = "0.5.0" +version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "convert_case 0.6.0", "lazy_static", "proc-macro2", @@ -1269,15 +1256,16 @@ dependencies = [ [[package]] name = "stylus-sdk" -version = "0.5.0" +version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "derivative", "hex", "keccak-const", "lazy_static", + "mini-alloc", "regex", "stylus-proc", ] @@ -1334,7 +1322,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "rustix", "windows-sys", @@ -1455,40 +1443,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/examples/erc20/rust-toolchain.toml b/examples/erc20/rust-toolchain.toml new file mode 100644 index 0000000..4d2dee8 --- /dev/null +++ b/examples/erc20/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.80.0" diff --git a/examples/erc20/src/erc20.rs b/examples/erc20/src/erc20.rs index 9f23737..865ed0b 100644 --- a/examples/erc20/src/erc20.rs +++ b/examples/erc20/src/erc20.rs @@ -60,7 +60,7 @@ pub enum Erc20Error { // Note: modifying storage will become much prettier soon impl Erc20 { /// Movement of funds between 2 accounts - /// (invoked by the external transfer() and transfer_from() functions ) + /// (invoked by the public transfer() and transfer_from() functions ) pub fn _transfer(&mut self, from: Address, to: Address, value: U256) -> Result<(), Erc20Error> { // Decreasing sender balance let mut sender_balance = self.balances.setter(from); @@ -132,9 +132,9 @@ impl Erc20 { } } -// These methods are external to other contracts +// These methods are public to other contracts // Note: modifying storage will become much prettier soon -#[external] +#[public] impl Erc20 { /// Immutable token name pub fn name() -> String { diff --git a/examples/erc20/src/lib.rs b/examples/erc20/src/lib.rs index 2f5e41a..2053833 100644 --- a/examples/erc20/src/lib.rs +++ b/examples/erc20/src/lib.rs @@ -5,16 +5,9 @@ extern crate alloc; // Modules and imports mod erc20; +use crate::erc20::{Erc20, Erc20Error, Erc20Params}; use alloy_primitives::{Address, U256}; -use stylus_sdk::{ - msg, - prelude::* -}; -use crate::erc20::{Erc20, Erc20Params, Erc20Error}; - -/// Initializes a custom, global allocator for Rust programs compiled to WASM. -#[global_allocator] -static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT; +use stylus_sdk::{msg, prelude::*}; /// Immutable definitions struct StylusTestTokenParams; @@ -36,7 +29,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc20)] impl StylusTestToken { /// Mints tokens @@ -56,4 +49,5 @@ impl StylusTestToken { self.erc20.burn(msg::sender(), value)?; Ok(()) } -} \ No newline at end of file +} + diff --git a/examples/erc721/Cargo.lock b/examples/erc721/Cargo.lock index d6c0ff3..3d336f9 100644 --- a/examples/erc721/Cargo.lock +++ b/examples/erc721/Cargo.lock @@ -19,7 +19,7 @@ checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", "bytes", - "cfg-if 1.0.0", + "cfg-if", "const-hex", "derive_more", "hex-literal", @@ -327,12 +327,6 @@ version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -345,7 +339,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "hex", "proptest", @@ -604,7 +598,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] @@ -704,7 +698,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "once_cell", @@ -766,18 +760,11 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "mini-alloc" -version = "0.5.0" +version = "0.5.2" dependencies = [ - "cfg-if 1.0.0", - "wee_alloc", + "cfg-if", ] [[package]] @@ -1199,7 +1186,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -1221,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1252,11 +1239,11 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stylus-proc" -version = "0.5.0" +version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "convert_case 0.6.0", "lazy_static", "proc-macro2", @@ -1269,15 +1256,16 @@ dependencies = [ [[package]] name = "stylus-sdk" -version = "0.5.0" +version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "derivative", "hex", "keccak-const", "lazy_static", + "mini-alloc", "regex", "stylus-proc", ] @@ -1334,7 +1322,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "rustix", "windows-sys", @@ -1455,40 +1443,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/examples/erc721/rust-toolchain.toml b/examples/erc721/rust-toolchain.toml new file mode 100644 index 0000000..4d2dee8 --- /dev/null +++ b/examples/erc721/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.80.0" diff --git a/examples/erc721/src/erc721.rs b/examples/erc721/src/erc721.rs index db93c43..6406aa0 100644 --- a/examples/erc721/src/erc721.rs +++ b/examples/erc721/src/erc721.rs @@ -82,7 +82,7 @@ sol_interface! { /// Selector for `onERC721Received`, which is returned by contracts implementing `IERC721TokenReceiver`. const ERC721_TOKEN_RECEIVER_ID: u32 = 0x150b7a02; -// These methods aren't external, but are helpers used by external methods. +// These methods aren't public, but are helpers used by public methods. // Methods marked as "pub" here are usable outside of the erc721 module (i.e. they're callable from lib.rs). impl Erc721 { /// Requires that msg::sender() is authorized to spend a given token @@ -221,8 +221,8 @@ impl Erc721 { } } -// these methods are external to other contracts -#[external] +// these methods are public to other contracts +#[public] impl Erc721 { /// Immutable NFT name. pub fn name() -> Result { diff --git a/examples/erc721/src/lib.rs b/examples/erc721/src/lib.rs index 33db176..2ab26a3 100644 --- a/examples/erc721/src/lib.rs +++ b/examples/erc721/src/lib.rs @@ -5,16 +5,10 @@ extern crate alloc; // Modules and imports mod erc721; -use alloy_primitives::{U256, Address}; +use crate::erc721::{Erc721, Erc721Error, Erc721Params}; +use alloy_primitives::{Address, U256}; /// Import the Stylus SDK along with alloy primitive types for use in our program. -use stylus_sdk::{ - msg, prelude::* -}; -use crate::erc721::{Erc721, Erc721Params, Erc721Error}; - -/// Initializes a custom, global allocator for Rust programs compiled to WASM. -#[global_allocator] -static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT; +use stylus_sdk::{msg, prelude::*}; /// Immutable definitions struct StylusTestNFTParams; @@ -38,7 +32,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc721)] impl StylusTestNFT { /// Mints an NFT @@ -65,4 +59,5 @@ impl StylusTestNFT { pub fn total_supply(&mut self) -> Result { Ok(self.erc721.total_supply.get()) } -} \ No newline at end of file +} + diff --git a/examples/single_call/Cargo.lock b/examples/single_call/Cargo.lock index d764899..3868100 100644 --- a/examples/single_call/Cargo.lock +++ b/examples/single_call/Cargo.lock @@ -19,7 +19,7 @@ checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", "bytes", - "cfg-if 1.0.0", + "cfg-if", "const-hex", "derive_more", "hex-literal", @@ -327,12 +327,6 @@ version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -345,7 +339,7 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d59688ad0945eaf6b84cb44fedbe93484c81b48970e98f09db8a22832d7961" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "hex", "proptest", @@ -594,7 +588,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] @@ -694,7 +688,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "once_cell", @@ -756,18 +750,11 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "mini-alloc" -version = "0.5.0" +version = "0.5.2" dependencies = [ - "cfg-if 1.0.0", - "wee_alloc", + "cfg-if", ] [[package]] @@ -1189,7 +1176,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -1211,7 +1198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1242,11 +1229,11 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stylus-proc" -version = "0.5.0" +version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "convert_case 0.6.0", "lazy_static", "proc-macro2", @@ -1259,15 +1246,16 @@ dependencies = [ [[package]] name = "stylus-sdk" -version = "0.5.0" +version = "0.5.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if 1.0.0", + "cfg-if", "derivative", "hex", "keccak-const", "lazy_static", + "mini-alloc", "regex", "stylus-proc", ] @@ -1335,7 +1323,7 @@ version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "rustix", "windows-sys", @@ -1456,40 +1444,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/examples/single_call/rust-toolchain.toml b/examples/single_call/rust-toolchain.toml new file mode 100644 index 0000000..4d2dee8 --- /dev/null +++ b/examples/single_call/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.80.0" diff --git a/examples/single_call/src/lib.rs b/examples/single_call/src/lib.rs index a056ffa..dabbbca 100644 --- a/examples/single_call/src/lib.rs +++ b/examples/single_call/src/lib.rs @@ -1,16 +1,13 @@ #![cfg_attr(not(feature = "export-abi"), no_main)] extern crate alloc; -#[global_allocator] -static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT; - use stylus_sdk::{abi::Bytes, alloy_primitives::Address, call::RawCall, prelude::*}; -#[solidity_storage] +#[storage] #[entrypoint] pub struct SingleCall; -#[external] +#[public] impl SingleCall { pub fn execute(&self, target: Address, data: Bytes) -> Bytes { let result = RawCall::new().call(target, data.to_vec().as_slice()); diff --git a/licenses/Apache-2.0 b/licenses/Apache-2.0 index e620afe..7c6b15e 100644 --- a/licenses/Apache-2.0 +++ b/licenses/Apache-2.0 @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2022-2023 Offchain Labs, Inc. + Copyright 2022-2024 Offchain Labs, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/licenses/COPYRIGHT.md b/licenses/COPYRIGHT.md index b3767a6..5655789 100644 --- a/licenses/COPYRIGHT.md +++ b/licenses/COPYRIGHT.md @@ -1,6 +1,6 @@ # Licensing Information -Copyright 2022-2023 Offchain Labs, Inc. +Copyright 2022-2024 Offchain Labs, Inc. Copyright assignment and [DCO sign-off](DCO.txt) is required to contribute to this project. diff --git a/licenses/MIT b/licenses/MIT index 6348f16..00903bf 100644 --- a/licenses/MIT +++ b/licenses/MIT @@ -1,6 +1,6 @@ MIT License -Copyright 2022-2023 Offchain Labs, Inc. +Copyright 2022-2024 Offchain Labs, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/mini-alloc/Cargo.toml b/mini-alloc/Cargo.toml index 9d25951..66b77f9 100644 --- a/mini-alloc/Cargo.toml +++ b/mini-alloc/Cargo.toml @@ -15,6 +15,3 @@ wasm-bindgen-test = "0.3.0" [dependencies] cfg-if = "1.0.0" - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -wee_alloc = "0.4.5" diff --git a/mini-alloc/README.md b/mini-alloc/README.md index 59e84dd..dcf62d1 100644 --- a/mini-alloc/README.md +++ b/mini-alloc/README.md @@ -27,11 +27,9 @@ In the above tests we disable memory expansion costs, which unfairly penelize `W Also, `core::arch::wasm32::memory_grow` must never be called by any code outside this crate. -On targets other than wasm32, `MiniAlloc` simply forwards to the allocator from another crate, `wee_alloc::WeeAlloc`. - ## License -© 2023 Offchain Labs, Inc. +© 2023-2024 Offchain Labs, Inc. This project is licensed under either of diff --git a/mini-alloc/src/imp.rs b/mini-alloc/src/imp.rs index a68eb8d..7d0c866 100644 --- a/mini-alloc/src/imp.rs +++ b/mini-alloc/src/imp.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use core::{ alloc::{GlobalAlloc, Layout}, diff --git a/mini-alloc/src/lib.rs b/mini-alloc/src/lib.rs index 69b1aa9..de19928 100644 --- a/mini-alloc/src/lib.rs +++ b/mini-alloc/src/lib.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md #![no_std] @@ -9,7 +9,5 @@ cfg_if! { if #[cfg(target_arch = "wasm32")] { mod imp; pub use imp::MiniAlloc; - } else { - pub use wee_alloc::WeeAlloc as MiniAlloc; } } diff --git a/mini-alloc/tests/misc.rs b/mini-alloc/tests/misc.rs index fe17956..aa9582c 100644 --- a/mini-alloc/tests/misc.rs +++ b/mini-alloc/tests/misc.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md #![no_std] @@ -134,6 +134,4 @@ fn edge_cases() { assert!(offset < size_bytes()); } } - - // TODO: test allocating all 4GB } diff --git a/stylus-proc/src/calls/mod.rs b/stylus-proc/src/calls/mod.rs index 735ff00..77a03f6 100644 --- a/stylus-proc/src/calls/mod.rs +++ b/stylus-proc/src/calls/mod.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::types::solidity_type_info; use convert_case::{Case, Casing}; @@ -24,21 +24,25 @@ pub fn sol_interface(input: TokenStream) -> TokenStream { let sol_type_value = quote!(stylus_sdk::alloy_sol_types::private::SolTypeValue); let mut output = quote!(); - let mut method_impls = quote!(); for item in input.items { + let mut method_impls = quote!(); + let Item::Contract(contract) = item else { error!(item.span(), "not an interface") }; if !contract.is_interface() { error!(contract.kind.span(), "not an interface"); } + if let Some(inherits) = contract.inheritance { + error!(inherits.span(), "inheritance is not currently supported"); + } let name = &contract.name; for item in contract.body { let Item::Function(func) = item else { - continue; // ignore non-functions + error!(item.span(), "unsupported interface item"); }; // uncomment when Alloy exposes this enum // if let FunctionKind::Function(_) = func.kind { @@ -50,23 +54,39 @@ pub fn sol_interface(input: TokenStream) -> TokenStream { // determine the purity let mut purity = None; + let mut external = false; for attr in &func.attributes.0 { - if let FunctionAttribute::Mutability(mutability) = attr { - if purity.is_some() { - error!(attr.span(), "more than one purity attribute specified"); - } - purity = Some(match mutability { - Mutability::Constant(_) | Mutability::Pure(_) => Pure, - Mutability::View(_) => View, - Mutability::Payable(_) => Payable, - }); - } - if let FunctionAttribute::Visibility(vis) = attr { - if let Visibility::Internal(_) | Visibility::Private(_) = vis { - error!(vis.span(), "internal method in interface"); + match attr { + FunctionAttribute::Mutability(mutability) => { + if purity.is_some() { + error!(attr.span(), "more than one purity attribute specified"); + } + purity = Some(match mutability { + Mutability::Pure(_) => Pure, + Mutability::View(_) => View, + Mutability::Payable(_) => Payable, + Mutability::Constant(_) => { + error!( + mutability.span(), + "constant mutability no longer supported" + ); + } + }); } + FunctionAttribute::Visibility(vis) => match vis { + Visibility::External(_) => { + external = true; + } + _ => { + error!(vis.span(), "visibility must be `external`"); + } + }, + _ => error!(attr.span(), "unsupported function attribute"), } } + if !external { + error!(func.span(), "visibility must be explicty set to `external`"); + } let purity = purity.unwrap_or(Write); // determine which context and kind of call to use diff --git a/stylus-proc/src/lib.rs b/stylus-proc/src/lib.rs index 837c07c..15dfaeb 100644 --- a/stylus-proc/src/lib.rs +++ b/stylus-proc/src/lib.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Procedural macros for [The Stylus SDK][sdk]. //! @@ -39,37 +39,44 @@ mod types; /// Allows a Rust `struct` to be used in persistent storage. /// /// ```ignore -/// #[solidity_storage] +/// #[storage] /// pub struct Contract { /// owner: StorageAddress, /// active: StorageBool, /// sub_struct: SubStruct, ///} /// -///#[solidity_storage] +///#[storage] ///pub struct SubStruct { /// // types implementing the `StorageType` trait. ///} /// ``` /// /// Each field must implement [`StorageType`]. This includes other structs, which will -/// implement the `trait` automatically when [`#[solidity_storage]`][solidity_storage] is applied. +/// implement the `trait` automatically when [`#[storage]`][storage] is applied. /// /// One may even implement [`StorageType`] to define custom storage entries, though this is rarely necessary /// since the [Stylus SDK][sdk] intends to include all standard Solidity types out-of-the-box. /// /// Please refer to the [SDK Feature Overview][overview] for more information on defining storage. /// -/// [solidity_storage]: macro@solidity_storage +/// [storage]: macro@storage /// [`StorageType`]: https://docs.rs/stylus-sdk/latest/stylus_sdk/storage/trait.StorageType.html /// [overview]: https://docs.arbitrum.io/stylus/reference/rust-sdk-guide#storage /// [sdk]: https://docs.rs/stylus-sdk/latest/stylus_sdk/index.html #[proc_macro_attribute] +pub fn storage(attr: TokenStream, input: TokenStream) -> TokenStream { + storage::storage(attr, input) +} + +#[doc(hidden)] +#[deprecated = "please use `#[storage]` instead"] +#[proc_macro_attribute] pub fn solidity_storage(attr: TokenStream, input: TokenStream) -> TokenStream { - storage::solidity_storage(attr, input) + storage::storage(attr, input) } -/// The types in [`#[solidity_storage]`][solidity_storage] are laid out in the EVM state trie exactly +/// The types in [`#[storage]`][storage] are laid out in the EVM state trie exactly /// as they are in [Solidity][solidity]. This means that the fields of a `struct` definition will map /// to the same storage slots as they would in EVM programming languages. Hence, it is often nice to /// define types using Solidity syntax, which makes this guarantee easier to see. @@ -96,17 +103,24 @@ pub fn solidity_storage(attr: TokenStream, input: TokenStream) -> TokenStream { /// Because the layout is identical to [Solidity's][solidity], existing Solidity smart contracts can /// upgrade to Rust without fear of storage slots not lining up. You simply copy-paste your type definitions. /// +/// Note that one exception to this storage layout guarantee is contracts which utilize +/// inheritance. The current solution in Stylus using `#[borrow]` and `#[inherits(...)]` packs +/// nested (inherited) structs into their own slots. This is consistent with regular struct nesting +/// in solidity, but not inherited structs. We plan to revisit this behavior in an upcoming +/// release. +/// /// Consequently, the order of fields will affect the JSON ABIs produced that explorers and tooling might use. /// Most developers don't need to worry about this though and can freely order their types when working on a /// Rust contract from scratch. /// +/// /// Please refer to the [SDK Feature Overview][overview] for more information on defining storage. /// -/// [solidity_storage]: macro@solidity_storage +/// [storage]: macro@storage /// [`StorageType`]: https://docs.rs/stylus-sdk/latest/stylus_sdk/storage/trait.StorageType.html /// [solidity]: https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html /// [overview]: https://docs.arbitrum.io/stylus/reference/rust-sdk-guide#erase-and-deriveerase -/// [erc20]: https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/examples/erc20/src/main.rs +/// [erc20]: https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/examples/erc20/src/main.rs #[proc_macro] pub fn sol_storage(input: TokenStream) -> TokenStream { storage::sol_storage(input) @@ -133,6 +147,9 @@ pub fn sol_storage(input: TokenStream) -> TokenStream { /// /// For example, `IService` will have a `make_payment` method that accepts an [`Address`] and returns a [`B256`]. /// +/// Currently only functions are supported, and any other items in the interface will cause an +/// error. +/// /// ```ignore /// pub fn do_call(account: IService, user: Address) -> Result { /// let config = Call::new() @@ -159,14 +176,14 @@ pub fn sol_storage(input: TokenStream) -> TokenStream { /// ```ignore /// sol_interface! { /// interface IMethods { -/// function pureFoo() pure; -/// function viewFoo() view; -/// function writeFoo(); -/// function payableFoo() payable; +/// function pureFoo() external pure; +/// function viewFoo() external view; +/// function writeFoo() external; +/// function payableFoo() external payable; /// } /// } /// -/// #[external] +/// #[public] /// impl Contract { /// pub fn call_pure(&self, methods: IMethods) -> Result<(), Vec> { /// Ok(methods.pure_foo(self)?) // `pure` methods might lie about not being `view` @@ -212,12 +229,12 @@ pub fn sol_storage(input: TokenStream) -> TokenStream { /// } /// ``` /// -/// Note that in the context of an [`#[external]`][external] call, the `&mut impl` argument will correctly +/// Note that in the context of an [`#[public]`][public] call, the `&mut impl` argument will correctly /// distinguish the method as being `write` or `payable`. This means you can write library code that will /// work regardless of whether the `reentrant` feature flag is enabled. /// /// [sol_interface]: macro@sol_interface -/// [external]: macro@external +/// [public]: macro@public /// [`TopLevelStorage`]: https://docs.rs/stylus-sdk/latest/stylus_sdk/storage/trait.TopLevelStorage.html /// [`StorageCache`]: https://docs.rs/stylus-sdk/latest/stylus_sdk/storage/struct.StorageCache.html /// [`flush`]: https://docs.rs/stylus-sdk/latest/stylus_sdk/storage/struct.StorageCache.html#method.flush @@ -283,7 +300,7 @@ pub fn derive_erase(input: TokenStream) -> TokenStream { /// InsufficientAllowance(InsufficientAllowance), /// } /// -/// #[external] +/// #[public] /// impl Contract { /// pub fn fallible_method() -> Result<(), Erc20Error> { /// // code that might revert @@ -316,8 +333,8 @@ pub fn derive_solidity_error(input: TokenStream) -> TokenStream { /// } /// ``` /// -/// The above will make the external methods of Contract the first to consider during invocation. -/// See [`#[external]`][external] for more information on method selection. +/// The above will make the public methods of Contract the first to consider during invocation. +/// See [`#[public]`][public] for more information on method selection. /// /// # Bytes-in, bytes-out programming /// @@ -362,7 +379,7 @@ pub fn derive_solidity_error(input: TokenStream) -> TokenStream { /// [`sol_interface`]: macro@sol_interface /// [entrypoint]: macro@entrypoint /// [reentrant]: https://docs.rs/stylus-sdk/latest/stylus_sdk/msg/fn.reentrant.html -/// [external]: macro@external +/// [public]: macro@public /// [check]: https://github.com/OffchainLabs/cargo-stylus#developing-with-stylus #[proc_macro_attribute] pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { @@ -373,10 +390,10 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// in different programming languages are fully interoperable. You can even automatically export your /// Rust contract as a Solidity interface so that others can add it to their Solidity projects. /// -/// This macro makes methods "external" so that other contracts can call them by implementing the [`Router`] trait. +/// This macro makes methods "public" so that other contracts can call them by implementing the [`Router`] trait. /// /// ```ignore -/// #[external] +/// #[public] /// impl Contract { /// // our owner method is now callable by other contracts /// pub fn owner(&self) -> Result> { @@ -392,16 +409,14 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// } /// ``` /// -/// Note that, currently, all external methods must return a [`Result`] with the error type [`Vec`]. -/// We intend to change this very soon. In the current model, [`Vec`] becomes the program's revert data, -/// which we intend to both make optional and richly typed. +/// In is example, [`Vec`] becomes the program's revert data. /// /// # [`#[payable]`][payable] /// /// As in Solidity, methods may accept ETH as call value. /// /// ```ignore -/// #[external] +/// #[public] /// impl Contract { /// #[payable] /// pub fn credit(&mut self) -> Result<(), Vec { @@ -415,25 +430,23 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// with [`#[payable]`][payable], or else calls to it will revert. This is required as a safety measure /// to prevent users losing funds to methods that didn't intend to accept ether. /// -/// # [`#[pure]`][pure] [`#[view]`][view], and #[write] +/// # [`pure`][pure] [`view`][view], and `write` /// -/// For aesthetics, these additional purity attributes exist to clarify that a method is [`pure`][pure], -/// [`view`][view], or `write`. They aren't necessary though, since the [`#[external]`][external] macro -/// can figure purity out for you based on the types of the arguments. -/// -/// For example, if a method includes an `&self`, it's at least [`view`][view]. If you'd prefer it be write, -/// applying `#[write]` will make it so. Note however that the reverse is not allowed. An `&mut self` -/// method cannot be made [`#[view]`][view], since it might mutate state. +/// For non-payable methods the [`#[public]`][public] macro can figure state mutability out for you based +/// on the types of the arguments. Functions with `&self` will be considered `view`, those with +/// `&mut self` will be considered `write`, and those with neither will be considered `pure`. Please note that +/// `pure` and `view` functions may change the state of other contracts by calling into them, or +/// even this one if the `reentrant` feature is enabled. /// /// Please refer to the [SDK Feature Overview][overview] for more information on defining methods. /// /// # Inheritance, `#[inherit]`, and `#[borrow]` /// /// Composition in Rust follows that of Solidity. Types that implement [`Router`], the trait that -/// [`#[external]`][external] provides, can be connected via inheritance. +/// [`#[public]`][public] provides, can be connected via inheritance. /// /// ```ignore -/// #[external] +/// #[public] /// #[inherit(Erc20)] /// impl Token { /// pub fn mint(&mut self, amount: U256) -> Result<(), Vec> { @@ -441,7 +454,7 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// } /// } /// -/// #[external] +/// #[public] /// impl Erc20 { /// pub fn balance_of() -> Result { /// ... @@ -458,13 +471,17 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// imports a crate implementing a standard, like ERC 20, and then adds or overrides just the methods they /// want to without modifying the imported `Erc20` type. /// +/// Stylus does not currently contain explicit `override` or `virtual` keywords for explicitly +/// marking override functions. It is important, therefore, to carefully ensure that contracts are +/// only overriding the functions. +/// /// Inheritance can also be chained. `#[inherit(Erc20, Erc721)]` will inherit both `Erc20` and `Erc721`, checking /// for methods in that order. `Erc20` and `Erc721` may also inherit other types themselves. Method resolution /// finds the first matching method by [`Depth First Search`][dfs]. /// /// Note that for the above to work, Token must implement [`Borrow`][Borrow] and /// [`BorrowMut`][BorrowMut]. You can implement this yourself, but for simplicity, -/// [`#[solidity_storage]`][solidity_storage] and [`sol_storage!`][sol_storage] provide a +/// [`#[storage]`][storage] and [`sol_storage!`][sol_storage] provide a /// `#[borrow]` annotation. /// /// ```ignore @@ -493,7 +510,7 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// can call it. This is usually done with the cargo stylus [CLI tool][cli]. /// /// The SDK does this automatically via a feature flag called `export-abi` that causes the -/// [`#[external]`][external] and [`#[entrypoint]`][entrypoint] macros to generate a `main` function +/// [`#[public]`][public] and [`#[entrypoint]`][entrypoint] macros to generate a `main` function /// that prints the Solidity ABI to the console. /// /// ```sh @@ -528,10 +545,10 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// } /// ``` /// -/// [solidity_storage]: macro@solidity_storage +/// [storage]: macro@storage /// [sol_storage]: macro@sol_storage /// [entrypoint]: macro@entrypoint -/// [external]: macro@external +/// [public]: macro@public /// [overview]: https://docs.arbitrum.io/stylus/reference/rust-sdk-guide#methods /// [`Router`]: https://docs.rs/stylus-sdk/latest/stylus_sdk/abi/trait.Router.html /// [Borrow]: https://doc.rust-lang.org/std/borrow/trait.Borrow.html @@ -543,8 +560,15 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { /// [cli]: https://github.com/OffchainLabs/cargo-stylus#exporting-solidity-abis /// [dfs]: https://en.wikipedia.org/wiki/Depth-first_search #[proc_macro_attribute] +pub fn public(attr: TokenStream, input: TokenStream) -> TokenStream { + methods::public::public(attr, input) +} + +#[doc(hidden)] +#[deprecated = "please use `#[public]` instead"] +#[proc_macro_attribute] pub fn external(attr: TokenStream, input: TokenStream) -> TokenStream { - methods::external::external(attr, input) + public(attr, input) } /// Implements the AbiType for arbitrary structs, allowing them to be used in external method diff --git a/stylus-proc/src/methods/entrypoint.rs b/stylus-proc/src/methods/entrypoint.rs index e7d8c52..78bb63a 100644 --- a/stylus-proc/src/methods/entrypoint.rs +++ b/stylus-proc/src/methods/entrypoint.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use cfg_if::cfg_if; use proc_macro::TokenStream; @@ -43,6 +43,10 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { }, } } + + const _: () = { + <#name>::__stylus_assert_overrides(); + }; }); if cfg!(feature = "export-abi") { diff --git a/stylus-proc/src/methods/error.rs b/stylus-proc/src/methods/error.rs index 6dedd23..07e2956 100644 --- a/stylus-proc/src/methods/error.rs +++ b/stylus-proc/src/methods/error.rs @@ -1,5 +1,5 @@ // Copyright 2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use proc_macro::TokenStream; use quote::quote; diff --git a/stylus-proc/src/methods/mod.rs b/stylus-proc/src/methods/mod.rs index d3e69d2..a53efc2 100644 --- a/stylus-proc/src/methods/mod.rs +++ b/stylus-proc/src/methods/mod.rs @@ -1,6 +1,6 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md pub mod entrypoint; pub mod error; -pub mod external; +pub mod public; diff --git a/stylus-proc/src/methods/external.rs b/stylus-proc/src/methods/public.rs similarity index 78% rename from stylus-proc/src/methods/external.rs rename to stylus-proc/src/methods/public.rs index e702d24..19517f1 100644 --- a/stylus-proc/src/methods/external.rs +++ b/stylus-proc/src/methods/public.rs @@ -1,61 +1,66 @@ // Copyright 2022-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md -use crate::types::{self, Purity}; +use crate::types::Purity; use convert_case::{Case, Casing}; use proc_macro::TokenStream; -use proc_macro2::Ident; +use proc_macro2::{Ident, Span}; use quote::{quote, quote_spanned}; -use std::{mem, str::FromStr}; +use std::mem; use syn::{ parenthesized, parse::{Parse, ParseStream}, parse_macro_input, punctuated::Punctuated, spanned::Spanned, - FnArg, ImplItem, Index, ItemImpl, Lit, LitStr, Pat, PatType, Result, ReturnType, Token, Type, + FnArg, ImplItem, Index, ItemImpl, LitStr, Pat, PatType, Result, ReturnType, Token, Type, }; -pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { +pub fn public(attr: TokenStream, input: TokenStream) -> TokenStream { + if !attr.is_empty() { + error!(Span::mixed_site(), "this macro is not configurable"); + } + let mut input = parse_macro_input!(input as ItemImpl); let mut selectors = quote!(); let mut match_selectors = quote!(); let mut abi = quote!(); let mut types = vec![]; + let mut override_selectors = quote!(); + let mut selector_consts = vec![]; for item in input.items.iter_mut() { let ImplItem::Method(method) = item else { continue; }; - // see if user chose a purity or selector (TODO: use drain_filter when stable) + // see if user chose a purity or selector let mut purity = None; - let mut override_id = None; let mut override_name = None; for attr in mem::take(&mut method.attrs) { let Some(ident) = attr.path.get_ident() else { + method.attrs.push(attr); continue; }; - if let Ok(elem) = Purity::from_str(&ident.to_string()) { + if *ident == "payable" { if !attr.tokens.is_empty() { error!(attr.tokens, "attribute does not take parameters"); } if purity.is_some() { - error!(attr.path, "more than one purity attribute"); + error!(attr.path, "more than one payable attribute"); } - purity = Some(elem); + purity = Some(Purity::Payable); continue; } if *ident == "selector" { - if override_id.is_some() || override_name.is_some() { + if override_name.is_some() { error!(attr.path, "more than one selector attribute"); } let args = match syn::parse2::(attr.tokens.clone()) { Ok(args) => args, Err(error) => error!(ident, "{}", error), }; - override_id = args.id; - override_name = args.name; + override_name = Some(args.name); continue; } method.attrs.push(attr); @@ -142,15 +147,24 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { let constant = Ident::new(&format!("SELECTOR_{name}"), name.span()); let arg_types: &Vec<_> = &args.iter().map(|a| &a.1).collect(); - let selector = match override_id { - Some(id) => quote! { #id }, - None => quote! { u32::from_be_bytes(function_selector!(#sol_name #(, #arg_types )*)) }, - }; + let selector = + quote! { u32::from_be_bytes(function_selector!(#sol_name #(, #arg_types )*)) }; selectors.extend(quote! { #[allow(non_upper_case_globals)] const #constant: u32 = #selector; }); + let sdk_purity = purity.as_tokens(); + override_selectors.extend(quote! { + #[allow(non_upper_case_globals)] + #constant => #sdk_purity.allow_override(purity), + }); + let error_msg = format!( + "function {} cannot be overriden with function marked {:?}", + name, purity + ); + selector_consts.push((constant.clone(), sdk_purity, error_msg)); + let in_span = method.sig.inputs.span(); let decode_inputs = quote_spanned! { in_span => <(#( #arg_types, )*) as AbiType>::SolType }; @@ -198,15 +212,7 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { x => format!(" {x}"), }; - let mut comment = quote!(); - if let Some(id) = override_id { - comment.extend(quote! { - write!(f, "\n // note: selector was overridden to be 0x{:x}.", #id)?; - }); - } - abi.extend(quote! { - #comment write!(f, "\n function {}(", #sol_name)?; #(#sol_args)* write!(f, ") external")?; @@ -257,7 +263,27 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { .map(|c| c.predicates) .unwrap_or_default(); - // implement Router with inheritence + let check_overrides = selector_consts + .iter() + .map(|(selector, purity, msg)| { + quote! { + assert!(<#self_ty>::__stylus_allow_override(#selector, #purity), "{}", #msg); + } + }) + .chain(inherits.iter().map(|ty| { + quote! { + <#ty>::__stylus_assert_overrides(); + } + })); + let inherit_overrides = inherits.iter().map(|ty| { + quote! { + if !<#ty>::__stylus_allow_override(selector, purity) { + return false; + } + } + }); + + // implement Router with inheritance let mut router = quote! { #input @@ -267,7 +293,6 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { #(#borrow_clauses,)* #where_clauses { - // TODO: this should be configurable type Storage = Self; #[inline(always)] @@ -290,6 +315,33 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { } } } + + // implement checks for method overriding. + impl<#generic_params> #self_ty where #where_clauses { + #[doc(hidden)] + /// Whether or not to allow overriding a selector by a child contract and method with + /// the given purity. This is currently implemented as a hidden function to allow it to + /// be `const`. A trait would be better, but `const` is not currently supported for + /// trait fns. + pub const fn __stylus_allow_override(selector: u32, purity: stylus_sdk::methods::Purity) -> bool { + use stylus_sdk::function_selector; + #selectors + if !match selector { + #override_selectors + _ => true + } { return false; } + #(#inherit_overrides)* + true + } + + #[doc(hidden)] + /// Check the functions defined in an entrypoint for valid overrides. + pub const fn __stylus_assert_overrides() { + use stylus_sdk::function_selector; + #selectors + #(#check_overrides)* + } + } }; // only collect abi info if enabled @@ -308,7 +360,7 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { let type_decls = quote! { let mut seen = HashSet::new(); - for item in [].iter() #(.chain(&<#types as InnerTypes>::inner_types()))* { + for item in ([] as [InnerType; 0]).iter() #(.chain(&<#types as InnerTypes>::inner_types()))* { if seen.insert(item.id) { writeln!(f, "\n {}", item.name)?; } @@ -346,7 +398,7 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { fn fmt_abi(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { use stylus_sdk::abi::{AbiType, GenerateAbi}; use stylus_sdk::abi::internal::write_solidity_returns; - use stylus_sdk::abi::export::{underscore_if_sol, internal::InnerTypes}; + use stylus_sdk::abi::export::{underscore_if_sol, internal::{InnerType, InnerTypes}}; use std::collections::HashSet; #(#inherited_abis)* write!(f, "interface I{}", #name)?; @@ -375,13 +427,11 @@ impl Parse for InheritsAttr { } struct SelectorArgs { - id: Option, - name: Option, + name: String, } impl Parse for SelectorArgs { fn parse(input: ParseStream) -> Result { - let mut id = None; let mut name = None; let content; @@ -397,24 +447,6 @@ impl Parse for SelectorArgs { let _: Token![=] = input.parse()?; match ident.to_string().as_str() { - "id" => { - let lit: Lit = input.parse()?; - if id.is_some() { - error!(@lit, r#"only one "id" is allowed"#); - } - id = Some(match lit { - Lit::Int(lit) => lit.base10_parse()?, - Lit::Str(lit) => { - let name = lit.value(); - if !name.contains('(') { - error!(@lit, "missing parens. Perhaps you meant name = \"{}\"?", name); - } - let hash = types::keccak(name.as_bytes()); - u32::from_be_bytes(hash[..4].try_into().unwrap()) - } - _ => error!(@lit, "expected u32 or string"), - }); - } "name" => { let lit: LitStr = input.parse()?; if name.is_some() { @@ -429,9 +461,10 @@ impl Parse for SelectorArgs { let _: Result = input.parse(); } - if id.is_some() == name.is_some() { - error!(@input.span(), r#"only one of "id" or "name" expected"#); + if let Some(name) = name { + Ok(Self { name }) + } else { + error!(@input.span(), r#""name" is required"#); } - Ok(Self { id, name }) } } diff --git a/stylus-proc/src/storage/mod.rs b/stylus-proc/src/storage/mod.rs index cd6b38a..a8c4e58 100644 --- a/stylus-proc/src/storage/mod.rs +++ b/stylus-proc/src/storage/mod.rs @@ -1,5 +1,5 @@ // Copyright 2023-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::storage::proc::{SolidityField, SolidityFields, SolidityStruct, SolidityStructs}; use proc_macro::TokenStream; @@ -9,7 +9,7 @@ use syn::{parse_macro_input, punctuated::Punctuated, Index, ItemStruct, Token, T mod proc; -pub fn solidity_storage(_attr: TokenStream, input: TokenStream) -> TokenStream { +pub fn storage(_attr: TokenStream, input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as ItemStruct); let name = &input.ident; @@ -25,7 +25,7 @@ pub fn solidity_storage(_attr: TokenStream, input: TokenStream) -> TokenStream { error!(&field, "Type not supported for EVM state storage"); }; - // implement borrows (TODO: use drain_filter when stable) + // implement borrows let attrs = mem::take(&mut field.attrs); for attr in attrs { if !attr.path.is_ident("borrow") { @@ -57,7 +57,6 @@ pub fn solidity_storage(_attr: TokenStream, input: TokenStream) -> TokenStream { let path = &ty.path.segments.last().unwrap().ident; let not_supported = format!("Type `{path}` not supported for EVM state storage"); - // TODO: use short-hand substition from the `storage-macro-shorthand` branch match path.to_string().as_str() { x @ ("u8" | "u16" | "u32" | "u64" | "u128" | "i8" | "i16" | "i32" | "i64" | "i128" | "U8" | "U16" | "U32" | "U64" | "U128" | "I8" | "I16" | "I32" | "I64" @@ -68,8 +67,8 @@ pub fn solidity_storage(_attr: TokenStream, input: TokenStream) -> TokenStream { x.to_uppercase() ); } - "usize" => error!(&field, "{not_supported}."), // TODO: add usize - "isize" => error!(&field, "{not_supported}."), // TODO: add isize + "usize" => error!(&field, "{not_supported}."), + "isize" => error!(&field, "{not_supported}."), "bool" => error!(&field, "{not_supported}. Instead try `StorageBool`."), "f32" | "f64" => error!(&field, "{not_supported}. Consider fixed-point arithmetic."), _ => {} @@ -116,7 +115,6 @@ pub fn solidity_storage(_attr: TokenStream, input: TokenStream) -> TokenStream { }); } - // TODO: add mechanism for struct assignment let expanded = quote! { #input @@ -192,7 +190,7 @@ pub fn sol_storage(input: TokenStream) -> TokenStream { out.extend(quote! { #(#attrs)* - #[stylus_sdk::stylus_proc::solidity_storage] + #[stylus_sdk::stylus_proc::storage] #vis struct #name #generics { #fields } diff --git a/stylus-proc/src/storage/proc.rs b/stylus-proc/src/storage/proc.rs index 43685b7..c983ce2 100644 --- a/stylus-proc/src/storage/proc.rs +++ b/stylus-proc/src/storage/proc.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use lazy_static::lazy_static; use proc_macro2::{Ident, Literal}; @@ -276,7 +276,7 @@ impl TryFrom for PrimitiveKey { let ty = match name.as_str() { "address" => "Address", - "bool" => "U8", // TODO: ask alloy to add a Bool type + "bool" => "U8", "int" => "I256", "uint" => "U256", "bytes" => return Ok(Self(syn::parse_str("Vec")?)), diff --git a/stylus-proc/src/types.rs b/stylus-proc/src/types.rs index 8509888..9e79400 100644 --- a/stylus-proc/src/types.rs +++ b/stylus-proc/src/types.rs @@ -1,8 +1,9 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use alloy_sol_types::SolType; -use sha3::{Digest, Keccak256}; +use proc_macro2::TokenStream; +use quote::quote; use std::{borrow::Cow, fmt::Display, num::NonZeroU16, str::FromStr}; use syn::Token; use syn_solidity::Type; @@ -16,6 +17,18 @@ pub enum Purity { Payable, } +impl Purity { + /// How to reference this purity from inside a contract. + pub fn as_tokens(&self) -> TokenStream { + match self { + Purity::Pure => quote! { stylus_sdk::methods::Purity::Pure }, + Purity::View => quote! { stylus_sdk::methods::Purity::View }, + Purity::Write => quote! { stylus_sdk::methods::Purity::Write }, + Purity::Payable => quote! { stylus_sdk::methods::Purity::Payable }, + } + } +} + impl Default for Purity { fn default() -> Self { Self::Pure @@ -129,9 +142,3 @@ pub fn solidity_type_info(ty: &Type) -> (Cow<'static, str>, Cow<'static, str>) { _ => todo!("Solidity type {ty} is not yet implemented in sol_interface!"), } } - -pub fn keccak>(preimage: T) -> [u8; 32] { - let mut hasher = Keccak256::new(); - hasher.update(preimage); - hasher.finalize().into() -} diff --git a/stylus-sdk/Cargo.toml b/stylus-sdk/Cargo.toml index c642065..5db34a9 100644 --- a/stylus-sdk/Cargo.toml +++ b/stylus-sdk/Cargo.toml @@ -23,6 +23,7 @@ lazy_static.workspace = true regex = { workspace = true, optional = true } # local deps +mini-alloc = { workspace = true, optional = true } stylus-proc.workspace = true [dev-dependencies] @@ -33,9 +34,10 @@ sha3.workspace = true features = ["default", "docs", "debug", "export-abi"] [features] -default = [] +default = ["mini-alloc"] export-abi = ["debug", "regex", "stylus-proc/export-abi", "alloy-primitives/tiny-keccak"] debug = [] docs = [] hostio = [] +mini-alloc = ["dep:mini-alloc"] reentrant = ["stylus-proc/reentrant"] diff --git a/stylus-sdk/src/abi/bytes.rs b/stylus-sdk/src/abi/bytes.rs index d8c3de8..181309e 100644 --- a/stylus-sdk/src/abi/bytes.rs +++ b/stylus-sdk/src/abi/bytes.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::{ abi::{AbiType, ConstString}, diff --git a/stylus-sdk/src/abi/const_string.rs b/stylus-sdk/src/abi/const_string.rs index c9717d7..67e26e8 100644 --- a/stylus-sdk/src/abi/const_string.rs +++ b/stylus-sdk/src/abi/const_string.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Provides [`ConstString`], a mechanism for string operations in `const` contexts. @@ -54,6 +54,7 @@ impl ConstString { let digits = number.checked_ilog10(); let digits = match digits { // TODO: simplify when `const_precise_live_drops` is stabilized + // https://github.com/rust-lang/rust/issues/73255 Some(digits) => digits as usize + 1, None => 1, }; diff --git a/stylus-sdk/src/abi/export/internal.rs b/stylus-sdk/src/abi/export/internal.rs index a182e3f..b49669c 100644 --- a/stylus-sdk/src/abi/export/internal.rs +++ b/stylus-sdk/src/abi/export/internal.rs @@ -1,5 +1,5 @@ // Copyright 2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! This module provides functions for code generated by `stylus-sdk-proc` for the `export-abi` command. //! Most users shouldn't call these. diff --git a/stylus-sdk/src/abi/export/mod.rs b/stylus-sdk/src/abi/export/mod.rs index 8553c1a..f66424b 100644 --- a/stylus-sdk/src/abi/export/mod.rs +++ b/stylus-sdk/src/abi/export/mod.rs @@ -1,5 +1,5 @@ // Copyright 2023-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Traits for exporting Solidity interfaces. //! diff --git a/stylus-sdk/src/abi/impls.rs b/stylus-sdk/src/abi/impls.rs index 0db1414..2ff95ed 100644 --- a/stylus-sdk/src/abi/impls.rs +++ b/stylus-sdk/src/abi/impls.rs @@ -1,5 +1,5 @@ // Copyright 2023-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use super::{AbiType, ConstString}; use alloc::{string::String, vec::Vec}; diff --git a/stylus-sdk/src/abi/internal.rs b/stylus-sdk/src/abi/internal.rs index ade2505..c8d7aae 100644 --- a/stylus-sdk/src/abi/internal.rs +++ b/stylus-sdk/src/abi/internal.rs @@ -1,5 +1,5 @@ // Copyright 2023-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! This module provides functions for code generated by `stylus-sdk-proc`. //! Most users shouldn't call these. diff --git a/stylus-sdk/src/abi/mod.rs b/stylus-sdk/src/abi/mod.rs index b608e2f..f771dcc 100644 --- a/stylus-sdk/src/abi/mod.rs +++ b/stylus-sdk/src/abi/mod.rs @@ -1,5 +1,5 @@ // Copyright 2023-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Solidity ABIs for Rust types. //! @@ -36,7 +36,7 @@ mod ints; pub mod internal; /// Executes a method given a selector and calldata. -/// This trait can be automatically implemented via `#[external]`. +/// This trait can be automatically implemented via `#[public]`. /// Composition with other routers is possible via `#[inherit]`. pub trait Router where diff --git a/stylus-sdk/src/block.rs b/stylus-sdk/src/block.rs index aa37ed9..f0f8236 100644 --- a/stylus-sdk/src/block.rs +++ b/stylus-sdk/src/block.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! VM affordances for inspecting the current block. //! diff --git a/stylus-sdk/src/call/context.rs b/stylus-sdk/src/call/context.rs index e40a7f4..1a98c2e 100644 --- a/stylus-sdk/src/call/context.rs +++ b/stylus-sdk/src/call/context.rs @@ -1,5 +1,5 @@ // Copyright 2022-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::storage::TopLevelStorage; @@ -26,6 +26,8 @@ where /// Recall that [`TopLevelStorage`] is special in that a reference to it represents access to the entire /// contract's state. So that it's sound to [`flush`] or [`clear`] the [`StorageCache`] when calling out /// to other contracts, calls that may induce reentrancy require an `&` or `&mut` to one. + /// Although this reference to [`TopLevelStorage`] is not used, the lifetime is still required + /// to ensure safety of the storage cache. /// /// ```no_run /// use stylus_sdk::call::{Call, Error}; @@ -34,7 +36,7 @@ where /// /// sol_interface! { /// interface IService { - /// function makePayment(address user) payable returns (string); + /// function makePayment(address user) external payable returns (string); /// } /// } /// @@ -162,7 +164,7 @@ cfg_if! { } cfg_if! { - if #[cfg(any(feature = "reentrant", feature = "docs"))] { + if #[cfg(any(not(feature = "reentrant"), feature = "docs"))] { impl Default for Call<(), false> { fn default() -> Self { Self::new() @@ -173,6 +175,9 @@ cfg_if! { /// Begin configuring a call, similar to how [`RawCall`](super::RawCall) and /// [`std::fs::OpenOptions`][OpenOptions] work. /// + /// This is not available if `reentrant` feature is enabled, as it may lead to + /// vulnerability to reentrancy attacks. See [`Call::new_in`]. + /// /// ```ignore /// use stylus_sdk::call::{Call, Error}; /// use stylus_sdk::{prelude::*, evm, msg, alloy_primitives::Address}; @@ -180,7 +185,7 @@ cfg_if! { /// /// sol_interface! { /// interface IService { - /// function makePayment(address user) payable returns (string); + /// function makePayment(address user) external payable returns (string); /// } /// } /// diff --git a/stylus-sdk/src/call/error.rs b/stylus-sdk/src/call/error.rs index ef45431..766fb2c 100644 --- a/stylus-sdk/src/call/error.rs +++ b/stylus-sdk/src/call/error.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use alloc::vec::Vec; use alloy_sol_types::{Panic, PanicKind, SolError}; diff --git a/stylus-sdk/src/call/mod.rs b/stylus-sdk/src/call/mod.rs index b2028c5..f4b16f8 100644 --- a/stylus-sdk/src/call/mod.rs +++ b/stylus-sdk/src/call/mod.rs @@ -1,5 +1,5 @@ // Copyright 2022-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Call other contracts. //! diff --git a/stylus-sdk/src/call/raw.rs b/stylus-sdk/src/call/raw.rs index 4e6c7a0..70a873a 100644 --- a/stylus-sdk/src/call/raw.rs +++ b/stylus-sdk/src/call/raw.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::{ contract::{read_return_data, RETURN_DATA_LEN}, @@ -140,7 +140,7 @@ impl RawCall { /// Note: values are clipped to the amount of ink remaining. /// See [`Ink and Gas`] for more information on Stylus's compute-pricing model. /// - /// [`Ink and Gas`]: https://developer.arbitrum.io/TODO + /// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas pub fn ink(mut self, ink: u64) -> Self { self.gas = Some(tx::ink_to_gas(ink)); self diff --git a/stylus-sdk/src/call/traits.rs b/stylus-sdk/src/call/traits.rs index dd5c98e..64c024c 100644 --- a/stylus-sdk/src/call/traits.rs +++ b/stylus-sdk/src/call/traits.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use alloy_primitives::U256; diff --git a/stylus-sdk/src/call/transfer.rs b/stylus-sdk/src/call/transfer.rs index e42bf4c..616c8f9 100644 --- a/stylus-sdk/src/call/transfer.rs +++ b/stylus-sdk/src/call/transfer.rs @@ -1,5 +1,5 @@ // Copyright 2022-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::call::RawCall; use alloc::vec::Vec; diff --git a/stylus-sdk/src/contract.rs b/stylus-sdk/src/contract.rs index 8f6909c..0a51f7c 100644 --- a/stylus-sdk/src/contract.rs +++ b/stylus-sdk/src/contract.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! VM affordances for inspecting the contract itself. //! diff --git a/stylus-sdk/src/crypto.rs b/stylus-sdk/src/crypto.rs index 7635eb8..2384fd9 100644 --- a/stylus-sdk/src/crypto.rs +++ b/stylus-sdk/src/crypto.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! VM-accelerated cryptography. //! diff --git a/stylus-sdk/src/debug.rs b/stylus-sdk/src/debug.rs index f2e0b50..ecf6899 100644 --- a/stylus-sdk/src/debug.rs +++ b/stylus-sdk/src/debug.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Debug-only items for printing to the console. //! diff --git a/stylus-sdk/src/deploy/mod.rs b/stylus-sdk/src/deploy/mod.rs index 1f29504..0844ae8 100644 --- a/stylus-sdk/src/deploy/mod.rs +++ b/stylus-sdk/src/deploy/mod.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Deploy other contracts. //! diff --git a/stylus-sdk/src/deploy/raw.rs b/stylus-sdk/src/deploy/raw.rs index a92510d..6033fc2 100644 --- a/stylus-sdk/src/deploy/raw.rs +++ b/stylus-sdk/src/deploy/raw.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::{ call::CachePolicy, @@ -17,8 +17,6 @@ use crate::storage::StorageCache; #[must_use] pub struct RawDeploy { salt: Option, - offset: usize, - size: Option, #[allow(unused)] cache_policy: CachePolicy, } @@ -47,20 +45,6 @@ impl RawDeploy { self } - /// Configures what portion of the revert data to copy in case of failure. - /// Does not fail if out of bounds, but rather copies the overlapping portion. - pub fn limit_revert_data(mut self, offset: usize, size: usize) -> Self { - self.offset = offset; - self.size = Some(size); - self - } - - /// Configures the call to avoid copying any revert data. - /// Equivalent to `limit_revert_data(0, 0)`. - pub fn skip_revert_data(self) -> Self { - self.limit_revert_data(0, 0) - } - /// Write all cached values to persistent storage before the init code. #[cfg(feature = "reentrant")] pub fn flush_storage_cache(mut self) -> Self { diff --git a/stylus-sdk/src/evm.rs b/stylus-sdk/src/evm.rs index 2fda916..8aae27b 100644 --- a/stylus-sdk/src/evm.rs +++ b/stylus-sdk/src/evm.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Affordances for the Ethereum Virtual Machine. //! @@ -18,12 +18,12 @@ use alloy_primitives::B256; use alloy_sol_types::{abi::token::WordToken, SolEvent, TopicList}; /// Emits an evm log from combined topics and data. -fn emit_log(bytes: &[u8], topics: usize) { - unsafe { hostio::emit_log(bytes.as_ptr(), bytes.len(), topics) } +fn emit_log(bytes: &[u8], num_topics: usize) { + unsafe { hostio::emit_log(bytes.as_ptr(), bytes.len(), num_topics) } } /// Emits an EVM log from its raw topics and data. -/// Most users should prefer the alloy-typed [`raw_log`]. +/// Most users should prefer the alloy-typed [`log`]. pub fn raw_log(topics: &[B256], data: &[u8]) -> Result<(), &'static str> { if topics.len() > 4 { return Err("too many topics"); @@ -60,7 +60,7 @@ pub fn pay_for_memory_grow(pages: u16) { wrap_hostio!( /// Gets the amount of gas remaining. See [`Ink and Gas`] for more information on Stylus's compute pricing. /// - /// [`Ink and Gas`]: https://developer.arbitrum.io/TODO + /// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas gas_left evm_gas_left u64 ); diff --git a/stylus-sdk/src/hostio.rs b/stylus-sdk/src/hostio.rs index 36ab02c..b627632 100644 --- a/stylus-sdk/src/hostio.rs +++ b/stylus-sdk/src/hostio.rs @@ -1,5 +1,5 @@ // Copyright 2022-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Raw host I/Os for low-level access to the Stylus runtime. //! @@ -72,7 +72,7 @@ vm_hooks! { /// Gets a subset of the code from the account at the given address. The semantics are identical to that /// of the EVM's [`EXT_CODE_COPY`] opcode, aside from one small detail: the write to the buffer `dest` will /// stop after the last byte is written. This is unlike the EVM, which right pads with zeros in this scenario. - /// The return value is the number of bytes written, which allows the caller to detect if this has occured. + /// The return value is the number of bytes written, which allows the caller to detect if this has occurred. /// /// [`EXT_CODE_COPY`]: https://www.evm.codes/#3C pub fn account_code(address: *const u8, offset: usize, size: usize, dest: *mut u8) -> usize; @@ -200,7 +200,7 @@ vm_hooks! { /// `read_return_data` hostio. The semantics are equivalent to that of the EVM's [`CREATE`] /// opcode, which notably includes the exact address returned. /// - /// [`Deploying Stylus Programs`]: https://developer.arbitrum.io/TODO + /// [`Deploying Stylus Programs`]: https://docs.arbitrum.io/stylus/stylus-quickstart /// [`CREATE`]: https://www.evm.codes/#f0 pub fn create1( code: *const u8, @@ -223,7 +223,7 @@ vm_hooks! { /// via the `read_return_data` hostio. The semantics are equivalent to that of the EVM's /// `[CREATE2`] opcode, which notably includes the exact address returned. /// - /// [`Deploying Stylus Programs`]: https://developer.arbitrum.io/TODO + /// [`Deploying Stylus Programs`]: https://docs.arbitrum.io/stylus/stylus-quickstart /// [`CREATE2`]: https://www.evm.codes/#f5 pub fn create2( code: *const u8, @@ -279,7 +279,7 @@ vm_hooks! { /// [`Ink and Gas`] for more information on Stylus's compute pricing. /// /// [`GAS`]: https://www.evm.codes/#5a - /// [`Ink and Gas`]: https://developer.arbitrum.io/TODO + /// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas pub fn evm_ink_left() -> u64; /// The `entrypoint!` macro handles importing this hostio, which is required if the @@ -375,7 +375,7 @@ vm_hooks! { /// Gets the price of ink in evm gas basis points. See [`Ink and Gas`] for more information on /// Stylus's compute-pricing model. /// - /// [`Ink and Gas`]: https://developer.arbitrum.io/TODO + /// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas pub fn tx_ink_price() -> u32; /// Gets the top-level sender of the transaction. The semantics are equivalent to that of the diff --git a/stylus-sdk/src/lib.rs b/stylus-sdk/src/lib.rs index a4a6c02..36ceea3 100644 --- a/stylus-sdk/src/lib.rs +++ b/stylus-sdk/src/lib.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! The Stylus SDK. //! @@ -28,6 +28,13 @@ // Only allow the standard library in tests and for exports #![cfg_attr(not(any(test, feature = "export-abi")), no_std)] +/// Use an efficient WASM allocator. +/// +/// If a different custom allocator is desired, disable the `mini-alloc` feature. +#[cfg(all(target_arch = "wasm32", feature = "mini-alloc"))] +#[global_allocator] +static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT; + extern crate alloc; pub use alloy_primitives; @@ -48,6 +55,7 @@ pub mod contract; pub mod crypto; pub mod deploy; pub mod evm; +pub mod methods; pub mod msg; pub mod prelude; pub mod storage; diff --git a/stylus-sdk/src/methods.rs b/stylus-sdk/src/methods.rs new file mode 100644 index 0000000..0e9586f --- /dev/null +++ b/stylus-sdk/src/methods.rs @@ -0,0 +1,64 @@ +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md + +//! Types relating to method definitions. + +/// State mutability of a contract fuction. This is currently used for checking whether contracts +/// are allowed to override a function from another contract they inherit from. +/// Users should not need this type outside of proc macros. +#[derive(Debug, Clone, Copy)] +pub enum Purity { + /// No state read/write. + Pure, + /// No state write. + View, + /// Cannot receive Ether. + Write, + /// Everything is allowed. + Payable, +} + +impl Purity { + /// Returns whether a function defined with this purity may be overridden + /// by one with the given purity. + pub const fn allow_override(&self, other: Purity) -> bool { + use Purity::*; + matches!( + (*self, other), + (Payable, Payable) + | (Write, Write) + | (Write, View) + | (Write, Pure) + | (View, View) + | (View, Pure) + | (Pure, Pure) + ) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_allow_override() { + use super::Purity::*; + assert!(Payable.allow_override(Payable)); + assert!(!Payable.allow_override(Write)); + assert!(!Payable.allow_override(View)); + assert!(!Payable.allow_override(Pure)); + + assert!(!Write.allow_override(Payable)); + assert!(Write.allow_override(Write)); + assert!(Write.allow_override(View)); + assert!(Write.allow_override(Pure)); + + assert!(!View.allow_override(Payable)); + assert!(!View.allow_override(Write)); + assert!(View.allow_override(View)); + assert!(View.allow_override(Pure)); + + assert!(!Pure.allow_override(Payable)); + assert!(!Pure.allow_override(Write)); + assert!(!Pure.allow_override(View)); + assert!(Pure.allow_override(Pure)); + } +} diff --git a/stylus-sdk/src/msg.rs b/stylus-sdk/src/msg.rs index c3b6343..062ff02 100644 --- a/stylus-sdk/src/msg.rs +++ b/stylus-sdk/src/msg.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! VM affordances for inspecting the current call. //! diff --git a/stylus-sdk/src/prelude.rs b/stylus-sdk/src/prelude.rs index df07ece..411da89 100644 --- a/stylus-sdk/src/prelude.rs +++ b/stylus-sdk/src/prelude.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Common imports for Stylus contracts. //! diff --git a/stylus-sdk/src/storage/array.rs b/stylus-sdk/src/storage/array.rs index 697ec49..0c71b01 100644 --- a/stylus-sdk/src/storage/array.rs +++ b/stylus-sdk/src/storage/array.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use super::{Erase, StorageGuard, StorageGuardMut, StorageType}; use alloy_primitives::U256; @@ -35,6 +35,14 @@ impl StorageType for StorageArray { } impl StorageArray { + /// Gets the number of elements stored. + /// + /// Although this type will always have the same length, this method is still provided for + /// consistency with [`StorageVec`]. + pub const fn len(&self) -> usize { + N + } + /// 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`. diff --git a/stylus-sdk/src/storage/bytes.rs b/stylus-sdk/src/storage/bytes.rs index 55f14b5..acea361 100644 --- a/stylus-sdk/src/storage/bytes.rs +++ b/stylus-sdk/src/storage/bytes.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use super::{Erase, GlobalStorage, Storage, StorageB8, StorageGuard, StorageGuardMut, StorageType}; use crate::crypto; @@ -199,7 +199,6 @@ impl StorageBytes { let len = self.len(); let mut bytes = Vec::with_capacity(len); - // TODO: efficient extraction for i in 0..len { let byte = unsafe { self.get_unchecked(i) }; bytes.push(byte); @@ -243,7 +242,6 @@ impl Erase for StorageBytes { } } -// TODO: efficient bulk insertion impl Extend for StorageBytes { fn extend>(&mut self, iter: T) { for elem in iter { @@ -252,7 +250,6 @@ impl Extend for StorageBytes { } } -// TODO: efficient bulk insertion impl<'a> Extend<&'a u8> for StorageBytes { fn extend>(&mut self, iter: T) { for elem in iter { diff --git a/stylus-sdk/src/storage/map.rs b/stylus-sdk/src/storage/map.rs index 660ae6b..6bef24e 100644 --- a/stylus-sdk/src/storage/map.rs +++ b/stylus-sdk/src/storage/map.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use crate::crypto; diff --git a/stylus-sdk/src/storage/mod.rs b/stylus-sdk/src/storage/mod.rs index d79a16a..1aae2ca 100644 --- a/stylus-sdk/src/storage/mod.rs +++ b/stylus-sdk/src/storage/mod.rs @@ -1,5 +1,5 @@ // Copyright 2023-2024, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Solidity compatible storage types and persistent storage access. //! @@ -112,7 +112,6 @@ macro_rules! alias_bytes { } alias_ints! { - StorageU1, StorageI1, 1, 1; StorageU8, StorageI8, 8, 1; StorageU16, StorageI16, 16, 1; StorageU32, StorageI32, 32, 1; @@ -140,6 +139,7 @@ alias_bytes! { /// /// Note: in the future `L` won't be needed. // TODO: drop L after SupportedInt provides LIMBS (waiting for clarity reasons) +// https://github.com/rust-lang/rust/issues/76560 #[derive(Debug)] pub struct StorageUint { slot: U256, @@ -215,6 +215,7 @@ impl From> for Uint { /// /// Note: in the future `L` won't be needed. // TODO: drop L after SupportedInt provides LIMBS (waiting for clarity reasons) +// https://github.com/rust-lang/rust/issues/76560 #[derive(Debug)] pub struct StorageSigned { slot: U256, @@ -510,6 +511,9 @@ impl From for Address { } /// Accessor for a storage-backed [`BlockNumber`]. +/// +/// This storage type allows convenient and type-safe storage of a +/// [`BlockNumber`]. #[derive(Debug)] pub struct StorageBlockNumber { slot: U256, @@ -523,7 +527,7 @@ impl StorageBlockNumber { **self } - /// Gets the underlying [`BlockNumber`] in persistent storage. + /// Sets the underlying [`BlockNumber`] in persistent storage. pub fn set(&mut self, value: BlockNumber) { overwrite_cell(&mut self.cached, value); let value = FixedBytes::from(value.to_be_bytes()); @@ -584,6 +588,9 @@ impl From for BlockNumber { } /// Accessor for a storage-backed [`BlockHash`]. +/// +/// This storage type allows convenient and type-safe storage of a +/// [`BlockHash`]. #[derive(Clone, Debug)] pub struct StorageBlockHash { slot: U256, diff --git a/stylus-sdk/src/storage/traits.rs b/stylus-sdk/src/storage/traits.rs index 19f3a4e..3080b2f 100644 --- a/stylus-sdk/src/storage/traits.rs +++ b/stylus-sdk/src/storage/traits.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use alloy_primitives::{FixedBytes, Signed, Uint, B256, U256}; use core::{ @@ -175,8 +175,7 @@ impl<'a, T: 'a> DerefMut for StorageGuardMut<'a, T> { } /// Trait for managing access to persistent storage. -/// Notable implementations include the [`StorageCache`](super::StorageCache) -/// and [`EagerStorage`](super::EagerStorage) types. +/// Implemented by the [`StorageCache`](super::StorageCache) type. 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 8c97dc6..f59896f 100644 --- a/stylus-sdk/src/storage/vec.rs +++ b/stylus-sdk/src/storage/vec.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md use super::{ Erase, GlobalStorage, SimpleStorageType, Storage, StorageGuard, StorageGuardMut, StorageType, diff --git a/stylus-sdk/src/tx.rs b/stylus-sdk/src/tx.rs index 9e27d62..13fa59a 100644 --- a/stylus-sdk/src/tx.rs +++ b/stylus-sdk/src/tx.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! VM affordances for inspecting the current tx. //! @@ -19,14 +19,14 @@ wrap_hostio! { /// Gets the price of ink in evm gas basis points. See [`Ink and Gas`] for more information on /// Stylus's compute-pricing model. /// - /// [`Ink and Gas`]: https://developer.arbitrum.io/TODO + /// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas ink_price INK_PRICE tx_ink_price u32 } /// Converts evm gas to ink. See [`Ink and Gas`] for more information on /// Stylus's compute-pricing model. /// -/// [`Ink and Gas`]: https://developer.arbitrum.io/TODO +/// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas pub fn gas_to_ink(gas: u64) -> u64 { gas.saturating_mul(ink_price().into()) } @@ -34,7 +34,7 @@ pub fn gas_to_ink(gas: u64) -> u64 { /// Converts ink to evm gas. See [`Ink and Gas`] for more information on /// Stylus's compute-pricing model. /// -/// [`Ink and Gas`]: https://developer.arbitrum.io/TODO +/// [`Ink and Gas`]: https://docs.arbitrum.io/stylus/concepts/stylus-gas pub fn ink_to_gas(ink: u64) -> u64 { ink / ink_price() as u64 } diff --git a/stylus-sdk/src/types.rs b/stylus-sdk/src/types.rs index 1847430..aa67c26 100644 --- a/stylus-sdk/src/types.rs +++ b/stylus-sdk/src/types.rs @@ -1,5 +1,5 @@ -// Copyright 2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2023-2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md //! Traits for common types. //! diff --git a/stylus-sdk/src/util.rs b/stylus-sdk/src/util.rs index e64414a..28d68b4 100644 --- a/stylus-sdk/src/util.rs +++ b/stylus-sdk/src/util.rs @@ -1,5 +1,5 @@ -// Copyright 2022-2023, Offchain Labs, Inc. -// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md +// Copyright 2022-2024, Offchain Labs, Inc. +// For licensing, seeghttps://github.com/OffchainLabs/stylus-sdk-rs/blob/main/licenses/COPYRIGHT.md /// Returns the minimum number of EVM words needed to store `bytes` bytes. pub(crate) const fn evm_words(bytes: usize) -> usize {