diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a3a60add1e..7e28b700135 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `#[ink::contract_ref]` attribute - [#2648](https://github.com/use-ink/ink/pull/2648) - Add `ink_revive_types` (and remove `pallet-revive` dependency from `ink_e2e`) - [#2657](https://github.com/use-ink/ink/pull/2657) - non-allocating Solidity ABI encoder - [#2655](https://github.com/use-ink/ink/pull/2655) +- Add `Event::encode_data_to` - [#2677](https://github.com/use-ink/ink/pull/2677) ### Changed - Marks the `pallet-revive` host function `account_id` stable - [#2578](https://github.com/use-ink/ink/pull/2578) diff --git a/crates/env/src/engine/on_chain/pallet_revive.rs b/crates/env/src/engine/on_chain/pallet_revive.rs index e06196b0cc5..b78b0ffb878 100644 --- a/crates/env/src/engine/on_chain/pallet_revive.rs +++ b/crates/env/src/engine/on_chain/pallet_revive.rs @@ -995,14 +995,7 @@ impl TypedEnvBackend for EnvInstance { .chunks_exact(32) .map(|c| c.try_into().unwrap()) .collect::>(); - let enc_data = scope.take_encoded_with(|buffer| { - let encoded = event.encode_data(); - let len = encoded.len(); - // NOTE: panics if buffer isn't large enough. - // This behavior is similar to `ScopedBuffer::take_encoded`. - buffer[..len].copy_from_slice(&encoded); - len - }); + let enc_data = scope.take_encoded_with(|buffer| event.encode_data_to(buffer)); ext::deposit_event(&enc_topics[..], enc_data); } diff --git a/crates/env/src/event.rs b/crates/env/src/event.rs index 966cff93f13..f7e12ee8fae 100644 --- a/crates/env/src/event.rs +++ b/crates/env/src/event.rs @@ -252,6 +252,10 @@ pub trait Event: AbiEncodeWith { /// ABI encode the dynamic data of this event. fn encode_data(&self) -> ink_prelude::vec::Vec; + + /// ABI encode the dynamic data of this event into the given buffer, and returns the + /// number of bytes written. + fn encode_data_to(&self, buffer: &mut [u8]) -> usize; } mod private { diff --git a/crates/ink/macro/src/event/mod.rs b/crates/ink/macro/src/event/mod.rs index 56f84076a25..149ec73c174 100644 --- a/crates/ink/macro/src/event/mod.rs +++ b/crates/ink/macro/src/event/mod.rs @@ -204,10 +204,15 @@ fn event_derive_struct(s: synstructure::Structure) -> syn::Result } ); - let encode_data = match abi { - Abi::Ink => quote! { - ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) - }, + let (encode_data, encode_data_to) = match abi { + Abi::Ink => ( + quote! { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) + }, + quote! { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } + ), Abi::Sol => { // For Solidity ABI encoding, only un-indexed fields are encoded as data. let data_field_tys = data_fields.iter().map(|field| { @@ -217,15 +222,24 @@ fn event_derive_struct(s: synstructure::Structure) -> syn::Result let data_field_values = data_fields.iter().map(|field| { &field.binding }); - quote! { - match self { - #pat => { - ::ink::sol::encode_sequence::<( #( #data_field_tys, )* )>( - &( #( #data_field_values, )* ), - ) + let ty = quote! { ( #( #data_field_tys, )* ) }; + let val = quote! { ( #( #data_field_values, )* ) }; + ( + quote! { + match self { + #pat => { + ::ink::sol::encode_sequence::<#ty>(&#val) + } + } + }, + quote! { + match self { + #pat => { + ::ink::sol::encode_sequence_to::<#ty>(&#val, buffer) + } } } - } + ) }, }; @@ -248,6 +262,10 @@ fn event_derive_struct(s: synstructure::Structure) -> syn::Result fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { #encode_data } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + #encode_data_to + } }) })) } diff --git a/crates/ink/macro/src/tests/event.rs b/crates/ink/macro/src/tests/event.rs index 52406ff7f19..a436e4921ed 100644 --- a/crates/ink/macro/src/tests/event.rs +++ b/crates/ink/macro/src/tests/event.rs @@ -57,6 +57,10 @@ fn unit_struct_works() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } @@ -98,6 +102,10 @@ fn unit_struct_anonymous_has_no_topics() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } no_build @@ -143,6 +151,10 @@ fn struct_with_fields_no_topics() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } @@ -192,6 +204,10 @@ fn struct_with_fields_and_some_topics() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } no_build @@ -234,6 +250,10 @@ fn custom_signature_topic() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } no_build @@ -276,6 +296,10 @@ fn name_override_works() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } no_build @@ -319,6 +343,10 @@ fn custom_signature_topic_precedence() { fn encode_data(&self) -> ::ink::prelude::vec::Vec<::core::primitive::u8> { ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_with(self) } + + fn encode_data_to(&self, buffer: &mut [::core::primitive::u8]) -> ::core::primitive::usize { + ::ink::abi::AbiEncodeWith::<::ink::abi::Ink>::encode_to_slice(self, buffer) + } } }; } no_build