git.delta.rocks / unique-network / refs/commits / fe70dfc798ca

difftreelog

refactor decouple make_signature from constant itself

Yaroslav Bolyukin2022-11-02parent: #773312d.patch.diff
in: master

9 files changed

modifiedcrates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/solidity_interface.rs
+++ b/crates/evm-coder/procedural/src/solidity_interface.rs
@@ -721,7 +721,7 @@
 		for arg in self.args.iter().filter(|a| !a.is_special()) {
 			has_params = true;
 			let ty = &arg.ty;
-			args.extend(quote! {nameof(#ty)});
+			args.extend(quote! {nameof(<#ty>::SIGNATURE)});
 			args.extend(quote! {fixed(",")})
 		}
 
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
before · crates/evm-coder/src/abi.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of EVM RLP reader/writer1819#![allow(dead_code)]2021#[cfg(not(feature = "std"))]22use alloc::vec::Vec;23use evm_core::ExitError;24use primitive_types::{H160, U256};2526use crate::{27	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},28	types::*,29	make_signature,30	custom_signature::{SignatureUnit},31};32use crate::execution::Result;3334const ABI_ALIGNMENT: usize = 32;3536trait TypeHelper {37	/// Is type dynamic sized.38	fn is_dynamic() -> bool;3940	/// Size for type aligned to [`ABI_ALIGNMENT`].41	fn size() -> usize;42}4344/// View into RLP data, which provides method to read typed items from it45#[derive(Clone)]46pub struct AbiReader<'i> {47	buf: &'i [u8],48	subresult_offset: usize,49	offset: usize,50}51impl<'i> AbiReader<'i> {52	/// Start reading RLP buffer, assuming there is no padding bytes53	pub fn new(buf: &'i [u8]) -> Self {54		Self {55			buf,56			subresult_offset: 0,57			offset: 0,58		}59	}60	/// Start reading RLP buffer, parsing first 4 bytes as selector61	pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {62		if buf.len() < 4 {63			return Err(Error::Error(ExitError::OutOfOffset));64		}65		let mut method_id = [0; 4];66		method_id.copy_from_slice(&buf[0..4]);6768		Ok((69			method_id,70			Self {71				buf,72				subresult_offset: 4,73				offset: 4,74			},75		))76	}7778	fn read_pad<const S: usize>(79		buf: &[u8],80		offset: usize,81		pad_start: usize,82		pad_size: usize,83		block_start: usize,84		block_size: usize,85	) -> Result<[u8; S]> {86		if buf.len() - offset < ABI_ALIGNMENT {87			return Err(Error::Error(ExitError::OutOfOffset));88		}89		let mut block = [0; S];90		let is_pad_zeroed = buf[pad_start..pad_size].iter().all(|&v| v == 0);91		if !is_pad_zeroed {92			return Err(Error::Error(ExitError::InvalidRange));93		}94		block.copy_from_slice(&buf[block_start..block_size]);95		Ok(block)96	}9798	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {99		let offset = self.offset;100		self.offset += ABI_ALIGNMENT;101		Self::read_pad(102			self.buf,103			offset,104			offset,105			offset + ABI_ALIGNMENT - S,106			offset + ABI_ALIGNMENT - S,107			offset + ABI_ALIGNMENT,108		)109	}110111	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {112		let offset = self.offset;113		self.offset += ABI_ALIGNMENT;114		Self::read_pad(115			self.buf,116			offset,117			offset + S,118			offset + ABI_ALIGNMENT,119			offset,120			offset + S,121		)122	}123124	/// Read [`H160`] at current position, then advance125	pub fn address(&mut self) -> Result<H160> {126		Ok(H160(self.read_padleft()?))127	}128129	/// Read [`bool`] at current position, then advance130	pub fn bool(&mut self) -> Result<bool> {131		let data: [u8; 1] = self.read_padleft()?;132		match data[0] {133			0 => Ok(false),134			1 => Ok(true),135			_ => Err(Error::Error(ExitError::InvalidRange)),136		}137	}138139	/// Read [`[u8; 4]`] at current position, then advance140	pub fn bytes4(&mut self) -> Result<[u8; 4]> {141		self.read_padright()142	}143144	/// Read [`Vec<u8>`] at current position, then advance145	pub fn bytes(&mut self) -> Result<Vec<u8>> {146		let mut subresult = self.subresult(None)?;147		let length = subresult.uint32()? as usize;148		if subresult.buf.len() < subresult.offset + length {149			return Err(Error::Error(ExitError::OutOfOffset));150		}151		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())152	}153154	/// Read [`string`] at current position, then advance155	pub fn string(&mut self) -> Result<string> {156		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))157	}158159	/// Read [`u8`] at current position, then advance160	pub fn uint8(&mut self) -> Result<u8> {161		Ok(self.read_padleft::<1>()?[0])162	}163164	/// Read [`u32`] at current position, then advance165	pub fn uint32(&mut self) -> Result<u32> {166		Ok(u32::from_be_bytes(self.read_padleft()?))167	}168169	/// Read [`u128`] at current position, then advance170	pub fn uint128(&mut self) -> Result<u128> {171		Ok(u128::from_be_bytes(self.read_padleft()?))172	}173174	/// Read [`U256`] at current position, then advance175	pub fn uint256(&mut self) -> Result<U256> {176		let buf: [u8; 32] = self.read_padleft()?;177		Ok(U256::from_big_endian(&buf))178	}179180	/// Read [`u64`] at current position, then advance181	pub fn uint64(&mut self) -> Result<u64> {182		Ok(u64::from_be_bytes(self.read_padleft()?))183	}184185	/// Read [`usize`] at current position, then advance186	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]187	pub fn read_usize(&mut self) -> Result<usize> {188		Ok(usize::from_be_bytes(self.read_padleft()?))189	}190191	/// Slice recursive buffer, advance one word for buffer offset192	/// If `size` is [`None`] then [`Self::offset`] and [`Self::subresult_offset`] evals from [`Self::buf`].193	fn subresult(&mut self, size: Option<usize>) -> Result<AbiReader<'i>> {194		let subresult_offset = self.subresult_offset;195		let offset = if let Some(size) = size {196			self.offset += size;197			self.subresult_offset += size;198			0199		} else {200			self.uint32()? as usize201		};202203		if offset + self.subresult_offset > self.buf.len() {204			return Err(Error::Error(ExitError::InvalidRange));205		}206207		let new_offset = offset + subresult_offset;208		Ok(AbiReader {209			buf: self.buf,210			subresult_offset: new_offset,211			offset: new_offset,212		})213	}214215	/// Is this parser reached end of buffer?216	pub fn is_finished(&self) -> bool {217		self.buf.len() == self.offset218	}219}220221/// Writer for RLP encoded data222#[derive(Default)]223pub struct AbiWriter {224	static_part: Vec<u8>,225	dynamic_part: Vec<(usize, AbiWriter)>,226	had_call: bool,227	is_dynamic: bool,228}229impl AbiWriter {230	/// Initialize internal buffers for output data, assuming no padding required231	pub fn new() -> Self {232		Self::default()233	}234235	/// Initialize internal buffers with data size236	pub fn new_dynamic(is_dynamic: bool) -> Self {237		Self {238			is_dynamic,239			..Default::default()240		}241	}242	/// Initialize internal buffers, inserting method selector at beginning243	pub fn new_call(method_id: u32) -> Self {244		let mut val = Self::new();245		val.static_part.extend(&method_id.to_be_bytes());246		val.had_call = true;247		val248	}249250	fn write_padleft(&mut self, block: &[u8]) {251		assert!(block.len() <= ABI_ALIGNMENT);252		self.static_part253			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);254		self.static_part.extend(block);255	}256257	fn write_padright(&mut self, block: &[u8]) {258		assert!(block.len() <= ABI_ALIGNMENT);259		self.static_part.extend(block);260		self.static_part261			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);262	}263264	/// Write [`H160`] to end of buffer265	pub fn address(&mut self, address: &H160) {266		self.write_padleft(&address.0)267	}268269	/// Write [`bool`] to end of buffer270	pub fn bool(&mut self, value: &bool) {271		self.write_padleft(&[if *value { 1 } else { 0 }])272	}273274	/// Write [`u8`] to end of buffer275	pub fn uint8(&mut self, value: &u8) {276		self.write_padleft(&[*value])277	}278279	/// Write [`u32`] to end of buffer280	pub fn uint32(&mut self, value: &u32) {281		self.write_padleft(&u32::to_be_bytes(*value))282	}283284	/// Write [`u128`] to end of buffer285	pub fn uint128(&mut self, value: &u128) {286		self.write_padleft(&u128::to_be_bytes(*value))287	}288289	/// Write [`U256`] to end of buffer290	pub fn uint256(&mut self, value: &U256) {291		let mut out = [0; 32];292		value.to_big_endian(&mut out);293		self.write_padleft(&out)294	}295296	/// Write [`usize`] to end of buffer297	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]298	pub fn write_usize(&mut self, value: &usize) {299		self.write_padleft(&usize::to_be_bytes(*value))300	}301302	/// Append recursive data, writing pending offset at end of buffer303	pub fn write_subresult(&mut self, result: Self) {304		self.dynamic_part.push((self.static_part.len(), result));305		// Empty block, to be filled later306		self.write_padleft(&[]);307	}308309	fn memory(&mut self, value: &[u8]) {310		let mut sub = Self::new();311		sub.uint32(&(value.len() as u32));312		for chunk in value.chunks(ABI_ALIGNMENT) {313			sub.write_padright(chunk);314		}315		self.write_subresult(sub);316	}317318	/// Append recursive [`str`] at end of buffer319	pub fn string(&mut self, value: &str) {320		self.memory(value.as_bytes())321	}322323	/// Append recursive [`[u8]`] at end of buffer324	pub fn bytes(&mut self, value: &[u8]) {325		self.memory(value)326	}327328	/// Finish writer, concatenating all internal buffers329	pub fn finish(mut self) -> Vec<u8> {330		for (static_offset, part) in self.dynamic_part {331			let part_offset = self.static_part.len()332				- if self.had_call { 4 } else { 0 }333				- if self.is_dynamic { ABI_ALIGNMENT } else { 0 };334335			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);336			let start = static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len();337			let stop = static_offset + ABI_ALIGNMENT;338			self.static_part[start..stop].copy_from_slice(&encoded_dynamic_offset);339			self.static_part.extend(part.finish())340		}341		self.static_part342	}343}344345/// [`AbiReader`] implements reading of many types.346pub trait AbiRead {347	/// Read item from current position, advanding decoder348	fn abi_read(reader: &mut AbiReader) -> Result<Self>349	where350		Self: Sized;351}352353macro_rules! impl_abi_readable {354	($ty:ty, $method:ident, $dynamic:literal) => {355		impl sealed::CanBePlacedInVec for $ty {}356357		impl TypeHelper for $ty {358			fn is_dynamic() -> bool {359				$dynamic360			}361362			fn size() -> usize {363				ABI_ALIGNMENT364			}365		}366367		impl AbiRead for $ty {368			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {369				reader.$method()370			}371		}372	};373}374375impl_abi_readable!(bool, bool, false);376impl_abi_readable!(uint32, uint32, false);377impl_abi_readable!(uint64, uint64, false);378impl_abi_readable!(uint128, uint128, false);379impl_abi_readable!(uint256, uint256, false);380impl_abi_readable!(bytes4, bytes4, false);381impl_abi_readable!(address, address, false);382impl_abi_readable!(string, string, true);383384impl TypeHelper for uint8 {385	fn is_dynamic() -> bool {386		false387	}388	fn size() -> usize {389		ABI_ALIGNMENT390	}391}392impl AbiRead for uint8 {393	fn abi_read(reader: &mut AbiReader) -> Result<uint8> {394		reader.uint8()395	}396}397398impl TypeHelper for bytes {399	fn is_dynamic() -> bool {400		true401	}402	fn size() -> usize {403		ABI_ALIGNMENT404	}405}406impl AbiRead for bytes {407	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {408		Ok(bytes(reader.bytes()?))409	}410}411412mod sealed {413	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead414	pub trait CanBePlacedInVec {}415}416417impl<R: AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {418	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {419		let mut sub = reader.subresult(None)?;420		let size = sub.uint32()? as usize;421		sub.subresult_offset = sub.offset;422		let mut out = Vec::with_capacity(size);423		for _ in 0..size {424			out.push(<R>::abi_read(&mut sub)?);425		}426		Ok(out)427	}428}429430impl<R: Signature> Signature for Vec<R> {431	const SIGNATURE: SignatureUnit = make_signature!(new nameof(R) fixed("[]"));432}433434impl sealed::CanBePlacedInVec for EthCrossAccount {}435436impl TypeHelper for EthCrossAccount {437	fn is_dynamic() -> bool {438		address::is_dynamic() || uint256::is_dynamic()439	}440441	fn size() -> usize {442		<address as TypeHelper>::size() + <uint256 as TypeHelper>::size()443	}444}445446impl AbiRead for EthCrossAccount {447	fn abi_read(reader: &mut AbiReader) -> Result<EthCrossAccount> {448		let size = if !EthCrossAccount::is_dynamic() {449			Some(<EthCrossAccount as TypeHelper>::size())450		} else {451			None452		};453		let mut subresult = reader.subresult(size)?;454		let eth = <address>::abi_read(&mut subresult)?;455		let sub = <uint256>::abi_read(&mut subresult)?;456457		Ok(EthCrossAccount { eth, sub })458	}459}460461impl AbiWrite for EthCrossAccount {462	fn abi_write(&self, writer: &mut AbiWriter) {463		self.eth.abi_write(writer);464		self.sub.abi_write(writer);465	}466}467468macro_rules! impl_tuples {469	($($ident:ident)+) => {470		impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+)471		where472			$(473				$ident: TypeHelper,474			)+475		{476			fn is_dynamic() -> bool {477				false478				$(479					|| <$ident>::is_dynamic()480				)*481			}482483			fn size() -> usize {484				0 $(+ <$ident>::size())+485			}486		}487488		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}489490		impl<$($ident),+> AbiRead for ($($ident,)+)491		where492			$($ident: AbiRead,)+493			($($ident,)+): TypeHelper,494		{495			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {496				let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };497				let mut subresult = reader.subresult(size)?;498				Ok((499					$(<$ident>::abi_read(&mut subresult)?,)+500				))501			}502		}503504		#[allow(non_snake_case)]505		impl<$($ident),+> AbiWrite for ($($ident,)+)506		where507			$($ident: AbiWrite,)+508		{509			fn abi_write(&self, writer: &mut AbiWriter) {510				let ($($ident,)+) = self;511				if writer.is_dynamic {512					let mut sub = AbiWriter::new();513					$($ident.abi_write(&mut sub);)+514					writer.write_subresult(sub);515				} else {516					$($ident.abi_write(writer);)+517				}518			}519		}520521		impl<$($ident),+> Signature for ($($ident,)+)522		where523		$($ident: Signature,)+524		{525			const SIGNATURE: SignatureUnit = make_signature!(526				new fixed("(")527				$(nameof($ident) fixed(","))+528				shift_left(1)529				fixed(")")530			);531		}532	};533}534535impl_tuples! {A}536impl_tuples! {A B}537impl_tuples! {A B C}538impl_tuples! {A B C D}539impl_tuples! {A B C D E}540impl_tuples! {A B C D E F}541impl_tuples! {A B C D E F G}542impl_tuples! {A B C D E F G H}543impl_tuples! {A B C D E F G H I}544impl_tuples! {A B C D E F G H I J}545546/// For questions about inability to provide custom implementations,547/// see [`AbiRead`]548pub trait AbiWrite {549	/// Write value to end of specified encoder550	fn abi_write(&self, writer: &mut AbiWriter);551	/// Specialization for [`crate::solidity_interface`] implementation,552	/// see comment in `impl AbiWrite for ResultWithPostInfo`553	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {554		let mut writer = AbiWriter::new();555		self.abi_write(&mut writer);556		Ok(writer.into())557	}558}559560/// This particular AbiWrite implementation should be split to another trait,561/// which only implements `to_result`, but due to lack of specialization feature562/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,563/// so here we abusing default trait methods for it564impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {565	fn abi_write(&self, _writer: &mut AbiWriter) {566		debug_assert!(false, "shouldn't be called, see comment")567	}568	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {569		match self {570			Ok(v) => Ok(WithPostDispatchInfo {571				post_info: v.post_info.clone(),572				data: {573					let mut out = AbiWriter::new();574					v.data.abi_write(&mut out);575					out576				},577			}),578			Err(e) => Err(e.clone()),579		}580	}581}582583macro_rules! impl_abi_writeable {584	($ty:ty, $method:ident) => {585		impl AbiWrite for $ty {586			fn abi_write(&self, writer: &mut AbiWriter) {587				writer.$method(&self)588			}589		}590	};591}592593impl_abi_writeable!(u8, uint8);594impl_abi_writeable!(u32, uint32);595impl_abi_writeable!(u128, uint128);596impl_abi_writeable!(U256, uint256);597impl_abi_writeable!(H160, address);598impl_abi_writeable!(bool, bool);599impl_abi_writeable!(&str, string);600601impl AbiWrite for string {602	fn abi_write(&self, writer: &mut AbiWriter) {603		writer.string(self)604	}605}606607impl AbiWrite for bytes {608	fn abi_write(&self, writer: &mut AbiWriter) {609		writer.bytes(self.0.as_slice())610	}611}612613impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {614	fn abi_write(&self, writer: &mut AbiWriter) {615		let is_dynamic = T::is_dynamic();616		let mut sub = if is_dynamic {617			AbiWriter::new_dynamic(is_dynamic)618		} else {619			AbiWriter::new()620		};621622		// Write items count623		(self.len() as u32).abi_write(&mut sub);624625		for item in self {626			item.abi_write(&mut sub);627		}628		writer.write_subresult(sub);629	}630}631632impl AbiWrite for () {633	fn abi_write(&self, _writer: &mut AbiWriter) {}634}635636/// Helper macros to parse reader into variables637#[deprecated]638#[macro_export]639macro_rules! abi_decode {640	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {641		$(642			let $name = $reader.$typ()?;643		)+644	}645}646647/// Helper macros to construct RLP-encoded buffer648#[deprecated]649#[macro_export]650macro_rules! abi_encode {651	($($typ:ident($value:expr)),* $(,)?) => {{652		#[allow(unused_mut)]653		let mut writer = ::evm_coder::abi::AbiWriter::new();654		$(655			writer.$typ($value);656		)*657		writer658	}};659	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{660		#[allow(unused_mut)]661		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);662		$(663			writer.$typ($value);664		)*665		writer666	}}667}668669#[cfg(test)]670pub mod test {671	use crate::{672		abi::{AbiRead, AbiWrite},673		types::*,674	};675676	use super::{AbiReader, AbiWriter};677	use hex_literal::hex;678	use primitive_types::{H160, U256};679	use concat_idents::concat_idents;680681	macro_rules! test_impl {682		($name:ident, $type:ty, $function_identifier:expr, $decoded_data:expr, $encoded_data:expr) => {683			concat_idents!(test_name = encode_decode_, $name {684				#[test]685				fn test_name() {686					let function_identifier: u32 = $function_identifier;687					let decoded_data = $decoded_data;688					let encoded_data = $encoded_data;689690					let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();691					assert_eq!(call, u32::to_be_bytes(function_identifier));692					let data = <$type>::abi_read(&mut decoder).unwrap();693					assert_eq!(data, decoded_data);694695					let mut writer = AbiWriter::new_call(function_identifier);696					decoded_data.abi_write(&mut writer);697					let ed = writer.finish();698					similar_asserts::assert_eq!(encoded_data, ed.as_slice());699				}700			});701		};702	}703704	macro_rules! test_impl_uint {705		($type:ident) => {706			test_impl!(707				$type,708				$type,709				0xdeadbeef,710				255 as $type,711				&hex!(712					"713						deadbeef714						00000000000000000000000000000000000000000000000000000000000000ff715					"716				)717			);718		};719	}720721	test_impl_uint!(uint8);722	test_impl_uint!(uint32);723	test_impl_uint!(uint128);724725	test_impl!(726		uint256,727		uint256,728		0xdeadbeef,729		U256([255, 0, 0, 0]),730		&hex!(731			"732				deadbeef733				00000000000000000000000000000000000000000000000000000000000000ff734			"735		)736	);737738	test_impl!(739		vec_tuple_address_uint256,740		Vec<(address, uint256)>,741		0x1ACF2D55,742		vec![743			(744				H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),745				U256([10, 0, 0, 0]),746			),747			(748				H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),749				U256([20, 0, 0, 0]),750			),751			(752				H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),753				U256([30, 0, 0, 0]),754			),755		],756		&hex!(757			"758				1ACF2D55759				0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]760				0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]761762				0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address763				000000000000000000000000000000000000000000000000000000000000000A // uint256764765				000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address766				0000000000000000000000000000000000000000000000000000000000000014 // uint256767768				0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address769				000000000000000000000000000000000000000000000000000000000000001E // uint256770			"771		)772	);773774	test_impl!(775		vec_tuple_uint256_string,776		Vec<(uint256, string)>,777		0xdeadbeef,778		vec![779			(1.into(), "Test URI 0".to_string()),780			(11.into(), "Test URI 1".to_string()),781			(12.into(), "Test URI 2".to_string()),782		],783		&hex!(784			"785				deadbeef786				0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]787				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]788789				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem790				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem791				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem792793				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60794				0000000000000000000000000000000000000000000000000000000000000040 // offset of string795				000000000000000000000000000000000000000000000000000000000000000a // size of string796				5465737420555249203000000000000000000000000000000000000000000000 // string797798				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0799				0000000000000000000000000000000000000000000000000000000000000040 // offset of string800				000000000000000000000000000000000000000000000000000000000000000a // size of string801				5465737420555249203100000000000000000000000000000000000000000000 // string802803				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160804				0000000000000000000000000000000000000000000000000000000000000040 // offset of string805				000000000000000000000000000000000000000000000000000000000000000a // size of string806				5465737420555249203200000000000000000000000000000000000000000000 // string807			"808		)809	);810811	#[test]812	fn dynamic_after_static() {813		let mut encoder = AbiWriter::new();814		encoder.bool(&true);815		encoder.string("test");816		let encoded = encoder.finish();817818		let mut encoder = AbiWriter::new();819		encoder.bool(&true);820		// Offset to subresult821		encoder.uint32(&(32 * 2));822		// Len of "test"823		encoder.uint32(&4);824		encoder.write_padright(&[b't', b'e', b's', b't']);825		let alternative_encoded = encoder.finish();826827		assert_eq!(encoded, alternative_encoded);828829		let mut decoder = AbiReader::new(&encoded);830		assert!(decoder.bool().unwrap());831		assert_eq!(decoder.string().unwrap(), "test");832	}833834	#[test]835	fn mint_sample() {836		let (call, mut decoder) = AbiReader::new_call(&hex!(837			"838				50bb4e7f839				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374840				0000000000000000000000000000000000000000000000000000000000000001841				0000000000000000000000000000000000000000000000000000000000000060842				0000000000000000000000000000000000000000000000000000000000000008843				5465737420555249000000000000000000000000000000000000000000000000844			"845		))846		.unwrap();847		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));848		assert_eq!(849			format!("{:?}", decoder.address().unwrap()),850			"0xad2c0954693c2b5404b7e50967d3481bea432374"851		);852		assert_eq!(decoder.uint32().unwrap(), 1);853		assert_eq!(decoder.string().unwrap(), "Test URI");854	}855856	#[test]857	fn parse_vec_with_dynamic_type() {858		let decoded_data = (859			0x36543006,860			vec![861				(1.into(), "Test URI 0".to_string()),862				(11.into(), "Test URI 1".to_string()),863				(12.into(), "Test URI 2".to_string()),864			],865		);866867		let encoded_data = &hex!(868			"869				36543006870				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address871				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]872				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]873874				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem875				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem876				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem877878				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60879				0000000000000000000000000000000000000000000000000000000000000040 // offset of string880				000000000000000000000000000000000000000000000000000000000000000a // size of string881				5465737420555249203000000000000000000000000000000000000000000000 // string882883				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0884				0000000000000000000000000000000000000000000000000000000000000040 // offset of string885				000000000000000000000000000000000000000000000000000000000000000a // size of string886				5465737420555249203100000000000000000000000000000000000000000000 // string887888				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160889				0000000000000000000000000000000000000000000000000000000000000040 // offset of string890				000000000000000000000000000000000000000000000000000000000000000a // size of string891				5465737420555249203200000000000000000000000000000000000000000000 // string892			"893		);894895		let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();896		assert_eq!(call, u32::to_be_bytes(decoded_data.0));897		let address = decoder.address().unwrap();898		let data = <Vec<(uint256, string)>>::abi_read(&mut decoder).unwrap();899		assert_eq!(data, decoded_data.1);900901		let mut writer = AbiWriter::new_call(decoded_data.0);902		address.abi_write(&mut writer);903		decoded_data.1.abi_write(&mut writer);904		let ed = writer.finish();905		similar_asserts::assert_eq!(encoded_data, ed.as_slice());906	}907}
after · crates/evm-coder/src/abi.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of EVM RLP reader/writer1819#![allow(dead_code)]2021#[cfg(not(feature = "std"))]22use alloc::vec::Vec;23use evm_core::ExitError;24use primitive_types::{H160, U256};2526use crate::{27	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},28	types::*,29	make_signature,30	custom_signature::{SignatureUnit},31};32use crate::execution::Result;3334const ABI_ALIGNMENT: usize = 32;3536trait TypeHelper {37	/// Is type dynamic sized.38	fn is_dynamic() -> bool;3940	/// Size for type aligned to [`ABI_ALIGNMENT`].41	fn size() -> usize;42}4344/// View into RLP data, which provides method to read typed items from it45#[derive(Clone)]46pub struct AbiReader<'i> {47	buf: &'i [u8],48	subresult_offset: usize,49	offset: usize,50}51impl<'i> AbiReader<'i> {52	/// Start reading RLP buffer, assuming there is no padding bytes53	pub fn new(buf: &'i [u8]) -> Self {54		Self {55			buf,56			subresult_offset: 0,57			offset: 0,58		}59	}60	/// Start reading RLP buffer, parsing first 4 bytes as selector61	pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {62		if buf.len() < 4 {63			return Err(Error::Error(ExitError::OutOfOffset));64		}65		let mut method_id = [0; 4];66		method_id.copy_from_slice(&buf[0..4]);6768		Ok((69			method_id,70			Self {71				buf,72				subresult_offset: 4,73				offset: 4,74			},75		))76	}7778	fn read_pad<const S: usize>(79		buf: &[u8],80		offset: usize,81		pad_start: usize,82		pad_size: usize,83		block_start: usize,84		block_size: usize,85	) -> Result<[u8; S]> {86		if buf.len() - offset < ABI_ALIGNMENT {87			return Err(Error::Error(ExitError::OutOfOffset));88		}89		let mut block = [0; S];90		let is_pad_zeroed = buf[pad_start..pad_size].iter().all(|&v| v == 0);91		if !is_pad_zeroed {92			return Err(Error::Error(ExitError::InvalidRange));93		}94		block.copy_from_slice(&buf[block_start..block_size]);95		Ok(block)96	}9798	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {99		let offset = self.offset;100		self.offset += ABI_ALIGNMENT;101		Self::read_pad(102			self.buf,103			offset,104			offset,105			offset + ABI_ALIGNMENT - S,106			offset + ABI_ALIGNMENT - S,107			offset + ABI_ALIGNMENT,108		)109	}110111	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {112		let offset = self.offset;113		self.offset += ABI_ALIGNMENT;114		Self::read_pad(115			self.buf,116			offset,117			offset + S,118			offset + ABI_ALIGNMENT,119			offset,120			offset + S,121		)122	}123124	/// Read [`H160`] at current position, then advance125	pub fn address(&mut self) -> Result<H160> {126		Ok(H160(self.read_padleft()?))127	}128129	/// Read [`bool`] at current position, then advance130	pub fn bool(&mut self) -> Result<bool> {131		let data: [u8; 1] = self.read_padleft()?;132		match data[0] {133			0 => Ok(false),134			1 => Ok(true),135			_ => Err(Error::Error(ExitError::InvalidRange)),136		}137	}138139	/// Read [`[u8; 4]`] at current position, then advance140	pub fn bytes4(&mut self) -> Result<[u8; 4]> {141		self.read_padright()142	}143144	/// Read [`Vec<u8>`] at current position, then advance145	pub fn bytes(&mut self) -> Result<Vec<u8>> {146		let mut subresult = self.subresult(None)?;147		let length = subresult.uint32()? as usize;148		if subresult.buf.len() < subresult.offset + length {149			return Err(Error::Error(ExitError::OutOfOffset));150		}151		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())152	}153154	/// Read [`string`] at current position, then advance155	pub fn string(&mut self) -> Result<string> {156		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))157	}158159	/// Read [`u8`] at current position, then advance160	pub fn uint8(&mut self) -> Result<u8> {161		Ok(self.read_padleft::<1>()?[0])162	}163164	/// Read [`u32`] at current position, then advance165	pub fn uint32(&mut self) -> Result<u32> {166		Ok(u32::from_be_bytes(self.read_padleft()?))167	}168169	/// Read [`u128`] at current position, then advance170	pub fn uint128(&mut self) -> Result<u128> {171		Ok(u128::from_be_bytes(self.read_padleft()?))172	}173174	/// Read [`U256`] at current position, then advance175	pub fn uint256(&mut self) -> Result<U256> {176		let buf: [u8; 32] = self.read_padleft()?;177		Ok(U256::from_big_endian(&buf))178	}179180	/// Read [`u64`] at current position, then advance181	pub fn uint64(&mut self) -> Result<u64> {182		Ok(u64::from_be_bytes(self.read_padleft()?))183	}184185	/// Read [`usize`] at current position, then advance186	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]187	pub fn read_usize(&mut self) -> Result<usize> {188		Ok(usize::from_be_bytes(self.read_padleft()?))189	}190191	/// Slice recursive buffer, advance one word for buffer offset192	/// If `size` is [`None`] then [`Self::offset`] and [`Self::subresult_offset`] evals from [`Self::buf`].193	fn subresult(&mut self, size: Option<usize>) -> Result<AbiReader<'i>> {194		let subresult_offset = self.subresult_offset;195		let offset = if let Some(size) = size {196			self.offset += size;197			self.subresult_offset += size;198			0199		} else {200			self.uint32()? as usize201		};202203		if offset + self.subresult_offset > self.buf.len() {204			return Err(Error::Error(ExitError::InvalidRange));205		}206207		let new_offset = offset + subresult_offset;208		Ok(AbiReader {209			buf: self.buf,210			subresult_offset: new_offset,211			offset: new_offset,212		})213	}214215	/// Is this parser reached end of buffer?216	pub fn is_finished(&self) -> bool {217		self.buf.len() == self.offset218	}219}220221/// Writer for RLP encoded data222#[derive(Default)]223pub struct AbiWriter {224	static_part: Vec<u8>,225	dynamic_part: Vec<(usize, AbiWriter)>,226	had_call: bool,227	is_dynamic: bool,228}229impl AbiWriter {230	/// Initialize internal buffers for output data, assuming no padding required231	pub fn new() -> Self {232		Self::default()233	}234235	/// Initialize internal buffers with data size236	pub fn new_dynamic(is_dynamic: bool) -> Self {237		Self {238			is_dynamic,239			..Default::default()240		}241	}242	/// Initialize internal buffers, inserting method selector at beginning243	pub fn new_call(method_id: u32) -> Self {244		let mut val = Self::new();245		val.static_part.extend(&method_id.to_be_bytes());246		val.had_call = true;247		val248	}249250	fn write_padleft(&mut self, block: &[u8]) {251		assert!(block.len() <= ABI_ALIGNMENT);252		self.static_part253			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);254		self.static_part.extend(block);255	}256257	fn write_padright(&mut self, block: &[u8]) {258		assert!(block.len() <= ABI_ALIGNMENT);259		self.static_part.extend(block);260		self.static_part261			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);262	}263264	/// Write [`H160`] to end of buffer265	pub fn address(&mut self, address: &H160) {266		self.write_padleft(&address.0)267	}268269	/// Write [`bool`] to end of buffer270	pub fn bool(&mut self, value: &bool) {271		self.write_padleft(&[if *value { 1 } else { 0 }])272	}273274	/// Write [`u8`] to end of buffer275	pub fn uint8(&mut self, value: &u8) {276		self.write_padleft(&[*value])277	}278279	/// Write [`u32`] to end of buffer280	pub fn uint32(&mut self, value: &u32) {281		self.write_padleft(&u32::to_be_bytes(*value))282	}283284	/// Write [`u128`] to end of buffer285	pub fn uint128(&mut self, value: &u128) {286		self.write_padleft(&u128::to_be_bytes(*value))287	}288289	/// Write [`U256`] to end of buffer290	pub fn uint256(&mut self, value: &U256) {291		let mut out = [0; 32];292		value.to_big_endian(&mut out);293		self.write_padleft(&out)294	}295296	/// Write [`usize`] to end of buffer297	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]298	pub fn write_usize(&mut self, value: &usize) {299		self.write_padleft(&usize::to_be_bytes(*value))300	}301302	/// Append recursive data, writing pending offset at end of buffer303	pub fn write_subresult(&mut self, result: Self) {304		self.dynamic_part.push((self.static_part.len(), result));305		// Empty block, to be filled later306		self.write_padleft(&[]);307	}308309	fn memory(&mut self, value: &[u8]) {310		let mut sub = Self::new();311		sub.uint32(&(value.len() as u32));312		for chunk in value.chunks(ABI_ALIGNMENT) {313			sub.write_padright(chunk);314		}315		self.write_subresult(sub);316	}317318	/// Append recursive [`str`] at end of buffer319	pub fn string(&mut self, value: &str) {320		self.memory(value.as_bytes())321	}322323	/// Append recursive [`[u8]`] at end of buffer324	pub fn bytes(&mut self, value: &[u8]) {325		self.memory(value)326	}327328	/// Finish writer, concatenating all internal buffers329	pub fn finish(mut self) -> Vec<u8> {330		for (static_offset, part) in self.dynamic_part {331			let part_offset = self.static_part.len()332				- if self.had_call { 4 } else { 0 }333				- if self.is_dynamic { ABI_ALIGNMENT } else { 0 };334335			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);336			let start = static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len();337			let stop = static_offset + ABI_ALIGNMENT;338			self.static_part[start..stop].copy_from_slice(&encoded_dynamic_offset);339			self.static_part.extend(part.finish())340		}341		self.static_part342	}343}344345/// [`AbiReader`] implements reading of many types.346pub trait AbiRead {347	/// Read item from current position, advanding decoder348	fn abi_read(reader: &mut AbiReader) -> Result<Self>349	where350		Self: Sized;351}352353macro_rules! impl_abi_readable {354	($ty:ty, $method:ident, $dynamic:literal) => {355		impl sealed::CanBePlacedInVec for $ty {}356357		impl TypeHelper for $ty {358			fn is_dynamic() -> bool {359				$dynamic360			}361362			fn size() -> usize {363				ABI_ALIGNMENT364			}365		}366367		impl AbiRead for $ty {368			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {369				reader.$method()370			}371		}372	};373}374375impl_abi_readable!(bool, bool, false);376impl_abi_readable!(uint32, uint32, false);377impl_abi_readable!(uint64, uint64, false);378impl_abi_readable!(uint128, uint128, false);379impl_abi_readable!(uint256, uint256, false);380impl_abi_readable!(bytes4, bytes4, false);381impl_abi_readable!(address, address, false);382impl_abi_readable!(string, string, true);383384impl TypeHelper for uint8 {385	fn is_dynamic() -> bool {386		false387	}388	fn size() -> usize {389		ABI_ALIGNMENT390	}391}392impl AbiRead for uint8 {393	fn abi_read(reader: &mut AbiReader) -> Result<uint8> {394		reader.uint8()395	}396}397398impl TypeHelper for bytes {399	fn is_dynamic() -> bool {400		true401	}402	fn size() -> usize {403		ABI_ALIGNMENT404	}405}406impl AbiRead for bytes {407	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {408		Ok(bytes(reader.bytes()?))409	}410}411412mod sealed {413	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead414	pub trait CanBePlacedInVec {}415}416417impl<R: AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {418	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {419		let mut sub = reader.subresult(None)?;420		let size = sub.uint32()? as usize;421		sub.subresult_offset = sub.offset;422		let mut out = Vec::with_capacity(size);423		for _ in 0..size {424			out.push(<R>::abi_read(&mut sub)?);425		}426		Ok(out)427	}428}429430impl<R: Signature> Signature for Vec<R> {431	const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]"));432}433434impl sealed::CanBePlacedInVec for EthCrossAccount {}435436impl TypeHelper for EthCrossAccount {437	fn is_dynamic() -> bool {438		address::is_dynamic() || uint256::is_dynamic()439	}440441	fn size() -> usize {442		<address as TypeHelper>::size() + <uint256 as TypeHelper>::size()443	}444}445446impl AbiRead for EthCrossAccount {447	fn abi_read(reader: &mut AbiReader) -> Result<EthCrossAccount> {448		let size = if !EthCrossAccount::is_dynamic() {449			Some(<EthCrossAccount as TypeHelper>::size())450		} else {451			None452		};453		let mut subresult = reader.subresult(size)?;454		let eth = <address>::abi_read(&mut subresult)?;455		let sub = <uint256>::abi_read(&mut subresult)?;456457		Ok(EthCrossAccount { eth, sub })458	}459}460461impl AbiWrite for EthCrossAccount {462	fn abi_write(&self, writer: &mut AbiWriter) {463		self.eth.abi_write(writer);464		self.sub.abi_write(writer);465	}466}467468macro_rules! impl_tuples {469	($($ident:ident)+) => {470		impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+)471		where472			$(473				$ident: TypeHelper,474			)+475		{476			fn is_dynamic() -> bool {477				false478				$(479					|| <$ident>::is_dynamic()480				)*481			}482483			fn size() -> usize {484				0 $(+ <$ident>::size())+485			}486		}487488		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}489490		impl<$($ident),+> AbiRead for ($($ident,)+)491		where492			$($ident: AbiRead,)+493			($($ident,)+): TypeHelper,494		{495			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {496				let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };497				let mut subresult = reader.subresult(size)?;498				Ok((499					$(<$ident>::abi_read(&mut subresult)?,)+500				))501			}502		}503504		#[allow(non_snake_case)]505		impl<$($ident),+> AbiWrite for ($($ident,)+)506		where507			$($ident: AbiWrite,)+508		{509			fn abi_write(&self, writer: &mut AbiWriter) {510				let ($($ident,)+) = self;511				if writer.is_dynamic {512					let mut sub = AbiWriter::new();513					$($ident.abi_write(&mut sub);)+514					writer.write_subresult(sub);515				} else {516					$($ident.abi_write(writer);)+517				}518			}519		}520521		impl<$($ident),+> Signature for ($($ident,)+)522		where523		$($ident: Signature,)+524		{525			const SIGNATURE: SignatureUnit = make_signature!(526				new fixed("(")527				$(nameof(<$ident>::SIGNATURE) fixed(","))+528				shift_left(1)529				fixed(")")530			);531		}532	};533}534535impl_tuples! {A}536impl_tuples! {A B}537impl_tuples! {A B C}538impl_tuples! {A B C D}539impl_tuples! {A B C D E}540impl_tuples! {A B C D E F}541impl_tuples! {A B C D E F G}542impl_tuples! {A B C D E F G H}543impl_tuples! {A B C D E F G H I}544impl_tuples! {A B C D E F G H I J}545546/// For questions about inability to provide custom implementations,547/// see [`AbiRead`]548pub trait AbiWrite {549	/// Write value to end of specified encoder550	fn abi_write(&self, writer: &mut AbiWriter);551	/// Specialization for [`crate::solidity_interface`] implementation,552	/// see comment in `impl AbiWrite for ResultWithPostInfo`553	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {554		let mut writer = AbiWriter::new();555		self.abi_write(&mut writer);556		Ok(writer.into())557	}558}559560/// This particular AbiWrite implementation should be split to another trait,561/// which only implements `to_result`, but due to lack of specialization feature562/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,563/// so here we abusing default trait methods for it564impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {565	fn abi_write(&self, _writer: &mut AbiWriter) {566		debug_assert!(false, "shouldn't be called, see comment")567	}568	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {569		match self {570			Ok(v) => Ok(WithPostDispatchInfo {571				post_info: v.post_info.clone(),572				data: {573					let mut out = AbiWriter::new();574					v.data.abi_write(&mut out);575					out576				},577			}),578			Err(e) => Err(e.clone()),579		}580	}581}582583macro_rules! impl_abi_writeable {584	($ty:ty, $method:ident) => {585		impl AbiWrite for $ty {586			fn abi_write(&self, writer: &mut AbiWriter) {587				writer.$method(&self)588			}589		}590	};591}592593impl_abi_writeable!(u8, uint8);594impl_abi_writeable!(u32, uint32);595impl_abi_writeable!(u128, uint128);596impl_abi_writeable!(U256, uint256);597impl_abi_writeable!(H160, address);598impl_abi_writeable!(bool, bool);599impl_abi_writeable!(&str, string);600601impl AbiWrite for string {602	fn abi_write(&self, writer: &mut AbiWriter) {603		writer.string(self)604	}605}606607impl AbiWrite for bytes {608	fn abi_write(&self, writer: &mut AbiWriter) {609		writer.bytes(self.0.as_slice())610	}611}612613impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {614	fn abi_write(&self, writer: &mut AbiWriter) {615		let is_dynamic = T::is_dynamic();616		let mut sub = if is_dynamic {617			AbiWriter::new_dynamic(is_dynamic)618		} else {619			AbiWriter::new()620		};621622		// Write items count623		(self.len() as u32).abi_write(&mut sub);624625		for item in self {626			item.abi_write(&mut sub);627		}628		writer.write_subresult(sub);629	}630}631632impl AbiWrite for () {633	fn abi_write(&self, _writer: &mut AbiWriter) {}634}635636/// Helper macros to parse reader into variables637#[deprecated]638#[macro_export]639macro_rules! abi_decode {640	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {641		$(642			let $name = $reader.$typ()?;643		)+644	}645}646647/// Helper macros to construct RLP-encoded buffer648#[deprecated]649#[macro_export]650macro_rules! abi_encode {651	($($typ:ident($value:expr)),* $(,)?) => {{652		#[allow(unused_mut)]653		let mut writer = ::evm_coder::abi::AbiWriter::new();654		$(655			writer.$typ($value);656		)*657		writer658	}};659	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{660		#[allow(unused_mut)]661		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);662		$(663			writer.$typ($value);664		)*665		writer666	}}667}668669#[cfg(test)]670pub mod test {671	use crate::{672		abi::{AbiRead, AbiWrite},673		types::*,674	};675676	use super::{AbiReader, AbiWriter};677	use hex_literal::hex;678	use primitive_types::{H160, U256};679	use concat_idents::concat_idents;680681	macro_rules! test_impl {682		($name:ident, $type:ty, $function_identifier:expr, $decoded_data:expr, $encoded_data:expr) => {683			concat_idents!(test_name = encode_decode_, $name {684				#[test]685				fn test_name() {686					let function_identifier: u32 = $function_identifier;687					let decoded_data = $decoded_data;688					let encoded_data = $encoded_data;689690					let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();691					assert_eq!(call, u32::to_be_bytes(function_identifier));692					let data = <$type>::abi_read(&mut decoder).unwrap();693					assert_eq!(data, decoded_data);694695					let mut writer = AbiWriter::new_call(function_identifier);696					decoded_data.abi_write(&mut writer);697					let ed = writer.finish();698					similar_asserts::assert_eq!(encoded_data, ed.as_slice());699				}700			});701		};702	}703704	macro_rules! test_impl_uint {705		($type:ident) => {706			test_impl!(707				$type,708				$type,709				0xdeadbeef,710				255 as $type,711				&hex!(712					"713						deadbeef714						00000000000000000000000000000000000000000000000000000000000000ff715					"716				)717			);718		};719	}720721	test_impl_uint!(uint8);722	test_impl_uint!(uint32);723	test_impl_uint!(uint128);724725	test_impl!(726		uint256,727		uint256,728		0xdeadbeef,729		U256([255, 0, 0, 0]),730		&hex!(731			"732				deadbeef733				00000000000000000000000000000000000000000000000000000000000000ff734			"735		)736	);737738	test_impl!(739		vec_tuple_address_uint256,740		Vec<(address, uint256)>,741		0x1ACF2D55,742		vec![743			(744				H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),745				U256([10, 0, 0, 0]),746			),747			(748				H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),749				U256([20, 0, 0, 0]),750			),751			(752				H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),753				U256([30, 0, 0, 0]),754			),755		],756		&hex!(757			"758				1ACF2D55759				0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]760				0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]761762				0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address763				000000000000000000000000000000000000000000000000000000000000000A // uint256764765				000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address766				0000000000000000000000000000000000000000000000000000000000000014 // uint256767768				0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address769				000000000000000000000000000000000000000000000000000000000000001E // uint256770			"771		)772	);773774	test_impl!(775		vec_tuple_uint256_string,776		Vec<(uint256, string)>,777		0xdeadbeef,778		vec![779			(1.into(), "Test URI 0".to_string()),780			(11.into(), "Test URI 1".to_string()),781			(12.into(), "Test URI 2".to_string()),782		],783		&hex!(784			"785				deadbeef786				0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]787				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]788789				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem790				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem791				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem792793				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60794				0000000000000000000000000000000000000000000000000000000000000040 // offset of string795				000000000000000000000000000000000000000000000000000000000000000a // size of string796				5465737420555249203000000000000000000000000000000000000000000000 // string797798				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0799				0000000000000000000000000000000000000000000000000000000000000040 // offset of string800				000000000000000000000000000000000000000000000000000000000000000a // size of string801				5465737420555249203100000000000000000000000000000000000000000000 // string802803				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160804				0000000000000000000000000000000000000000000000000000000000000040 // offset of string805				000000000000000000000000000000000000000000000000000000000000000a // size of string806				5465737420555249203200000000000000000000000000000000000000000000 // string807			"808		)809	);810811	#[test]812	fn dynamic_after_static() {813		let mut encoder = AbiWriter::new();814		encoder.bool(&true);815		encoder.string("test");816		let encoded = encoder.finish();817818		let mut encoder = AbiWriter::new();819		encoder.bool(&true);820		// Offset to subresult821		encoder.uint32(&(32 * 2));822		// Len of "test"823		encoder.uint32(&4);824		encoder.write_padright(&[b't', b'e', b's', b't']);825		let alternative_encoded = encoder.finish();826827		assert_eq!(encoded, alternative_encoded);828829		let mut decoder = AbiReader::new(&encoded);830		assert!(decoder.bool().unwrap());831		assert_eq!(decoder.string().unwrap(), "test");832	}833834	#[test]835	fn mint_sample() {836		let (call, mut decoder) = AbiReader::new_call(&hex!(837			"838				50bb4e7f839				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374840				0000000000000000000000000000000000000000000000000000000000000001841				0000000000000000000000000000000000000000000000000000000000000060842				0000000000000000000000000000000000000000000000000000000000000008843				5465737420555249000000000000000000000000000000000000000000000000844			"845		))846		.unwrap();847		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));848		assert_eq!(849			format!("{:?}", decoder.address().unwrap()),850			"0xad2c0954693c2b5404b7e50967d3481bea432374"851		);852		assert_eq!(decoder.uint32().unwrap(), 1);853		assert_eq!(decoder.string().unwrap(), "Test URI");854	}855856	#[test]857	fn parse_vec_with_dynamic_type() {858		let decoded_data = (859			0x36543006,860			vec![861				(1.into(), "Test URI 0".to_string()),862				(11.into(), "Test URI 1".to_string()),863				(12.into(), "Test URI 2".to_string()),864			],865		);866867		let encoded_data = &hex!(868			"869				36543006870				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address871				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]872				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]873874				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem875				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem876				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem877878				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60879				0000000000000000000000000000000000000000000000000000000000000040 // offset of string880				000000000000000000000000000000000000000000000000000000000000000a // size of string881				5465737420555249203000000000000000000000000000000000000000000000 // string882883				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0884				0000000000000000000000000000000000000000000000000000000000000040 // offset of string885				000000000000000000000000000000000000000000000000000000000000000a // size of string886				5465737420555249203100000000000000000000000000000000000000000000 // string887888				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160889				0000000000000000000000000000000000000000000000000000000000000040 // offset of string890				000000000000000000000000000000000000000000000000000000000000000a // size of string891				5465737420555249203200000000000000000000000000000000000000000000 // string892			"893		);894895		let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();896		assert_eq!(call, u32::to_be_bytes(decoded_data.0));897		let address = decoder.address().unwrap();898		let data = <Vec<(uint256, string)>>::abi_read(&mut decoder).unwrap();899		assert_eq!(data, decoded_data.1);900901		let mut writer = AbiWriter::new_call(decoded_data.0);902		address.abi_write(&mut writer);903		decoded_data.1.abi_write(&mut writer);904		let ed = writer.finish();905		similar_asserts::assert_eq!(encoded_data, ed.as_slice());906	}907}
modifiedcrates/evm-coder/src/custom_signature.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/custom_signature.rs
+++ b/crates/evm-coder/src/custom_signature.rs
@@ -9,37 +9,33 @@
 //! #### Example
 //! ```
 //! use std::str::from_utf8;
-//! use evm_coder::make_signature;
-//! use evm_coder::custom_signature::{
-//! 	SignatureUnit,
-//! 	SIGNATURE_SIZE_LIMIT
-//! };
+//! use evm_coder::{custom_signature::SignatureUnit, make_signature};
 //!
 //! // Create trait for our signature
 //! trait SoliditySignature {
-//!		const SIGNATURE: SignatureUnit;
+//!     const SIGNATURE: SignatureUnit;
 //!
-//!		fn name() -> &'static str {
-//!			from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
-//!		}
-//!	}
+//!     fn name() -> &'static str {
+//!         from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
+//!     }
+//! }
 //!
 //! // Make signatures for some types
-//!	impl SoliditySignature for u8 {
-//!		make_signature!(new fixed("uint8"));
-//!	}
-//!	impl SoliditySignature for u32 {
-//!		make_signature!(new fixed("uint32"));
-//!	}
-//!	impl<T: SoliditySignature> SoliditySignature for Vec<T> {
-//!		make_signature!(new nameof(T) fixed("[]"));
-//!	}
-//!	impl<A: SoliditySignature, B: SoliditySignature> SoliditySignature for (A, B) {
-//!		make_signature!(new fixed("(") nameof(A) fixed(",") nameof(B) fixed(")"));
-//!	}
-//!	impl<A: SoliditySignature> SoliditySignature for (A,) {
-//!		make_signature!(new fixed("(") nameof(A) fixed(",") shift_left(1) fixed(")"));
-//!	}
+//! impl SoliditySignature for u8 {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));
+//! }
+//! impl SoliditySignature for u32 {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint32"));
+//! }
+//! impl<T: SoliditySignature> SoliditySignature for Vec<T> {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
+//! }
+//! impl<A: SoliditySignature, B: SoliditySignature> SoliditySignature for (A, B) {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("(") nameof(A::SIGNATURE) fixed(",") nameof(B::SIGNATURE) fixed(")"));
+//! }
+//! impl<A: SoliditySignature> SoliditySignature for (A,) {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("(") nameof(A::SIGNATURE) fixed(",") shift_left(1) fixed(")"));
+//! }
 //!
 //! assert_eq!(u8::name(), "uint8");
 //! assert_eq!(<Vec<u8>>::name(), "uint8[]");
@@ -52,28 +48,23 @@
 //! #### Example
 //! ```
 //! use core::str::from_utf8;
-//! use evm_coder::{
-//!		make_signature,
-//!		custom_signature::{
-//!			SIGNATURE_SIZE_LIMIT, SignatureUnit, SignaturePreferences, FunctionSignature,
-//!		},
-//!	};
+//! use evm_coder::{custom_signature::SignatureUnit, make_signature};
 //! // Trait for our signature
 //! trait SoliditySignature {
-//!		const SIGNATURE: SignatureUnit;
+//!     const SIGNATURE: SignatureUnit;
 //!
-//!		fn name() -> &'static str {
-//!			from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
-//!		}
-//!	}
+//!     fn name() -> &'static str {
+//!         from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
+//!     }
+//! }
 //!
 //! // Make signatures for some types
-//!	impl SoliditySignature for u8 {
-//!		make_signature!(new fixed("uint8"));
-//!	}
-//!	impl<T: SoliditySignature> SoliditySignature for Vec<T> {
-//!		make_signature!(new nameof(T) fixed("[]"));
-//!	}
+//! impl SoliditySignature for u8 {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));
+//! }
+//! impl<T: SoliditySignature> SoliditySignature for Vec<T> {
+//!     const SIGNATURE: SignatureUnit = make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
+//! }
 //! ```
 
 /// The maximum length of the signature.
@@ -134,8 +125,23 @@
 	(@size; fixed($expr:expr) $($tt:tt)*) => {
 		$expr.len() + $crate::make_signature!(@size; $($tt)*)
 	};
-	(@size; nameof($expr:ty) $($tt:tt)*) => {
-		<$expr>::SIGNATURE.len + $crate::make_signature!(@size; $($tt)*)
+	(@size; nameof($expr:expr) $($tt:tt)*) => {
+		$expr.len + $crate::make_signature!(@size; $($tt)*)
+	};
+	(@size; numof($expr:expr) $($tt:tt)*) => {
+		{
+			let mut out = 0;
+			let mut v = $expr;
+			if v == 0 {
+				out = 1;
+			} else {
+				while v > 0 {
+					out += 1;
+					v /= 10;
+				}
+			}
+			out
+		} + $crate::make_signature!(@size; $($tt)*)
 	};
 	(@size; shift_left($expr:expr) $($tt:tt)*) => {
 		$crate::make_signature!(@size; $($tt)*) - $expr
@@ -150,12 +156,41 @@
 		}
 		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
 	};
-	(@data($dst:ident, $dst_offset:ident); nameof($expr:ty) $($tt:tt)*) => {
+	(@data($dst:ident, $dst_offset:ident); nameof($expr:expr) $($tt:tt)*) => {
 		{
-			$crate::make_signature!(@copy(&<$expr>::SIGNATURE.data, $dst, <$expr>::SIGNATURE.len, $dst_offset));
+			$crate::make_signature!(@copy(&$expr.data, $dst, $expr.len, $dst_offset));
 		}
 		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
 	};
+	(@data($dst:ident, $dst_offset:ident); numof($expr:expr) $($tt:tt)*) => {
+		{
+			let mut v = $expr;
+			let mut need_to_swap = 0;
+			if v == 0 {
+				$dst[$dst_offset] = b'0';
+				$dst_offset += 1;
+			} else {
+				while v > 0 {
+					let n = (v % 10) as u8;
+					$dst[$dst_offset] = b'0' + n;
+					v /= 10;
+					need_to_swap += 1;
+					$dst_offset += 1;
+				}
+			}
+			let mut i = 0;
+			#[allow(clippy::manual_swap)]
+			while i < need_to_swap / 2 {
+				let a = $dst_offset - i - 1;
+				let b = $dst_offset - need_to_swap + i;
+				let v = $dst[a];
+				$dst[a] = $dst[b];
+				$dst[b] = v;
+				i += 1;
+			}
+		}
+		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
+	};
 	(@data($dst:ident, $dst_offset:ident); shift_left($expr:expr) $($tt:tt)*) => {
 		$dst_offset -= $expr;
 		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
@@ -181,34 +216,38 @@
 	use super::{SIGNATURE_SIZE_LIMIT, SignatureUnit};
 
 	trait Name {
-		const SIGNATURE: SignatureUnit;
+		const NAME: SignatureUnit;
 
 		fn name() -> &'static str {
-			from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
+			from_utf8(&Self::NAME.data[..Self::NAME.len]).expect("bad utf-8")
 		}
 	}
 
 	impl Name for u8 {
-		const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));
+		const NAME: SignatureUnit = make_signature!(new fixed("uint8"));
 	}
 	impl Name for u32 {
-		const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint32"));
+		const NAME: SignatureUnit = make_signature!(new fixed("uint32"));
 	}
 	impl<T: Name> Name for Vec<T> {
-		const SIGNATURE: SignatureUnit = make_signature!(new nameof(T) fixed("[]"));
+		const NAME: SignatureUnit = make_signature!(new nameof(T::NAME) fixed("[]"));
 	}
 	impl<A: Name, B: Name> Name for (A, B) {
-		const SIGNATURE: SignatureUnit =
-			make_signature!(new fixed("(") nameof(A) fixed(",") nameof(B) fixed(")"));
+		const NAME: SignatureUnit =
+			make_signature!(new fixed("(") nameof(A::NAME) fixed(",") nameof(B::NAME) fixed(")"));
 	}
 	impl<A: Name> Name for (A,) {
-		const SIGNATURE: SignatureUnit =
-			make_signature!(new fixed("(") nameof(A) fixed(",") shift_left(1) fixed(")"));
+		const NAME: SignatureUnit =
+			make_signature!(new fixed("(") nameof(A::NAME) fixed(",") shift_left(1) fixed(")"));
+	}
+	impl<A: Name, const SIZE: usize> Name for [A; SIZE] {
+		const NAME: SignatureUnit =
+			make_signature!(new nameof(A::NAME) fixed("[") numof(SIZE) fixed("]"));
 	}
 
 	struct MaxSize();
 	impl Name for MaxSize {
-		const SIGNATURE: SignatureUnit = SignatureUnit {
+		const NAME: SignatureUnit = SignatureUnit {
 			data: [b'!'; SIGNATURE_SIZE_LIMIT],
 			len: SIGNATURE_SIZE_LIMIT,
 		};
@@ -273,6 +312,13 @@
 	}
 
 	#[test]
+	fn num() {
+		assert_eq!(<[u8; 0]>::name(), "uint8[0]");
+		assert_eq!(<[u8; 1234]>::name(), "uint8[1234]");
+		assert_eq!(<[u8; 12345]>::name(), "uint8[12345]");
+	}
+
+	#[test]
 	fn over_max_size() {
 		let t = trybuild::TestCases::new();
 		t.compile_fail("tests/build_failed/custom_signature_over_max_size.rs");
modifiedcrates/evm-coder/tests/build_failed/custom_signature_over_max_size.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.rs
+++ b/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.rs
@@ -15,7 +15,8 @@
 }
 
 impl<T: Name> Name for Vec<T> {
-	evm_coder::make_signature!(new nameof(T) fixed("[]"));
+	const SIGNATURE: SignatureUnit =
+		evm_coder::make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
 }
 
 struct MaxSize();
modifiedcrates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderrdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderr
+++ b/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderr
@@ -1,18 +1,28 @@
+warning: unused import: `make_signature`
+ --> tests/build_failed/custom_signature_over_max_size.rs:5:2
+  |
+5 |     make_signature,
+  |     ^^^^^^^^^^^^^^
+  |
+  = note: `#[warn(unused_imports)]` on by default
+
 error: any use of this value will cause an error
-  --> tests/build_failed/custom_signature_over_max_size.rs:18:2
+  --> tests/build_failed/custom_signature_over_max_size.rs:19:3
    |
-18 |     evm_coder::make_signature!(new nameof(T) fixed("[]"));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 256 but the index is 256
+18 |     const SIGNATURE: SignatureUnit =
+   |     ------------------------------
+19 |         evm_coder::make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 256 but the index is 256
    |
    = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-   = note: this error originates in the macro `make_signature` which comes from the expansion of the macro `evm_coder::make_signature` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::make_signature` which comes from the expansion of the macro `evm_coder::make_signature` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: any use of this value will cause an error
-  --> tests/build_failed/custom_signature_over_max_size.rs:29:29
+  --> tests/build_failed/custom_signature_over_max_size.rs:30:29
    |
-29 | const NAME: SignatureUnit = <Vec<MaxSize>>::SIGNATURE;
+30 | const NAME: SignatureUnit = <Vec<MaxSize>>::SIGNATURE;
    | -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
modifiedcrates/evm-coder/tests/conditional_is.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/conditional_is.rs
+++ b/crates/evm-coder/tests/conditional_is.rs
@@ -1,11 +1,4 @@
 use evm_coder::{types::*, solidity_interface, execution::Result};
-use evm_coder::{
-	make_signature,
-	custom_signature::{
-		SIGNATURE_SIZE_LIMIT, SignatureUnit, SignaturePreferences, FunctionSignature,
-	},
-	types::Signature,
-};
 
 pub struct Contract(bool);
 
modifiedcrates/evm-coder/tests/generics.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/generics.rs
+++ b/crates/evm-coder/tests/generics.rs
@@ -16,12 +16,6 @@
 
 use std::marker::PhantomData;
 use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};
-use evm_coder::{
-	make_signature,
-	custom_signature::{
-		SIGNATURE_SIZE_LIMIT, SignatureUnit, SignaturePreferences, FunctionSignature,
-	},
-};
 
 pub struct Generic<T>(PhantomData<T>);
 
modifiedcrates/evm-coder/tests/random.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/random.rs
+++ b/crates/evm-coder/tests/random.rs
@@ -17,13 +17,7 @@
 #![allow(dead_code)] // This test only checks that macros is not panicking
 
 use evm_coder::{ToLog, execution::Result, solidity_interface, types::*, solidity, weight};
-use evm_coder::{
-	make_signature,
-	custom_signature::{
-		SIGNATURE_SIZE_LIMIT, SignatureUnit, SignaturePreferences, FunctionSignature,
-	},
-	types::Signature,
-};
+use evm_coder::{types::Signature};
 
 pub struct Impls;
 
modifiedcrates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/solidity_generation.rs
+++ b/crates/evm-coder/tests/solidity_generation.rs
@@ -15,13 +15,7 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};
-use evm_coder::{
-	make_signature,
-	custom_signature::{
-		SIGNATURE_SIZE_LIMIT, SignatureUnit, SignaturePreferences, FunctionSignature,
-	},
-	types::Signature,
-};
+use evm_coder::{types::Signature};
 
 pub struct ERC20;