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

Implement specific bit types for integers #677

Merged
merged 6 commits into from
Aug 7, 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
12 changes: 6 additions & 6 deletions crates/dyn-abi/benches/abi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(unknown_lints, clippy::incompatible_msrv, missing_docs)]

use alloy_dyn_abi::{DynSolType, DynSolValue};
use alloy_primitives::{hex, U256};
use alloy_primitives::{hex, Uint, U256};
use alloy_sol_types::{sol, sol_data, SolType, SolValue};
use criterion::{
criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
Expand Down Expand Up @@ -142,12 +142,12 @@ fn encode_struct_input() -> Input {
Input {
tokenIn: hex!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").into(),
tokenOut: hex!("955d5c14C8D4944dA1Ea7836bd44D54a8eC35Ba1").into(),
fee: 10000,
fee: Uint::from(10000),
recipient: hex!("299A299A22F8C7397d9DB3702439069d951AeA74").into(),
deadline: U256::from(1685523099_u64),
amountIn: U256::from(10000000000000000000_u128),
amountOutMinimum: U256::from(836797564735606450550734848_u128),
sqrtPriceLimitX96: U256::ZERO,
sqrtPriceLimitX96: Uint::ZERO,
}
}

Expand All @@ -156,7 +156,7 @@ fn encode_struct_input_tokens() -> [ethabi::Token; 8] {
[
ethabi::Token::Address(input.tokenIn.0 .0.into()),
ethabi::Token::Address(input.tokenOut.0 .0.into()),
ethabi::Token::Uint(input.fee.into()),
ethabi::Token::Uint(input.fee.to::<u64>().into()),
ethabi::Token::Address(input.recipient.0 .0.into()),
ethabi::Token::Uint(ethabi::Uint::from_big_endian(&input.deadline.to_be_bytes_vec())),
ethabi::Token::Uint(ethabi::Uint::from_big_endian(&input.amountIn.to_be_bytes_vec())),
Expand All @@ -174,12 +174,12 @@ fn encode_struct_sol_values() -> [DynSolValue; 8] {
[
input.tokenIn.into(),
input.tokenOut.into(),
input.fee.into(),
input.fee.to::<u64>().into(),
input.recipient.into(),
input.deadline.into(),
input.amountIn.into(),
input.amountOutMinimum.into(),
input.sqrtPriceLimitX96.into(),
input.sqrtPriceLimitX96.to::<U256>().into(),
]
}

Expand Down
60 changes: 45 additions & 15 deletions crates/primitives/src/aliases.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
//! Type aliases for common primitive types.

use crate::{FixedBytes, Signed};
use crate::{FixedBytes, Signed, Uint};

pub use ruint::aliases::{
U0, U1, U1024, U128, U16, U160, U192, U2048, U256, U32, U320, U384, U4096, U448, U512, U64, U8,
};
pub use ruint::aliases::{U0, U1, U1024, U2048, U320, U384, U4096, U448};

macro_rules! int_aliases {
($($name:ident<$BITS:literal, $LIMBS:literal>),* $(,)?) => {$(
($($unsigned:ident, $signed:ident<$BITS:literal, $LIMBS:literal>),* $(,)?) => {$(
#[doc = concat!($BITS, "-bit [unsigned integer type][Uint], consisting of ", $LIMBS, ", 64-bit limbs.")]
pub type $unsigned = Uint<$BITS, $LIMBS>;

#[doc = concat!($BITS, "-bit [signed integer type][Signed], consisting of ", $LIMBS, ", 64-bit limbs.")]
pub type $name = Signed<$BITS, $LIMBS>;
pub type $signed = Signed<$BITS, $LIMBS>;

const _: () = assert!($LIMBS == ruint::nlimbs($BITS));
)*};
}
Expand All @@ -21,15 +23,43 @@ pub type I0 = Signed<0, 0>;
pub type I1 = Signed<1, 1>;

int_aliases! {
I8<8, 1>,
I16<16, 1>,
I32<32, 1>,
I64<64, 1>,
I128<128, 2>,
I160<160, 3>,
I192<192, 3>,
I256<256, 4>,
I512<512, 8>,
U8, I8< 8, 1>,
U16, I16< 16, 1>,
U24, I24< 24, 1>,
U32, I32< 32, 1>,
U40, I40< 40, 1>,
U48, I48< 48, 1>,
U56, I56< 56, 1>,
U64, I64< 64, 1>,

U72, I72< 72, 2>,
U80, I80< 80, 2>,
U88, I88< 88, 2>,
U96, I96< 96, 2>,
U104, I104<104, 2>,
U112, I112<112, 2>,
U120, I120<120, 2>,
U128, I128<128, 2>,

U136, I136<136, 3>,
U144, I144<144, 3>,
U152, I152<152, 3>,
U160, I160<160, 3>,
U168, I168<168, 3>,
U176, I176<176, 3>,
U184, I184<184, 3>,
U192, I192<192, 3>,

U200, I200<200, 4>,
U208, I208<208, 4>,
U216, I216<216, 4>,
U224, I224<224, 4>,
U232, I232<232, 4>,
U240, I240<240, 4>,
U248, I248<248, 4>,
U256, I256<256, 4>,

U512, I512<512, 8>,
}

macro_rules! fixed_bytes_aliases {
Expand Down
28 changes: 12 additions & 16 deletions crates/sol-macro-expander/src/expand/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ pub fn rec_expand_type(ty: &Type, crates: &ExternCrates, tokens: &mut TokenStrea
// IMPORTANT: Keep in sync with `sol-types/src/types/data_type.rs`
/// The [`expand_rust_type`] recursive implementation.
pub fn rec_expand_rust_type(ty: &Type, crates: &ExternCrates, tokens: &mut TokenStream) {
// Display sizes that match with the Rust type, otherwise we lose information
// (e.g. `uint24` displays the same as `uint32` because both use `u32`)
fn allowed_int_size(size: Option<NonZeroU16>) -> bool {
matches!(size.map_or(256, NonZeroU16::get), 8 | 16 | 32 | 64 | 128 | 256)
}

let alloy_sol_types = &crates.sol_types;
let tts = match *ty {
Type::Address(span, _) => quote_spanned! {span=> #alloy_sol_types::private::Address },
Expand All @@ -106,22 +100,24 @@ pub fn rec_expand_rust_type(ty: &Type, crates: &ExternCrates, tokens: &mut Token
let size = Literal::u16_unsuffixed(size.get());
quote_spanned! {span=> #alloy_sol_types::private::FixedBytes<#size> }
}
Type::Int(span, size) | Type::Uint(span, size) if allowed_int_size(size) => {
Type::Int(span, size) | Type::Uint(span, size) => {
let size = size.map_or(256, NonZeroU16::get);
if size <= 128 {
let name = match ty {
let primitive = matches!(size, 8 | 16 | 32 | 64 | 128);
if primitive {
let prefix = match ty {
Type::Int(..) => "i",
Type::Uint(..) => "u",
_ => unreachable!(),
};
return Ident::new(&format!("{name}{size}"), span).to_tokens(tokens);
return Ident::new(&format!("{prefix}{size}"), span).to_tokens(tokens);
}
assert_eq!(size, 256);
match ty {
Type::Int(..) => quote_spanned! {span=> #alloy_sol_types::private::I256 },
Type::Uint(..) => quote_spanned! {span=> #alloy_sol_types::private::U256 },
let prefix = match ty {
Type::Int(..) => "I",
Type::Uint(..) => "U",
_ => unreachable!(),
}
};
let name = Ident::new(&format!("{prefix}{size}"), span);
quote_spanned! {span=> #alloy_sol_types::private::primitives::aliases::#name }
}

Type::Tuple(ref tuple) => {
Expand Down Expand Up @@ -150,7 +146,7 @@ pub fn rec_expand_rust_type(ty: &Type, crates: &ExternCrates, tokens: &mut Token
},

// Exhaustive fallback to `SolType::RustType`
ref ty @ (Type::Int(..) | Type::Uint(..) | Type::Custom(_)) => {
Type::Custom(_) => {
let span = ty.span();
let ty = expand_type(ty, crates);
quote_spanned! {span=> <#ty as #alloy_sol_types::SolType>::RustType }
Expand Down
4 changes: 2 additions & 2 deletions crates/sol-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ pub mod private {
vec::Vec,
};
pub use alloy_primitives::{
bytes, keccak256, Address, Bytes, FixedBytes, Function, IntoLogData, LogData, Signed, Uint,
B256, I256, U256,
self as primitives, bytes, keccak256, Address, Bytes, FixedBytes, Function, IntoLogData,
LogData, Signed, Uint, B256, I256, U256,
};
pub use core::{
borrow::{Borrow, BorrowMut},
Expand Down
Loading