Skip to content

Commit 106eeb7

Browse files
feat: optimize wasm binary size (#330)
* remove dynamic Host from logging * remove dynamic Host from #[storage] macro * remove dynamic Host from sol_interface and calls * add Host associated type to HostAccess * refactor VM * remove cfg_if from host access impl * use `impl Host` in tests and apis * use `impl Host` for unsafe deploy * add "unsized" constraint for host parameter, fix ./ci/clippy.sh --contract-client-gen pipeline * use `impl Host` in tests and contract client generation
1 parent 6a8ffe6 commit 106eeb7

File tree

17 files changed

+335
-368
lines changed

17 files changed

+335
-368
lines changed

stylus-core/src/host.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ dyn_clone::clone_trait_object!(Host);
3737

3838
/// Defines a trait that allows a Stylus contract to access its host safely.
3939
pub trait HostAccess {
40+
/// Host type returned by [`Self::vm()`].
41+
type Host: Host;
42+
4043
/// Provides access to the parametrized host of a contract, giving access
4144
/// to all the desired hostios from the user.
42-
fn vm(&self) -> &dyn Host;
45+
fn vm(&self) -> &Self::Host;
4346
}
4447

4548
/// Defines a trait that can deny access to a contract router method if a message value is

stylus-proc/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub fn sol_storage(input: TokenStream) -> TokenStream {
165165
/// # }
166166
/// # mod evm { pub fn gas_left() -> u64 { 100 } }
167167
/// # mod msg { pub fn value() -> alloy_primitives::U256 { 100.try_into().unwrap() } }
168-
/// pub fn do_call(host: &dyn Host, account: IService, user: Address) -> Result<String, Error> {
168+
/// pub fn do_call(host: &impl Host, account: IService, user: Address) -> Result<String, Error> {
169169
/// let config = Call::new()
170170
/// .gas(host.evm_gas_left() / 2) // limit to half the gas left
171171
/// .value(host.msg_value()); // set the callvalue
@@ -236,7 +236,7 @@ pub fn sol_storage(input: TokenStream) -> TokenStream {
236236
/// # mod evm { pub fn gas_left() -> u64 { 100 } }
237237
/// # mod msg { pub fn value() -> alloy_primitives::U256 { 100.try_into().unwrap() } }
238238
/// pub fn do_call(
239-
/// host: &dyn Host,
239+
/// host: &impl Host,
240240
/// account: IService, // serializes as an Address
241241
/// user: Address,
242242
/// ) -> Result<String, Error> {

stylus-proc/src/macros/entrypoint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ fn user_entrypoint_fn(user_fn: Ident) -> Option<syn::ItemFn> {
176176
#[no_mangle]
177177
#[cfg(not(feature = "contract-client-gen"))]
178178
pub extern "C" fn user_entrypoint(len: usize) -> usize {
179-
let host = stylus_sdk::host::VM(stylus_sdk::host::WasmVM{});
179+
let host = stylus_sdk::host::VM { host: stylus_sdk::host::WasmVM{}};
180180
#deny_reentrant
181181

182182
// The following call is a noop to ensure that pay_for_memory_grow is

stylus-proc/src/macros/public/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ fn get_client_funcs<E: InterfaceExtension>(
114114
let signature = quote! {
115115
#funcs_visibility fn #func_name(
116116
&self,
117-
host: &dyn stylus_sdk::stylus_core::host::Host,
117+
host: &impl stylus_sdk::stylus_core::host::Host,
118118
context: impl #context,
119119
#(#inputs,)*
120120
) -> #output_type

stylus-proc/src/macros/sol_interface.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,11 @@ impl Interface {
125125

126126
self.item_impl.items.push(parse_quote! {
127127
#(#attrs)*
128-
pub fn #rust_name(&self, host: &dyn stylus_sdk::stylus_core::host::Host, context: impl #context #(, #rust_args)*) ->
129-
Result<<#return_type as #SolType>::RustType, stylus_sdk::stylus_core::calls::errors::Error>
128+
pub fn #rust_name(
129+
&self,
130+
host: &impl stylus_sdk::stylus_core::host::Host,
131+
context: impl #context #(, #rust_args)*
132+
) -> Result<<#return_type as #SolType>::RustType, stylus_sdk::stylus_core::calls::errors::Error>
130133
{
131134
let args = <(#(#sol_args,)*) as #SolType>::abi_encode_params(&(#(#rust_arg_names,)*));
132135
let mut calldata = vec![#selector0, #selector1, #selector2, #selector3];
@@ -335,7 +338,7 @@ mod tests {
335338
#[function_attr]
336339
pub fn make_payment(
337340
&self,
338-
host: &dyn stylus_sdk::stylus_core::host::Host,
341+
host: &impl stylus_sdk::stylus_core::host::Host,
339342
context: impl stylus_sdk::stylus_core::calls::MutatingCallContext,
340343
user: <stylus_sdk::alloy_sol_types::sol_data::Address as stylus_sdk::alloy_sol_types::SolType>::RustType,
341344
) ->
@@ -354,7 +357,7 @@ mod tests {
354357

355358
pub fn get_constant(
356359
&self,
357-
host: &dyn stylus_sdk::stylus_core::host::Host,
360+
host: &impl stylus_sdk::stylus_core::host::Host,
358361
context: impl stylus_sdk::stylus_core::calls::StaticCallContext,
359362
) ->
360363
Result<<stylus_sdk::alloy_sol_types::sol_data::FixedBytes<32> as stylus_sdk::alloy_sol_types::SolType>::RustType, stylus_sdk::stylus_core::calls::errors::Error>
@@ -368,7 +371,7 @@ mod tests {
368371

369372
pub fn get_foo(
370373
&self,
371-
host: &dyn stylus_sdk::stylus_core::host::Host,
374+
host: &impl stylus_sdk::stylus_core::host::Host,
372375
context: impl stylus_sdk::stylus_core::calls::StaticCallContext,
373376
) ->
374377
Result<<inner::Foo as stylus_sdk::alloy_sol_types::SolType>::RustType, stylus_sdk::stylus_core::calls::errors::Error>

stylus-proc/src/macros/storage.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,28 +143,19 @@ impl Storage {
143143
fn impl_host_access(&self) -> syn::ItemImpl {
144144
let name = &self.name;
145145
let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
146-
cfg_if::cfg_if! {
147-
if #[cfg(feature = "stylus-test")] {
148-
parse_quote! {
149-
#[cfg(not(feature = "contract-client-gen"))]
150-
impl #impl_generics stylus_sdk::stylus_core::HostAccess for #name #ty_generics #where_clause {
151-
fn vm(&self) -> &dyn stylus_sdk::stylus_core::Host {
152-
self.__stylus_host.host.as_ref()
153-
}
154-
}
155-
}
156-
} else {
157-
parse_quote! {
158-
#[cfg(not(feature = "contract-client-gen"))]
159-
impl #impl_generics stylus_sdk::stylus_core::HostAccess for #name #ty_generics #where_clause {
160-
fn vm(&self) -> &dyn stylus_sdk::stylus_core::Host {
161-
&self.__stylus_host
162-
}
163-
}
146+
147+
parse_quote! {
148+
#[cfg(not(feature = "contract-client-gen"))]
149+
impl #impl_generics stylus_sdk::stylus_core::HostAccess for #name #ty_generics #where_clause {
150+
type Host = stylus_sdk::host::VM;
151+
152+
fn vm(&self) -> &Self::Host {
153+
&self.__stylus_host
164154
}
165155
}
166156
}
167157
}
158+
168159
fn impl_value_denier(&self) -> syn::ItemImpl {
169160
let name = &self.name;
170161
let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
@@ -181,6 +172,7 @@ impl Storage {
181172
}
182173
}
183174
}
175+
184176
fn impl_constructor_guard(&self) -> syn::ItemImpl {
185177
let name = &self.name;
186178
let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
@@ -205,6 +197,7 @@ impl Storage {
205197
}
206198
}
207199
}
200+
208201
fn impl_from_vm(&self) -> Option<syn::ItemImpl> {
209202
cfg_if::cfg_if! {
210203
if #[cfg(feature = "stylus-test")] {
@@ -236,6 +229,7 @@ impl Storage {
236229
}
237230
}
238231
}
232+
239233
fn impl_vm_access(&self) -> syn::ItemImpl {
240234
let name = &self.name;
241235
let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();

stylus-sdk/src/call/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ mod raw;
2727
pub mod transfer;
2828

2929
/// Static calls the contract at the given address.
30-
pub fn static_call(
31-
host: &dyn Host,
30+
pub fn static_call<H: Host + ?Sized>(
31+
host: &H,
3232
context: impl StaticCallContext,
3333
to: Address,
3434
data: &[u8],
@@ -49,8 +49,8 @@ pub fn static_call(
4949
/// A delegate call must trust the other contract to uphold safety requirements.
5050
/// Though this function clears any cached values, the other contract may arbitrarily change storage,
5151
/// spend ether, and do other things one should never blindly allow other contracts to do.
52-
pub unsafe fn delegate_call(
53-
host: &dyn Host,
52+
pub unsafe fn delegate_call<H: Host + ?Sized>(
53+
host: &H,
5454
context: impl MutatingCallContext,
5555
to: Address,
5656
data: &[u8],
@@ -64,8 +64,8 @@ pub unsafe fn delegate_call(
6464
}
6565

6666
/// Calls the contract at the given address.
67-
pub fn call(
68-
host: &dyn Host,
67+
pub fn call<H: Host + ?Sized>(
68+
host: &H,
6969
context: impl MutatingCallContext,
7070
to: Address,
7171
data: &[u8],

stylus-sdk/src/call/raw.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ use stylus_core::Host;
1010
/// For safe calls, see [`Call`](super::Call).
1111
#[derive(Clone)]
1212
#[must_use]
13-
pub struct RawCall<'a> {
13+
pub struct RawCall<'a, H: Host + ?Sized> {
1414
kind: CallKind,
1515
callvalue: U256,
1616
gas: Option<u64>,
1717
offset: usize,
1818
size: Option<usize>,
1919
#[allow(unused)]
2020
cache_policy: CachePolicy,
21-
host: &'a dyn Host,
21+
host: &'a H,
2222
}
2323

2424
/// What kind of call to perform.
@@ -40,7 +40,7 @@ pub(crate) enum CachePolicy {
4040
Clear,
4141
}
4242

43-
impl<'a> RawCall<'a> {
43+
impl<'a, H: Host + ?Sized> RawCall<'a, H> {
4444
/// Begin configuring the raw call, similar to how [`std::fs::OpenOptions`][OpenOptions] works.
4545
///
4646
/// ```no_run
@@ -49,7 +49,7 @@ impl<'a> RawCall<'a> {
4949
/// use stylus_sdk::{alloy_primitives::address, hex};
5050
/// use stylus_sdk::host::WasmVM;
5151
///
52-
/// fn do_call(host: &dyn Host) -> Result<(), ()> {
52+
/// fn do_call(host: &impl Host) -> Result<(), ()> {
5353
/// let contract = address!("361594F5429D23ECE0A88E4fBE529E1c49D524d8");
5454
/// let calldata = &hex::decode("eddecf107b5740cef7f5a01e3ea7e287665c4e75").unwrap();
5555
///
@@ -65,7 +65,7 @@ impl<'a> RawCall<'a> {
6565
/// ```
6666
///
6767
/// [OpenOptions]: https://doc.rust-lang.org/stable/std/fs/struct.OpenOptions.html
68-
pub fn new(host: &'a dyn Host) -> Self {
68+
pub fn new(host: &'a H) -> Self {
6969
Self {
7070
host,
7171
cache_policy: CachePolicy::default(),
@@ -78,7 +78,7 @@ impl<'a> RawCall<'a> {
7878
}
7979

8080
/// Configures a call that supplies callvalue, denominated in wei.
81-
pub fn new_with_value(host: &'a dyn Host, callvalue: U256) -> Self {
81+
pub fn new_with_value(host: &'a H, callvalue: U256) -> Self {
8282
Self {
8383
host,
8484
callvalue,
@@ -93,7 +93,7 @@ impl<'a> RawCall<'a> {
9393
/// Begin configuring a [`delegate call`].
9494
///
9595
/// [`DELEGATE_CALL`]: https://www.evm.codes/#F4
96-
pub fn new_delegate(host: &'a dyn Host) -> Self {
96+
pub fn new_delegate(host: &'a H) -> Self {
9797
Self {
9898
host,
9999
cache_policy: CachePolicy::default(),
@@ -108,7 +108,7 @@ impl<'a> RawCall<'a> {
108108
/// Begin configuring a [`static call`].
109109
///
110110
/// [`STATIC_CALL`]: https://www.evm.codes/#FA
111-
pub fn new_static(host: &'a dyn Host) -> Self {
111+
pub fn new_static(host: &'a H) -> Self {
112112
Self {
113113
host,
114114
cache_policy: CachePolicy::default(),

stylus-sdk/src/call/transfer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ use super::RawCall;
1717
/// # use stylus_sdk::prelude::*;
1818
/// # use stylus_sdk::stylus_core::host::Host;
1919
/// # use stylus_sdk::call::transfer::transfer_eth;
20-
/// # fn wrap(host: &dyn Host) -> Result<(), Vec<u8>> {
20+
/// # fn wrap(host: &impl Host) -> Result<(), Vec<u8>> {
2121
/// # let value = alloy_primitives::U256::ZERO;
2222
/// # let recipient = alloy_primitives::Address::ZERO;
2323
/// transfer_eth(host, recipient, value)?; // these two are equivalent
2424
/// call(host, Call::new().value(value), recipient, &[])?; // these two are equivalent
2525
/// # Ok(())
2626
/// # }
2727
/// ```
28-
pub fn transfer_eth(host: &dyn Host, to: Address, amount: U256) -> Result<(), Vec<u8>> {
28+
pub fn transfer_eth(host: &impl Host, to: Address, amount: U256) -> Result<(), Vec<u8>> {
2929
host.flush_cache(true); // clear the storage to persist changes, invalidating the cache
3030
unsafe {
3131
RawCall::new_with_value(host, amount)

stylus-sdk/src/deploy/raw.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl RawDeploy {
6969
/// For extra flexibility, this method does not clear the global storage cache.
7070
pub unsafe fn deploy(
7171
self,
72-
host: &dyn Host,
72+
host: &impl Host,
7373
code: &[u8],
7474
endowment: U256,
7575
) -> Result<Address, Vec<u8>> {

0 commit comments

Comments
 (0)