Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implements the API for the `pallet-revive` host function `to_account_id` - [#2578](https://github.com/use-ink/ink/pull/2578)
- 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)

### Changed
- Marks the `pallet-revive` host function `account_id` stable - [#2578](https://github.com/use-ink/ink/pull/2578)
Expand Down
14 changes: 14 additions & 0 deletions crates/env/src/call/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,20 @@ where
.collect()
}

fn encode_to(&self, buffer: &mut [u8]) -> usize {
// TODO: (@davidsemakula) Optimized implementation.
let encoded = SolEncode::encode(self);
let len = encoded.len();
debug_assert!(
len <= buffer.len(),
"encode scope buffer overflowed, encoded len is {} but buffer len is {}",
len,
buffer.len()
);
buffer[..len].copy_from_slice(&encoded);
len
}

// NOTE: Not actually used for encoding because of `encode` override above.
fn to_sol_type(&self) {}
}
Expand Down
11 changes: 1 addition & 10 deletions crates/primitives/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,7 @@ where
}

fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
let encoded = SolEncode::encode(self);
let len = encoded.len();
debug_assert!(
len <= buffer.len(),
"encode scope buffer overflowed, encoded len is {} but buffer len is {}",
len,
buffer.len()
);
buffer[..len].copy_from_slice(&encoded);
len
SolEncode::encode_to(self, buffer)
}

fn encode_to_vec(&self, buffer: &mut Vec<u8>) {
Expand Down
33 changes: 31 additions & 2 deletions crates/primitives/src/sol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod macros;

mod bytes;
mod encodable;
mod encoder;
mod error;
mod params;
mod result;
Expand Down Expand Up @@ -182,11 +183,21 @@ pub trait SolEncode<'a> {
const DYNAMIC: bool =
<<Self::SolType as SolTypeEncode>::AlloyType as AlloySolType>::DYNAMIC;

/// Solidity ABI encode the value.
/// Solidity ABI encode the value
fn encode(&'a self) -> Vec<u8> {
<Self::SolType as SolTypeEncode>::encode(&self.to_sol_type())
}

/// Solidity ABI encode the value into the given buffer, and returns the number of
/// bytes written.
///
/// # Panics
///
/// Panics if the buffer is not large enough.
fn encode_to(&'a self, buffer: &mut [u8]) -> usize {
<Self::SolType as SolTypeEncode>::encode_to(&self.to_sol_type(), buffer)
}

/// Solidity ABI encode the value as a topic (i.e. an indexed event parameter).
fn encode_topic<H>(&'a self, hasher: H) -> [u8; 32]
where
Expand All @@ -207,13 +218,31 @@ pub trait SolEncode<'a> {
/// - `T` must be a tuple type where each member implements [`SolEncode`].
/// - The result can be different from [`SolEncode::encode`] for the given tuple because
/// this function always returns the encoded data in place, even for tuples containing
/// dynamic types (i.e. no offset is included for dynamic tuples).
/// dynamic types (i.e. no top-level offset is included for dynamic tuples).
///
/// This function is a convenience wrapper for [`SolParamsEncode::encode`].
pub fn encode_sequence<T: for<'a> SolParamsEncode<'a>>(value: &T) -> Vec<u8> {
SolParamsEncode::encode(value)
}

/// Solidity ABI encode the given value into the given buffer as a parameter sequence, and
/// returns the number of bytes written.
///
/// # Note
///
/// - `T` must be a tuple type where each member implements [`SolEncode`].
/// - The result can be different from [`SolEncode::encode_to`] for the given tuple
/// because this function always returns the encoded data in place, even for tuples
/// containing dynamic types (i.e. no top-level offset is included for dynamic tuples).
///
/// This function is a convenience wrapper for [`SolParamsEncode::encode_to`].
pub fn encode_sequence_to<T: for<'a> SolParamsEncode<'a>>(
value: &T,
buffer: &mut [u8],
) -> usize {
SolParamsEncode::encode_to(value, buffer)
}

/// Solidity ABI decode the given data as a parameter sequence.
///
/// # Note
Expand Down
25 changes: 9 additions & 16 deletions crates/primitives/src/sol/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ use core::{

use alloy_sol_types::{
SolType as AlloySolType,
abi::token::{
PackedSeqToken,
WordToken,
},
sol_data,
};
use ink_prelude::{
Expand All @@ -46,6 +42,7 @@ use crate::sol::{
encodable::{
DynSizeDefault,
FixedSizeDefault,
Word,
},
types::SolTokenType,
utils::{
Expand Down Expand Up @@ -108,7 +105,7 @@ where
// requirement for `SolTypeValue<Self::AlloyType>`.
let mut word = [0; 32];
word[..N].copy_from_slice(self.0.as_slice());
WordToken::from(word)
Word(word)
}
}

Expand All @@ -120,11 +117,11 @@ where
where
H: Fn(&[u8], &mut [u8; 32]),
{
self.tokenize().0.0
self.tokenize().0
}

fn topic_preimage(&self, buffer: &mut Vec<u8>) {
buffer.extend(self.tokenize().0.0);
buffer.extend(self.tokenize().0);
}

fn default_topic_preimage(buffer: &mut Vec<u8>) {
Expand All @@ -144,7 +141,7 @@ impl<const N: usize> SolTokenType for FixedBytes<N>
where
sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
{
type TokenType<'enc> = WordToken;
type TokenType<'enc> = Word;

type DefaultType = FixedSizeDefault;
}
Expand Down Expand Up @@ -256,9 +253,7 @@ impl SolTypeEncode for DynBytes {
const DEFAULT_VALUE: Self::DefaultType = DynSizeDefault;

fn tokenize(&self) -> Self::TokenType<'_> {
// Direct implementation simplifies generic implementations by removing
// requirement for `SolTypeValue<Self::AlloyType>`.
PackedSeqToken(self.0.as_slice())
self.0.as_slice()
}
}

Expand Down Expand Up @@ -290,7 +285,7 @@ impl SolTopicEncode for DynBytes {
}

impl SolTokenType for DynBytes {
type TokenType<'enc> = PackedSeqToken<'enc>;
type TokenType<'enc> = &'enc [u8];

type DefaultType = DynSizeDefault;
}
Expand Down Expand Up @@ -369,9 +364,7 @@ impl SolTypeEncode for ByteSlice<'_> {
const DEFAULT_VALUE: Self::DefaultType = DynSizeDefault;

fn tokenize(&self) -> Self::TokenType<'_> {
// Direct implementation simplifies generic implementations by removing
// requirement for `SolTypeValue<Self::AlloyType>`.
PackedSeqToken(self.0)
self.0
}
}

Expand Down Expand Up @@ -403,7 +396,7 @@ impl SolTopicEncode for ByteSlice<'_> {
}

impl SolTokenType for ByteSlice<'_> {
type TokenType<'enc> = PackedSeqToken<'enc>;
type TokenType<'enc> = &'enc [u8];

type DefaultType = DynSizeDefault;
}
Expand Down
Loading
Loading