From 02972c2a52c38dd6d85a9ac8f0bab2e14fd5b299 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 29 Nov 2023 14:53:22 -0700 Subject: [PATCH 01/14] Rename `memory_grow` to `pay_for_memory_grow` --- stylus-proc/src/methods/entrypoint.rs | 2 +- stylus-sdk/src/evm.rs | 4 ++-- stylus-sdk/src/hostio.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stylus-proc/src/methods/entrypoint.rs b/stylus-proc/src/methods/entrypoint.rs index 411acf8..98f3904 100644 --- a/stylus-proc/src/methods/entrypoint.rs +++ b/stylus-proc/src/methods/entrypoint.rs @@ -84,7 +84,7 @@ pub fn entrypoint(attr: TokenStream, input: TokenStream) -> TokenStream { output.extend(quote! { #[no_mangle] pub unsafe fn mark_used() { - stylus_sdk::evm::memory_grow(0); + stylus_sdk::evm::pay_for_memory_grow(0); panic!(); } diff --git a/stylus-sdk/src/evm.rs b/stylus-sdk/src/evm.rs index 5914e49..9ade581 100644 --- a/stylus-sdk/src/evm.rs +++ b/stylus-sdk/src/evm.rs @@ -53,8 +53,8 @@ pub fn log(event: T) { /// This function exists to force the compiler to import this symbol. /// Calling it will unproductively consume gas. -pub fn memory_grow(pages: u16) { - unsafe { hostio::memory_grow(pages) } +pub fn pay_for_memory_grow(pages: u16) { + unsafe { hostio::pay_for_memory_grow(pages) } } wrap_hostio!( diff --git a/stylus-sdk/src/hostio.rs b/stylus-sdk/src/hostio.rs index 0e78148..7d2d861 100644 --- a/stylus-sdk/src/hostio.rs +++ b/stylus-sdk/src/hostio.rs @@ -221,7 +221,7 @@ extern "C" { /// Internally the Stylus VM forces calls to this hostio whenever new WASM pages are allocated. /// Calls made voluntarily will unproductively consume gas. #[allow(dead_code)] - pub fn memory_grow(pages: u16); + pub fn pay_for_memory_grow(pages: u16); /// Whether the current call is reentrant. pub fn msg_reentrant() -> bool; From 7bef833ee0e59011e46967981984905b57ca37bd Mon Sep 17 00:00:00 2001 From: Michael Benfield Date: Mon, 22 Jan 2024 13:07:41 -0800 Subject: [PATCH 02/14] code, code_size hostios --- stylus-sdk/src/evm.rs | 18 +++++++++++++++++- stylus-sdk/src/hostio.rs | 8 ++++++++ stylus-sdk/src/types.rs | 15 +++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/stylus-sdk/src/evm.rs b/stylus-sdk/src/evm.rs index 9ade581..ab9d633 100644 --- a/stylus-sdk/src/evm.rs +++ b/stylus-sdk/src/evm.rs @@ -14,7 +14,7 @@ use crate::hostio::{self, wrap_hostio}; use alloc::{vec, vec::Vec}; -use alloy_primitives::B256; +use alloy_primitives::{Address, B256}; use alloy_sol_types::{token::WordToken, SolEvent, TopicList}; /// Emits an evm log from combined topics and data. @@ -57,6 +57,22 @@ pub fn pay_for_memory_grow(pages: u16) { unsafe { hostio::pay_for_memory_grow(pages) } } +/// Get the code associated with the given `address`. +/// +/// Start at `offset` into the code and write at most `size` bytes. +pub fn ext_code(address: &Address, offset: usize, size: Option) -> Vec { + let size = if let Some(sz) = size { + sz + } else { + unsafe { hostio::account_code_size(address.0.as_ptr()) } + }; + let mut data = vec![0; size]; + let size_written = + unsafe { hostio::account_code(address.0.as_ptr(), offset, size, data.as_mut_ptr()) }; + data.truncate(size_written); + data +} + wrap_hostio!( /// Gets the amount of gas remaining. See [`Ink and Gas`] for more information on Stylus's compute pricing. /// diff --git a/stylus-sdk/src/hostio.rs b/stylus-sdk/src/hostio.rs index 7d2d861..9740ef2 100644 --- a/stylus-sdk/src/hostio.rs +++ b/stylus-sdk/src/hostio.rs @@ -28,6 +28,11 @@ extern "C" { /// [`BALANCE`]: https://www.evm.codes/#31 pub fn account_balance(address: *const u8, dest: *mut u8); + /// Write the code associated with the given address into `dest`, starting + /// at `offset`, writing at most `size` bytes. + /// Returns the number of bytes written. + pub fn account_code(address: *const u8, offset: usize, size: usize, dest: *mut u8) -> usize; + /// Gets the code hash of the account at the given address. The semantics are equivalent /// to that of the EVM's [`EXT_CODEHASH`] opcode. Note that the code hash of an account without /// code will be the empty hash @@ -36,6 +41,9 @@ extern "C" { /// [`EXT_CODEHASH`]: https://www.evm.codes/#3F pub fn account_codehash(address: *const u8, dest: *mut u8); + /// Get the size of the code associated with the given address. + pub fn account_code_size(address: *const u8) -> usize; + /// Reads a 32-byte value from permanent storage. Stylus's storage format is identical to /// that of the EVM. This means that, under the hood, this hostio is accessing the 32-byte /// value stored in the EVM state trie at offset `key`, which will be `0` when not previously diff --git a/stylus-sdk/src/types.rs b/stylus-sdk/src/types.rs index eb2594e..52cc629 100644 --- a/stylus-sdk/src/types.rs +++ b/stylus-sdk/src/types.rs @@ -13,6 +13,9 @@ //! let balance = account.balance(); //! ``` +use alloc::vec; +use alloc::vec::Vec; + use crate::hostio; use alloy_primitives::{b256, Address, B256, U256}; @@ -21,6 +24,9 @@ pub trait AddressVM { /// The balance in wei of the account. fn balance(&self) -> U256; + /// The code of the contract at the given address. + fn code(&self) -> Vec; + /// The codehash of the contract or [`EOA`] at the given address. /// /// [`EOA`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account @@ -41,6 +47,15 @@ impl AddressVM for Address { U256::from_be_bytes(data) } + fn code(&self) -> Vec { + let size = unsafe { hostio::account_code_size(self.0.as_ptr()) }; + let mut data = vec![0; size]; + unsafe { + hostio::account_code(self.0.as_ptr(), 0, size, data.as_mut_ptr()); + } + data + } + fn codehash(&self) -> B256 { let mut data = [0; 32]; unsafe { hostio::account_codehash(self.0.as_ptr(), data.as_mut_ptr()) }; From 330ef7cc5aebf16b7ce0b5c5abeef6b85bbb66e2 Mon Sep 17 00:00:00 2001 From: Michael Benfield Date: Thu, 25 Jan 2024 11:34:17 -0800 Subject: [PATCH 03/14] SolidityError derive macro --- examples/erc20/Cargo.lock | 61 ++++++++++++++++++++++++++++++---- examples/erc20/src/erc20.rs | 13 ++------ stylus-proc/src/lib.rs | 6 ++++ stylus-proc/src/storage/mod.rs | 30 ++++++++++++++++- 4 files changed, 91 insertions(+), 19 deletions(-) diff --git a/examples/erc20/Cargo.lock b/examples/erc20/Cargo.lock index 7988a62..8538f33 100644 --- a/examples/erc20/Cargo.lock +++ b/examples/erc20/Cargo.lock @@ -19,7 +19,7 @@ checksum = "e416903084d3392ebd32d94735c395d6709415b76c7728e594d3f996f2b03e65" dependencies = [ "alloy-rlp", "bytes", - "cfg-if", + "cfg-if 1.0.0", "const-hex", "derive_more", "hex-literal", @@ -137,6 +137,12 @@ dependencies = [ "libc", ] +[[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" @@ -149,7 +155,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08849ed393c907c90016652a01465a12d86361cd38ad2a7de026c56a520cc259" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "hex", "serde", @@ -294,7 +300,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -368,11 +374,18 @@ version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" +[[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.4.2" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "wee_alloc", ] [[package]] @@ -623,7 +636,7 @@ version = "0.4.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if", + "cfg-if 1.0.0", "convert_case 0.6.0", "lazy_static", "proc-macro2", @@ -640,7 +653,7 @@ version = "0.4.2" dependencies = [ "alloy-primitives", "alloy-sol-types", - "cfg-if", + "cfg-if 1.0.0", "derivative", "fnv", "hex", @@ -689,7 +702,7 @@ version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "redox_syscall", "rustix", @@ -756,6 +769,40 @@ 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.48.0" diff --git a/examples/erc20/src/erc20.rs b/examples/erc20/src/erc20.rs index e3a8669..12191bc 100644 --- a/examples/erc20/src/erc20.rs +++ b/examples/erc20/src/erc20.rs @@ -1,4 +1,4 @@ -use alloc::{string::String, vec::Vec}; +use alloc::string::String; use core::marker::PhantomData; use stylus_sdk::{ alloy_primitives::{Address, U256}, @@ -36,21 +36,12 @@ sol! { error InsufficientAllowance(address owner, address spender, uint256 have, uint256 want); } +#[derive(SolidityError)] pub enum Erc20Error { InsufficientBalance(InsufficientBalance), InsufficientAllowance(InsufficientAllowance), } -// We will soon provide a #[derive(SolidityError)] to clean this up -impl From for Vec { - fn from(err: Erc20Error) -> Vec { - match err { - Erc20Error::InsufficientBalance(e) => e.encode(), - Erc20Error::InsufficientAllowance(e) => e.encode(), - } - } -} - // These methods aren't exposed to other contracts // Note: modifying storage will become much prettier soon impl Erc20 { diff --git a/stylus-proc/src/lib.rs b/stylus-proc/src/lib.rs index 2b9893b..b975245 100644 --- a/stylus-proc/src/lib.rs +++ b/stylus-proc/src/lib.rs @@ -264,6 +264,12 @@ pub fn derive_erase(input: TokenStream) -> TokenStream { storage::derive_erase(input) } +/// For an error type `E`, implement `From` for `Vec`. +#[proc_macro_derive(SolidityError)] +pub fn derive_solidity_error(input: TokenStream) -> TokenStream { + storage::derive_solidity_error(input) +} + /// Defines the entrypoint, which is where Stylus execution begins. /// Without it the contract will fail to pass [`cargo stylus check`][check]. /// Most commonly this macro is used to annotate the top level storage `struct`. diff --git a/stylus-proc/src/storage/mod.rs b/stylus-proc/src/storage/mod.rs index 3138f1c..8781d06 100644 --- a/stylus-proc/src/storage/mod.rs +++ b/stylus-proc/src/storage/mod.rs @@ -5,7 +5,9 @@ use crate::storage::proc::{SolidityField, SolidityFields, SolidityStruct, Solidi use proc_macro::TokenStream; use quote::{quote, ToTokens}; use std::mem; -use syn::{parse_macro_input, punctuated::Punctuated, Index, ItemStruct, Token, Type}; +use syn::{ + parse_macro_input, punctuated::Punctuated, Fields, Index, ItemEnum, ItemStruct, Token, Type, +}; mod proc; @@ -223,3 +225,29 @@ pub fn derive_erase(input: TokenStream) -> TokenStream { }; output.into() } + +pub fn derive_solidity_error(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as ItemEnum); + let name = &input.ident; + let mut match_arms = quote! {}; + for variant in input.variants.iter() { + let variant_name = &variant.ident; + match variant.fields { + Fields::Unnamed(_) if variant.fields.len() == 1 => {} + _ => panic!("SolidityError: Each variant must be a tuple struct with one field"), + } + match_arms.extend(quote! { + #name::#variant_name(e) => e.encode(), + }) + } + let output = quote! { + impl From<#name> for ::alloc::vec::Vec { + fn from(err: #name) -> ::alloc::vec::Vec { + match err { + #match_arms + } + } + } + }; + output.into() +} From 44ab101f5d448bb60f3864fd756faff519ad45bf Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Mon, 29 Jan 2024 22:44:47 -0700 Subject: [PATCH 04/14] improve docstrings --- stylus-sdk/src/hostio.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/stylus-sdk/src/hostio.rs b/stylus-sdk/src/hostio.rs index 9740ef2..82792bf 100644 --- a/stylus-sdk/src/hostio.rs +++ b/stylus-sdk/src/hostio.rs @@ -28,11 +28,20 @@ extern "C" { /// [`BALANCE`]: https://www.evm.codes/#31 pub fn account_balance(address: *const u8, dest: *mut u8); - /// Write the code associated with the given address into `dest`, starting - /// at `offset`, writing at most `size` bytes. - /// Returns the number of bytes written. + /// 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. + /// + /// [`EXT_CODE_COPY`]: https://www.evm.codes/#3C pub fn account_code(address: *const u8, offset: usize, size: usize, dest: *mut u8) -> usize; + /// Gets the size of the code in bytes at the given address. The semantics are equivalent + /// to that of the EVM's [`EXT_CODESIZE`]. + /// + /// [`EXT_CODESIZE`]: https://www.evm.codes/#3B + pub fn account_code_size(address: *const u8) -> usize; + /// Gets the code hash of the account at the given address. The semantics are equivalent /// to that of the EVM's [`EXT_CODEHASH`] opcode. Note that the code hash of an account without /// code will be the empty hash @@ -41,9 +50,6 @@ extern "C" { /// [`EXT_CODEHASH`]: https://www.evm.codes/#3F pub fn account_codehash(address: *const u8, dest: *mut u8); - /// Get the size of the code associated with the given address. - pub fn account_code_size(address: *const u8) -> usize; - /// Reads a 32-byte value from permanent storage. Stylus's storage format is identical to /// that of the EVM. This means that, under the hood, this hostio is accessing the 32-byte /// value stored in the EVM state trie at offset `key`, which will be `0` when not previously @@ -270,6 +276,8 @@ extern "C" { /// bounds, but rather copies the overlapping portion. The semantics are otherwise equivalent /// to that of the EVM's [`RETURN_DATA_COPY`] opcode. /// + /// Returns the number of bytes written. + /// /// [`RETURN_DATA_COPY`]: https://www.evm.codes/#3e pub fn read_return_data(dest: *mut u8, offset: usize, size: usize) -> usize; From c8951eab9b5bd61b264d192241642bf316aa466e Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Mon, 29 Jan 2024 23:49:07 -0700 Subject: [PATCH 05/14] add code_size, comments, and slight optimization --- stylus-sdk/src/evm.rs | 18 +----------------- stylus-sdk/src/storage/map.rs | 2 +- stylus-sdk/src/types.rs | 32 +++++++++++++++++++++++--------- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/stylus-sdk/src/evm.rs b/stylus-sdk/src/evm.rs index ab9d633..9ade581 100644 --- a/stylus-sdk/src/evm.rs +++ b/stylus-sdk/src/evm.rs @@ -14,7 +14,7 @@ use crate::hostio::{self, wrap_hostio}; use alloc::{vec, vec::Vec}; -use alloy_primitives::{Address, B256}; +use alloy_primitives::B256; use alloy_sol_types::{token::WordToken, SolEvent, TopicList}; /// Emits an evm log from combined topics and data. @@ -57,22 +57,6 @@ pub fn pay_for_memory_grow(pages: u16) { unsafe { hostio::pay_for_memory_grow(pages) } } -/// Get the code associated with the given `address`. -/// -/// Start at `offset` into the code and write at most `size` bytes. -pub fn ext_code(address: &Address, offset: usize, size: Option) -> Vec { - let size = if let Some(sz) = size { - sz - } else { - unsafe { hostio::account_code_size(address.0.as_ptr()) } - }; - let mut data = vec![0; size]; - let size_written = - unsafe { hostio::account_code(address.0.as_ptr(), offset, size, data.as_mut_ptr()) }; - data.truncate(size_written); - data -} - wrap_hostio!( /// Gets the amount of gas remaining. See [`Ink and Gas`] for more information on Stylus's compute pricing. /// diff --git a/stylus-sdk/src/storage/map.rs b/stylus-sdk/src/storage/map.rs index 8b25f0c..660ae6b 100644 --- a/stylus-sdk/src/storage/map.rs +++ b/stylus-sdk/src/storage/map.rs @@ -186,7 +186,7 @@ impl StorageKey for String { impl StorageKey for Address { fn to_slot(&self, root: B256) -> U256 { - let int: U160 = self.0.try_into().unwrap(); + let int: U160 = self.0.into(); int.to_slot(root) } } diff --git a/stylus-sdk/src/types.rs b/stylus-sdk/src/types.rs index 52cc629..a0ab9fb 100644 --- a/stylus-sdk/src/types.rs +++ b/stylus-sdk/src/types.rs @@ -13,10 +13,8 @@ //! let balance = account.balance(); //! ``` -use alloc::vec; -use alloc::vec::Vec; - use crate::hostio; +use alloc::vec::Vec; use alloy_primitives::{b256, Address, B256, U256}; /// Trait that allows the [`Address`] type to inspect the corresponding account's balance and codehash. @@ -24,9 +22,20 @@ pub trait AddressVM { /// The balance in wei of the account. fn balance(&self) -> U256; - /// The code of the contract at the given address. + /// The account's code. + /// + /// Returns an empty [`vec`] for [`EOAs`]. + /// + /// [`EOAs`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account fn code(&self) -> Vec; + /// The length of the account's code in bytes. + /// + /// Returns `0` for [`EOAs`]. + /// + /// [`EOAs`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account + fn code_size(&self) -> usize; + /// The codehash of the contract or [`EOA`] at the given address. /// /// [`EOA`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account @@ -43,22 +52,27 @@ pub trait AddressVM { impl AddressVM for Address { fn balance(&self) -> U256 { let mut data = [0; 32]; - unsafe { hostio::account_balance(self.0.as_ptr(), data.as_mut_ptr()) }; + unsafe { hostio::account_balance(self.as_ptr(), data.as_mut_ptr()) }; U256::from_be_bytes(data) } fn code(&self) -> Vec { - let size = unsafe { hostio::account_code_size(self.0.as_ptr()) }; - let mut data = vec![0; size]; + let size = self.code_size(); + let mut data = Vec::with_capacity(size); unsafe { - hostio::account_code(self.0.as_ptr(), 0, size, data.as_mut_ptr()); + hostio::account_code(self.as_ptr(), 0, size, data.as_mut_ptr()); + data.set_len(size); } data } + fn code_size(&self) -> usize { + unsafe { hostio::account_code_size(self.as_ptr()) } + } + fn codehash(&self) -> B256 { let mut data = [0; 32]; - unsafe { hostio::account_codehash(self.0.as_ptr(), data.as_mut_ptr()) }; + unsafe { hostio::account_codehash(self.as_ptr(), data.as_mut_ptr()) }; data.into() } From db5052f3f9c22007140c7820bdac12af1ee096fe Mon Sep 17 00:00:00 2001 From: Michael Benfield Date: Wed, 7 Feb 2024 12:19:09 -0800 Subject: [PATCH 06/14] External methods that don't return Result --- stylus-proc/src/methods/external.rs | 7 ++----- stylus-sdk/src/abi/internal.rs | 26 +++++++++++++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/stylus-proc/src/methods/external.rs b/stylus-proc/src/methods/external.rs index 848d2b5..bbe8ed4 100644 --- a/stylus-proc/src/methods/external.rs +++ b/stylus-proc/src/methods/external.rs @@ -155,10 +155,7 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { } }; let result = Self::#name(#storage #(#expand_args, )* ); - match result { - Ok(result) => Some(Ok(internal::encode_return_type(result))), - Err(err) => Some(Err(err.into())), - } + Some(EncodableReturnType::encode(result)) } }); @@ -258,7 +255,7 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { #[inline(always)] fn route(storage: &mut S, selector: u32, input: &[u8]) -> Option { use stylus_sdk::{function_selector, alloy_sol_types::SolType}; - use stylus_sdk::abi::{internal, AbiType, Router}; + use stylus_sdk::abi::{internal, internal::EncodableReturnType, AbiType, Router}; use alloc::vec; #[cfg(feature = "export-abi")] diff --git a/stylus-sdk/src/abi/internal.rs b/stylus-sdk/src/abi/internal.rs index 8ea4d53..69863b1 100644 --- a/stylus-sdk/src/abi/internal.rs +++ b/stylus-sdk/src/abi/internal.rs @@ -4,16 +4,32 @@ //! This module provides functions for code generated by `stylus-sdk-proc`. //! Most users shouldn't call these. -use crate::{abi::AbiType, console, msg}; +use crate::{abi::AbiType, console, msg, ArbResult}; use alloc::{vec, vec::Vec}; use alloy_primitives::U256; use alloy_sol_types::SolType; use core::fmt; -#[inline(always)] -pub fn encode_return_type(x: T) -> Vec { - // coerce types into a tuple of at least 1 element - <(T,) as AbiType>::SolType::encode(&(x,)) +pub trait EncodableReturnType { + fn encode(self) -> ArbResult; +} + +impl EncodableReturnType for T { + #[inline(always)] + fn encode(self) -> ArbResult { + // coerce types into a tuple of at least 1 element + Ok(<(T,) as AbiType>::SolType::encode(&(self,))) + } +} + +impl>> EncodableReturnType for Result { + #[inline(always)] + fn encode(self) -> ArbResult { + match self { + Ok(result) => result.encode(), + Err(err) => Err(err.into()), + } + } } #[inline(always)] From 1af18069dfabba0b56171f404c3be45e3c482370 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 14 Feb 2024 20:41:34 -0700 Subject: [PATCH 07/14] export infallible methods --- stylus-proc/src/methods/external.rs | 2 +- stylus-sdk/src/abi/internal.rs | 8 +++++--- stylus-sdk/src/storage/map.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/stylus-proc/src/methods/external.rs b/stylus-proc/src/methods/external.rs index bbe8ed4..77b6cd9 100644 --- a/stylus-proc/src/methods/external.rs +++ b/stylus-proc/src/methods/external.rs @@ -1,4 +1,4 @@ -// Copyright 2022-2023, Offchain Labs, Inc. +// Copyright 2022-2024, Offchain Labs, Inc. // For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md use crate::types::{self, Purity}; diff --git a/stylus-sdk/src/abi/internal.rs b/stylus-sdk/src/abi/internal.rs index 69863b1..1ad9902 100644 --- a/stylus-sdk/src/abi/internal.rs +++ b/stylus-sdk/src/abi/internal.rs @@ -1,4 +1,4 @@ -// Copyright 2023, Offchain Labs, Inc. +// Copyright 2023-2024, Offchain Labs, Inc. // For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md //! This module provides functions for code generated by `stylus-sdk-proc`. @@ -58,12 +58,14 @@ pub fn failed_to_decode_arguments(err: alloy_sol_types::Error) { pub trait AbiResult { type OkType; - type ErrType; } impl AbiResult for Result { type OkType = O; - type ErrType = E; +} + +impl AbiResult for T { + type OkType = T; } pub fn write_solidity_returns(f: &mut fmt::Formatter) -> fmt::Result diff --git a/stylus-sdk/src/storage/map.rs b/stylus-sdk/src/storage/map.rs index 8b25f0c..660ae6b 100644 --- a/stylus-sdk/src/storage/map.rs +++ b/stylus-sdk/src/storage/map.rs @@ -186,7 +186,7 @@ impl StorageKey for String { impl StorageKey for Address { fn to_slot(&self, root: B256) -> U256 { - let int: U160 = self.0.try_into().unwrap(); + let int: U160 = self.0.into(); int.to_slot(root) } } From 7524fb7b62d65c3e31a2e737a8a5565f6144bb99 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 14 Feb 2024 21:13:36 -0700 Subject: [PATCH 08/14] fix contributor links --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 430fd37..10e5347 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,5 +8,5 @@ Please provide a summary of the changes and any backward incompatibilities. - [ ] I have read the [DCO][DCO] and ensured that these changes comply. - [ ] I assign this work under its [open source licensing][terms]. -[DCO]: licenses/DCO.txt -[terms]: licenses/COPYRIGHT.md +[DCO]: https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/DCO.txt +[terms]: https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md From 14647ee061c42b7f957a49e8e2b8e5fd239b07fa Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Tue, 20 Feb 2024 17:48:15 -0700 Subject: [PATCH 09/14] fix panic, add abi-export, & relocate --- stylus-proc/src/lib.rs | 27 +++++- stylus-proc/src/methods/error.rs | 51 ++++++++++++ stylus-proc/src/methods/external.rs | 23 +++++- stylus-proc/src/methods/mod.rs | 1 + stylus-proc/src/storage/mod.rs | 36 +------- stylus-sdk/src/abi/export/internal.rs | 82 +++++++++++++++++++ .../src/abi/{export.rs => export/mod.rs} | 5 +- stylus-sdk/src/abi/internal.rs | 4 +- 8 files changed, 191 insertions(+), 38 deletions(-) create mode 100644 stylus-proc/src/methods/error.rs create mode 100644 stylus-sdk/src/abi/export/internal.rs rename stylus-sdk/src/abi/{export.rs => export/mod.rs} (97%) diff --git a/stylus-proc/src/lib.rs b/stylus-proc/src/lib.rs index b975245..471b097 100644 --- a/stylus-proc/src/lib.rs +++ b/stylus-proc/src/lib.rs @@ -264,10 +264,33 @@ pub fn derive_erase(input: TokenStream) -> TokenStream { storage::derive_erase(input) } -/// For an error type `E`, implement `From` for `Vec`. +/// Allows an error `enum` to be used in method signatures. +/// +/// ```ignore +/// sol! { +/// error InsufficientBalance(address from, uint256 have, uint256 want); +/// error InsufficientAllowance(address owner, address spender, uint256 have, uint256 want); +/// } +/// +/// #[derive(SolidityError)] +/// pub enum Erc20Error { +/// InsufficientBalance(InsufficientBalance), +/// InsufficientAllowance(InsufficientAllowance), +/// } +/// +/// #[external] +/// impl Contract { +/// pub fn fallible_method() -> Result<(), Erc20Error> { +/// // code that might revert +/// } +/// } +/// ``` +/// +/// Under the hood, the above macro works by implementing `From` for `Vec` +/// along with printing code for abi-export. #[proc_macro_derive(SolidityError)] pub fn derive_solidity_error(input: TokenStream) -> TokenStream { - storage::derive_solidity_error(input) + methods::error::derive_solidity_error(input) } /// Defines the entrypoint, which is where Stylus execution begins. diff --git a/stylus-proc/src/methods/error.rs b/stylus-proc/src/methods/error.rs new file mode 100644 index 0000000..cb1df47 --- /dev/null +++ b/stylus-proc/src/methods/error.rs @@ -0,0 +1,51 @@ +// Copyright 2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md + +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, Fields, ItemEnum}; + +pub fn derive_solidity_error(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as ItemEnum); + let name = &input.ident; + let mut match_arms = quote!(); + let mut errors = vec![]; + for variant in input.variants { + let variant_name = variant.ident; + let error = match variant.fields { + Fields::Unnamed(e) if variant.fields.len() == 1 => e.unnamed.first().unwrap().clone(), + _ => error!(variant.fields, "Variant not a 1-tuple"), + }; + match_arms.extend(quote! { + #name::#variant_name(e) => e.encode(), + }); + errors.push(error); + } + quote! { + impl From<#name> for ::alloc::vec::Vec { + fn from(err: #name) -> ::alloc::vec::Vec { + match err { + #match_arms + } + } + } + + impl stylus_sdk::abi::export::internal::InnerTypes for #name { + fn inner_types() -> Vec { + use alloc::vec; + use core::any::TypeId; + use stylus_sdk::abi::export::internal::InnerType; + use stylus_sdk::alloy_sol_types::SolError; + + vec![ + #( + InnerType { + name: format!("error {};", <#errors as SolError>::SIGNATURE.replace(',', ", ")), + id: TypeId::of::<#errors>(), + } + ),* + ] + } + } + }.into() +} diff --git a/stylus-proc/src/methods/external.rs b/stylus-proc/src/methods/external.rs index 77b6cd9..0956b35 100644 --- a/stylus-proc/src/methods/external.rs +++ b/stylus-proc/src/methods/external.rs @@ -20,6 +20,7 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { let mut selectors = quote!(); let mut match_selectors = quote!(); let mut abi = quote!(); + let mut types = vec![]; for item in input.items.iter_mut() { let ImplItem::Method(method) = item else { @@ -278,6 +279,24 @@ pub fn external(_attr: TokenStream, input: TokenStream) -> TokenStream { return router.into(); } + for item in input.items.iter_mut() { + let ImplItem::Method(method) = item else { + continue; + }; + if let ReturnType::Type(_, ty) = &method.sig.output { + types.push(ty); + } + } + + let type_decls = quote! { + let mut seen = HashSet::new(); + for item in [].iter() #(.chain(&<#types as InnerTypes>::inner_types()))* { + if seen.insert(item.id) { + writeln!(f, "\n {}", item.name)?; + } + } + }; + let name = match *self_ty.clone() { Type::Path(path) => path.path.segments.last().unwrap().ident.clone().to_string(), _ => error!(self_ty, "Can't generate ABI for unnamed type"), @@ -309,12 +328,14 @@ 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}; + use stylus_sdk::abi::export::{underscore_if_sol, internal::InnerTypes}; + use std::collections::HashSet; #(#inherited_abis)* write!(f, "interface I{}", #name)?; #is_clause write!(f, " {{")?; #abi + #type_decls writeln!(f, "}}")?; Ok(()) } diff --git a/stylus-proc/src/methods/mod.rs b/stylus-proc/src/methods/mod.rs index 256b033..d3e69d2 100644 --- a/stylus-proc/src/methods/mod.rs +++ b/stylus-proc/src/methods/mod.rs @@ -2,4 +2,5 @@ // For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md pub mod entrypoint; +pub mod error; pub mod external; diff --git a/stylus-proc/src/storage/mod.rs b/stylus-proc/src/storage/mod.rs index 8781d06..cd6b38a 100644 --- a/stylus-proc/src/storage/mod.rs +++ b/stylus-proc/src/storage/mod.rs @@ -1,13 +1,11 @@ -// Copyright 2023, Offchain Labs, Inc. +// Copyright 2023-2024, Offchain Labs, Inc. // For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md use crate::storage::proc::{SolidityField, SolidityFields, SolidityStruct, SolidityStructs}; use proc_macro::TokenStream; use quote::{quote, ToTokens}; use std::mem; -use syn::{ - parse_macro_input, punctuated::Punctuated, Fields, Index, ItemEnum, ItemStruct, Token, Type, -}; +use syn::{parse_macro_input, punctuated::Punctuated, Index, ItemStruct, Token, Type}; mod proc; @@ -216,38 +214,12 @@ pub fn derive_erase(input: TokenStream) -> TokenStream { self.#ident.erase(); }); } - let output = quote! { + quote! { impl #impl_generics stylus_sdk::storage::Erase for #name #ty_generics #where_clause { fn erase(&mut self) { #erase_fields } } - }; - output.into() -} - -pub fn derive_solidity_error(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as ItemEnum); - let name = &input.ident; - let mut match_arms = quote! {}; - for variant in input.variants.iter() { - let variant_name = &variant.ident; - match variant.fields { - Fields::Unnamed(_) if variant.fields.len() == 1 => {} - _ => panic!("SolidityError: Each variant must be a tuple struct with one field"), - } - match_arms.extend(quote! { - #name::#variant_name(e) => e.encode(), - }) } - let output = quote! { - impl From<#name> for ::alloc::vec::Vec { - fn from(err: #name) -> ::alloc::vec::Vec { - match err { - #match_arms - } - } - } - }; - output.into() + .into() } diff --git a/stylus-sdk/src/abi/export/internal.rs b/stylus-sdk/src/abi/export/internal.rs new file mode 100644 index 0000000..129183a --- /dev/null +++ b/stylus-sdk/src/abi/export/internal.rs @@ -0,0 +1,82 @@ +// Copyright 2024, Offchain Labs, Inc. +// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/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. + +use alloy_primitives::{Address, FixedBytes, Signed, Uint}; +use core::any::TypeId; + +/// Represents a unique Solidity Type. +pub struct InnerType { + /// Full interface string. + pub name: String, + /// Unique identifier for de-duplication when printing interfaces. + pub id: TypeId, +} + +/// Trait for collecting structs and error types. +pub trait InnerTypes { + /// Collect any structs and errors under the type. + /// Empty for primitives. + fn inner_types() -> Vec { + vec![] + } +} + +impl InnerTypes for Result +where + O: InnerTypes, + E: InnerTypes, +{ + fn inner_types() -> Vec { + let mut out = O::inner_types(); + out.extend(E::inner_types()); + out + } +} + +impl InnerTypes for Vec { + fn inner_types() -> Vec { + T::inner_types() + } +} + +impl InnerTypes for [T; N] { + fn inner_types() -> Vec { + T::inner_types() + } +} + +macro_rules! impl_inner { + ($ty:ident $($rest:ident)+) => { + impl_inner!($ty); + impl_inner!($($rest)+); + }; + ($ty:ident) => { + impl InnerTypes for $ty {} + }; +} + +impl_inner!(bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 String Address); + +impl InnerTypes for Uint {} +impl InnerTypes for Signed {} +impl InnerTypes for FixedBytes {} + +macro_rules! impl_tuple { + () => { + impl InnerTypes for () {} + }; + ($first:ident $(, $rest:ident)*) => { + impl<$first: InnerTypes $(, $rest: InnerTypes)*> InnerTypes for ( $first $(, $rest)* , ) { + fn inner_types() -> Vec { + vec![] + } + } + + impl_tuple! { $($rest),* } + }; +} + +impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X); diff --git a/stylus-sdk/src/abi/export.rs b/stylus-sdk/src/abi/export/mod.rs similarity index 97% rename from stylus-sdk/src/abi/export.rs rename to stylus-sdk/src/abi/export/mod.rs index c81c6c5..535291c 100644 --- a/stylus-sdk/src/abi/export.rs +++ b/stylus-sdk/src/abi/export/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023, Offchain Labs, Inc. +// Copyright 2023-2024, Offchain Labs, Inc. // For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md //! Traits for exporting Solidity interfaces. @@ -12,6 +12,9 @@ use core::{fmt, marker::PhantomData}; use lazy_static::lazy_static; use regex::Regex; +#[doc(hidden)] +pub mod internal; + /// Trait for storage types so that users can print a Solidity interface to the console. /// This is auto-derived via the [`external`] macro when the `export-abi` feature is enabled. /// diff --git a/stylus-sdk/src/abi/internal.rs b/stylus-sdk/src/abi/internal.rs index 1ad9902..84cb68d 100644 --- a/stylus-sdk/src/abi/internal.rs +++ b/stylus-sdk/src/abi/internal.rs @@ -76,8 +76,8 @@ where if abi == "()" { Ok(()) } else if abi.starts_with('(') { - write!(f, " returns {}", abi) + write!(f, " returns {abi}") } else { - write!(f, " returns ({})", abi) + write!(f, " returns ({abi})") } } From 1383cc0ee3921c14a49bdeefa679396b4fac4fa1 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Tue, 20 Feb 2024 22:54:20 -0700 Subject: [PATCH 10/14] cfg-gate abi code --- stylus-proc/src/methods/error.rs | 44 ++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/stylus-proc/src/methods/error.rs b/stylus-proc/src/methods/error.rs index cb1df47..5b8d3c0 100644 --- a/stylus-proc/src/methods/error.rs +++ b/stylus-proc/src/methods/error.rs @@ -21,31 +21,37 @@ pub fn derive_solidity_error(input: TokenStream) -> TokenStream { }); errors.push(error); } - quote! { - impl From<#name> for ::alloc::vec::Vec { - fn from(err: #name) -> ::alloc::vec::Vec { + let mut output = quote! { + impl From<#name> for alloc::vec::Vec { + fn from(err: #name) -> alloc::vec::Vec { match err { #match_arms } } } + }; - impl stylus_sdk::abi::export::internal::InnerTypes for #name { - fn inner_types() -> Vec { - use alloc::vec; - use core::any::TypeId; - use stylus_sdk::abi::export::internal::InnerType; - use stylus_sdk::alloy_sol_types::SolError; + if cfg!(feature = "export-abi") { + output.extend(quote! { + impl stylus_sdk::abi::export::internal::InnerTypes for #name { + fn inner_types() -> alloc::vec::Vec { + use alloc::{format, vec}; + use core::any::TypeId; + use stylus_sdk::abi::export::internal::InnerType; + use stylus_sdk::alloy_sol_types::SolError; - vec![ - #( - InnerType { - name: format!("error {};", <#errors as SolError>::SIGNATURE.replace(',', ", ")), - id: TypeId::of::<#errors>(), - } - ),* - ] + vec![ + #( + InnerType { + name: format!("error {};", <#errors as SolError>::SIGNATURE.replace(',', ", ")), + id: TypeId::of::<#errors>(), + } + ),* + ] + } } - } - }.into() + }); + } + + output.into() } From 1a0f2a94153cf67579bcccab0a691c3b4386ccae Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 21 Feb 2024 17:41:43 -0700 Subject: [PATCH 11/14] address review comments --- stylus-proc/src/methods/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylus-proc/src/methods/error.rs b/stylus-proc/src/methods/error.rs index 5b8d3c0..968837f 100644 --- a/stylus-proc/src/methods/error.rs +++ b/stylus-proc/src/methods/error.rs @@ -17,7 +17,7 @@ pub fn derive_solidity_error(input: TokenStream) -> TokenStream { _ => error!(variant.fields, "Variant not a 1-tuple"), }; match_arms.extend(quote! { - #name::#variant_name(e) => e.encode(), + #name::#variant_name(e) => stylus_sdk::alloy_sol_types::SolError::encode(&e), }); errors.push(error); } From fff184ecf4039817112d1848c8f5688bf87f2da4 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Fri, 23 Feb 2024 11:40:20 -0700 Subject: [PATCH 12/14] remove testnet-2 hostios --- stylus-sdk/src/evm.rs | 2 +- stylus-sdk/src/hostio.rs | 16 +--------------- stylus-sdk/src/types.rs | 29 ----------------------------- 3 files changed, 2 insertions(+), 45 deletions(-) diff --git a/stylus-sdk/src/evm.rs b/stylus-sdk/src/evm.rs index 96e9ae4..f2b15fb 100644 --- a/stylus-sdk/src/evm.rs +++ b/stylus-sdk/src/evm.rs @@ -54,7 +54,7 @@ pub fn log(event: T) { /// This function exists to force the compiler to import this symbol. /// Calling it will unproductively consume gas. pub fn pay_for_memory_grow(pages: u16) { - unsafe { hostio::pay_for_memory_grow(pages) } + unsafe { hostio::memory_grow(pages) } } wrap_hostio!( diff --git a/stylus-sdk/src/hostio.rs b/stylus-sdk/src/hostio.rs index 82792bf..c115630 100644 --- a/stylus-sdk/src/hostio.rs +++ b/stylus-sdk/src/hostio.rs @@ -28,20 +28,6 @@ extern "C" { /// [`BALANCE`]: https://www.evm.codes/#31 pub fn account_balance(address: *const u8, dest: *mut u8); - /// 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. - /// - /// [`EXT_CODE_COPY`]: https://www.evm.codes/#3C - pub fn account_code(address: *const u8, offset: usize, size: usize, dest: *mut u8) -> usize; - - /// Gets the size of the code in bytes at the given address. The semantics are equivalent - /// to that of the EVM's [`EXT_CODESIZE`]. - /// - /// [`EXT_CODESIZE`]: https://www.evm.codes/#3B - pub fn account_code_size(address: *const u8) -> usize; - /// Gets the code hash of the account at the given address. The semantics are equivalent /// to that of the EVM's [`EXT_CODEHASH`] opcode. Note that the code hash of an account without /// code will be the empty hash @@ -235,7 +221,7 @@ extern "C" { /// Internally the Stylus VM forces calls to this hostio whenever new WASM pages are allocated. /// Calls made voluntarily will unproductively consume gas. #[allow(dead_code)] - pub fn pay_for_memory_grow(pages: u16); + pub fn memory_grow(pages: u16); /// Whether the current call is reentrant. pub fn msg_reentrant() -> bool; diff --git a/stylus-sdk/src/types.rs b/stylus-sdk/src/types.rs index a0ab9fb..2c65cb5 100644 --- a/stylus-sdk/src/types.rs +++ b/stylus-sdk/src/types.rs @@ -14,7 +14,6 @@ //! ``` use crate::hostio; -use alloc::vec::Vec; use alloy_primitives::{b256, Address, B256, U256}; /// Trait that allows the [`Address`] type to inspect the corresponding account's balance and codehash. @@ -22,20 +21,6 @@ pub trait AddressVM { /// The balance in wei of the account. fn balance(&self) -> U256; - /// The account's code. - /// - /// Returns an empty [`vec`] for [`EOAs`]. - /// - /// [`EOAs`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account - fn code(&self) -> Vec; - - /// The length of the account's code in bytes. - /// - /// Returns `0` for [`EOAs`]. - /// - /// [`EOAs`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account - fn code_size(&self) -> usize; - /// The codehash of the contract or [`EOA`] at the given address. /// /// [`EOA`]: https://ethereum.org/en/developers/docs/accounts/#types-of-account @@ -56,20 +41,6 @@ impl AddressVM for Address { U256::from_be_bytes(data) } - fn code(&self) -> Vec { - let size = self.code_size(); - let mut data = Vec::with_capacity(size); - unsafe { - hostio::account_code(self.as_ptr(), 0, size, data.as_mut_ptr()); - data.set_len(size); - } - data - } - - fn code_size(&self) -> usize { - unsafe { hostio::account_code_size(self.as_ptr()) } - } - fn codehash(&self) -> B256 { let mut data = [0; 32]; unsafe { hostio::account_codehash(self.as_ptr(), data.as_mut_ptr()) }; From 7e235974002886793185951b8b2648dc6cf4adf8 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Fri, 23 Feb 2024 11:41:03 -0700 Subject: [PATCH 13/14] bump version to 0.4.3 --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d6fa83..418fc24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -308,7 +308,7 @@ checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] name = "mini-alloc" -version = "0.4.2" +version = "0.4.3" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-test", @@ -498,7 +498,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.4.2" +version = "0.4.3" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "stylus-sdk" -version = "0.4.2" +version = "0.4.3" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index b38370b..d56cda7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["stylus-sdk", "stylus-proc", "mini-alloc"] resolver = "2" [workspace.package] -version = "0.4.2" +version = "0.4.3" edition = "2021" authors = ["Offchain Labs"] license = "MIT OR Apache-2.0" From 5bb4a8d686c769c375d347500aea6c054d654490 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Fri, 23 Feb 2024 11:49:39 -0700 Subject: [PATCH 14/14] fix smoketest --- ci/smoke_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/smoke_test.sh b/ci/smoke_test.sh index fa23fd4..cb9b8bd 100755 --- a/ci/smoke_test.sh +++ b/ci/smoke_test.sh @@ -11,4 +11,4 @@ cargo stylus new counter cd counter echo "[workspace]" >> Cargo.toml -cargo stylus deploy --private-key $PRIV_KEY +cargo stylus deploy --private-key $PRIV_KEY -e https://stylus-testnet.arbitrum.io/rpc