Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add abi_packed_encoded_size #672

Merged
merged 1 commit into from
Jun 18, 2024
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
2 changes: 1 addition & 1 deletion crates/dyn-abi/src/dynamic/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct DynSolEvent {
impl DynSolEvent {
/// Creates a new event, without length-checking the indexed, or ensuring
/// the body is a tuple. This allows creation of invalid events.
pub fn new_unchecked(
pub const fn new_unchecked(
topic_0: Option<B256>,
indexed: Vec<DynSolType>,
body: DynSolType,
Expand Down
69 changes: 36 additions & 33 deletions crates/dyn-abi/src/dynamic/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,21 @@ impl DynSolValue {
}
}

/// Encodes the packed value and appends it to the end of a byte array.
/// Non-standard Packed Mode ABI encoding.
///
/// Note that invalid value sizes will saturate to the maximum size, e.g. `Uint(x, 300)` will
/// behave the same as `Uint(x, 256)`.
///
/// See [`SolType::abi_encode_packed`](alloy_sol_types::SolType::abi_encode_packed) for more
/// details.
#[inline]
pub fn abi_encode_packed(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.abi_packed_encoded_size());
self.abi_encode_packed_to(&mut buf);
buf
}

/// Non-standard Packed Mode ABI encoding.
///
/// See [`abi_encode_packed`](Self::abi_encode_packed) for more details.
pub fn abi_encode_packed_to(&self, buf: &mut Vec<u8>) {
Expand All @@ -690,49 +704,38 @@ impl DynSolValue {
}
Self::FixedArray(inner) | Self::Array(inner) => {
for val in inner {
let mut buf_inner = Vec::new();
val.abi_encode_packed_to(&mut buf_inner);

// Array elements are always padded
if buf_inner.len() < 32usize {
// Calculate the number of padding elements needed
let padding_needed = 32usize.saturating_sub(buf_inner.len());

// Extend the vector with the padding elements
buf_inner.resize(32usize, 0);

// Rotate the vector left by the number of padding elements added
buf_inner.rotate_right(padding_needed);
// Array elements are left-padded to 32 bytes.
if let Some(padding_needed) = 32usize.checked_sub(val.abi_packed_encoded_size())
{
buf.extend(core::iter::repeat(0).take(padding_needed));
}
buf.extend_from_slice(&buf_inner);
}
}
Self::Tuple(inner) => {
for val in inner {
val.abi_encode_packed_to(buf);
}
}
#[cfg(feature = "eip712")]
Self::CustomStruct { tuple, .. } => {
for val in tuple {
as_tuple!(Self inner) => {
for val in inner {
val.abi_encode_packed_to(buf);
}
}
}
}

/// Non-standard Packed Mode ABI encoding.
/// Returns the length of this value when ABI-encoded in Non-standard Packed Mode.
///
/// Note that invalid value sizes will saturate to the maximum size, e.g. `Uint(x, 300)` will
/// behave the same as `Uint(x, 256)`.
///
/// See [`SolType::abi_encode_packed`](alloy_sol_types::SolType::abi_encode_packed) for more
/// details.
#[inline]
pub fn abi_encode_packed(&self) -> Vec<u8> {
let mut buf = Vec::new();
self.abi_encode_packed_to(&mut buf);
buf
/// See [`abi_encode_packed`](Self::abi_encode_packed) for more details.
pub fn abi_packed_encoded_size(&self) -> usize {
match self {
Self::Address(_) | Self::Function(_) => 20,
Self::Bool(_) => 1,
Self::String(s) => s.len(),
Self::Bytes(b) => b.len(),
Self::FixedBytes(_, size) => (*size).min(32),
Self::Int(_, size) | Self::Uint(_, size) => (size / 8).min(32),
Self::FixedArray(inner) | Self::Array(inner) => {
inner.iter().map(|v| v.abi_packed_encoded_size().max(32)).sum()
}
as_tuple!(Self inner) => inner.iter().map(Self::abi_packed_encoded_size).sum(),
}
}

/// Tokenize this value into a [`DynToken`].
Expand Down
2 changes: 1 addition & 1 deletion crates/dyn-abi/src/eip712/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl TypeDef {
/// Instantiate a new type definition, without checking that the type name
/// is a valid root type. This may result in bad behavior in a resolver.
#[inline]
pub fn new_unchecked(type_name: String, props: Vec<PropertyDef>) -> Self {
pub const fn new_unchecked(type_name: String, props: Vec<PropertyDef>) -> Self {
Self { type_name, props }
}

Expand Down
4 changes: 2 additions & 2 deletions crates/primitives/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl LogData {
/// invalid logs. May be safely used when the length of the topic list is
/// known to be 4 or less.
#[inline]
pub fn new_unchecked(topics: Vec<B256>, data: Bytes) -> Self {
pub const fn new_unchecked(topics: Vec<B256>, data: Bytes) -> Self {
Self { topics, data }
}

Expand Down Expand Up @@ -109,7 +109,7 @@ impl Log {

/// Creates a new log.
#[inline]
pub fn new_unchecked(address: Address, topics: Vec<B256>, data: Bytes) -> Self {
pub const fn new_unchecked(address: Address, topics: Vec<B256>, data: Bytes) -> Self {
Self { address, data: LogData::new_unchecked(topics, data) }
}

Expand Down
1 change: 1 addition & 0 deletions crates/sol-macro-expander/src/expand/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, enumm: &ItemEnum) -> Result<TokenStream>

const SOL_NAME: &'static str = #uint8_st::SOL_NAME;
const ENCODED_SIZE: ::core::option::Option<usize> = #uint8_st::ENCODED_SIZE;
const PACKED_ENCODED_SIZE: ::core::option::Option<usize> = #uint8_st::PACKED_ENCODED_SIZE;

#[inline]
fn valid_token(token: &Self::Token<'_>) -> bool {
Expand Down
17 changes: 17 additions & 0 deletions crates/sol-macro-expander/src/expand/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, s: &ItemStruct) -> Result<TokenStream> {

#[inline]
fn stv_abi_encoded_size(&self) -> usize {
if let Some(size) = <Self as alloy_sol_types::SolType>::ENCODED_SIZE {
return size;
}

// TODO: Avoid cloning
let tuple = <UnderlyingRustTuple<'_> as ::core::convert::From<Self>>::from(self.clone());
<UnderlyingSolTuple<'_> as alloy_sol_types::SolType>::abi_encoded_size(&tuple)
Expand All @@ -106,6 +110,17 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, s: &ItemStruct) -> Result<TokenStream> {
let tuple = <UnderlyingRustTuple<'_> as ::core::convert::From<Self>>::from(self.clone());
<UnderlyingSolTuple<'_> as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out)
}

#[inline]
fn stv_abi_packed_encoded_size(&self) -> usize {
if let Some(size) = <Self as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE {
return size;
}

// TODO: Avoid cloning
let tuple = <UnderlyingRustTuple<'_> as ::core::convert::From<Self>>::from(self.clone());
<UnderlyingSolTuple<'_> as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple)
}
}

#[automatically_derived]
Expand All @@ -116,6 +131,8 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, s: &ItemStruct) -> Result<TokenStream> {
const SOL_NAME: &'static str = <Self as alloy_sol_types::SolStruct>::NAME;
const ENCODED_SIZE: Option<usize> =
<UnderlyingSolTuple<'_> as alloy_sol_types::SolType>::ENCODED_SIZE;
const PACKED_ENCODED_SIZE: Option<usize> =
<UnderlyingSolTuple<'_> as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE;

#[inline]
fn valid_token(token: &Self::Token<'_>) -> bool {
Expand Down
6 changes: 6 additions & 0 deletions crates/sol-macro-expander/src/expand/udt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, udt: &ItemUdt) -> Result<TokenStream> {
fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec<u8>) {
<#underlying_sol as alloy_sol_types::SolType>::abi_encode_packed_to(self, out)
}

#[inline]
fn stv_abi_packed_encoded_size(&self) -> usize {
<#underlying_sol as alloy_sol_types::SolType>::abi_encoded_size(self)
}
}

#[automatically_derived]
Expand Down Expand Up @@ -97,6 +102,7 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, udt: &ItemUdt) -> Result<TokenStream> {

const SOL_NAME: &'static str = Self::NAME;
const ENCODED_SIZE: Option<usize> = <#underlying_sol as alloy_sol_types::SolType>::ENCODED_SIZE;
const PACKED_ENCODED_SIZE: Option<usize> = <#underlying_sol as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE;

#[inline]
fn valid_token(token: &Self::Token<'_>) -> bool {
Expand Down
9 changes: 8 additions & 1 deletion crates/sol-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,19 @@ pub mod private {
pub trait SolTypeValue<T: super::SolType> {
// Note: methods are prefixed with `stv_` to avoid name collisions with
// the `SolValue` trait.
fn stv_to_tokens(&self) -> T::Token<'_>;

#[inline(always)]
fn stv_abi_encoded_size(&self) -> usize {
T::ENCODED_SIZE.unwrap()
}
fn stv_to_tokens(&self) -> T::Token<'_>;

#[inline(always)]
fn stv_abi_packed_encoded_size(&self) -> usize {
T::PACKED_ENCODED_SIZE.unwrap()
}
fn stv_abi_encode_packed_to(&self, out: &mut Vec<u8>);

fn stv_eip712_data_word(&self) -> super::Word;
}

Expand Down
Loading