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

difftreelog

CORE-317 cargo fmt

Trubnikov Sergey2022-04-11parent: #0902e70.patch.diff
in: master

2 files changed

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//! TODO: I misunterstood therminology, abi IS rlp encoded, so18//! this module should be replaced with rlp crate1920#![allow(dead_code)]2122#[cfg(not(feature = "std"))]23use alloc::vec::Vec;24use evm_core::ExitError;25use primitive_types::{H160, U256};2627use crate::{28	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},29	types::{string, self},30};31use crate::execution::Result;3233const ABI_ALIGNMENT: usize = 32;3435#[derive(Clone)]36pub struct AbiReader<'i> {37	buf: &'i [u8],38	subresult_offset: usize,39	offset: usize,40}41impl<'i> AbiReader<'i> {42	pub fn new(buf: &'i [u8]) -> Self {43		Self {44			buf,45			subresult_offset: 0,46			offset: 0,47		}48	}49	pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {50		if buf.len() < 4 {51			return Err(Error::Error(ExitError::OutOfOffset));52		}53		let mut method_id = [0; 4];54		method_id.copy_from_slice(&buf[0..4]);5556		Ok((57			method_id,58			Self {59				buf,60				subresult_offset: 4,61				offset: 4,62			},63		))64	}6566	fn read_pad<const S: usize>(buf: &[u8], offset: usize, pad_start: usize, pad_size: usize, block_start: usize, block_size: usize) -> Result<[u8; S]> {67		if buf.len() - offset < ABI_ALIGNMENT {68			return Err(Error::Error(ExitError::OutOfOffset));69		}70		let mut block = [0; S];71		// Verify padding is empty72		if !buf[pad_start..pad_size]73			.iter()74			.all(|&v| v == 0)75		{76			return Err(Error::Error(ExitError::InvalidRange));77		}78		block.copy_from_slice(79			&buf[block_start..block_size],80		);81		Ok(block)82	}8384	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {85		let offset = self.offset;86		self.offset += ABI_ALIGNMENT;87		Self::read_pad(88			self.buf,89			offset,90			offset, 91			offset + ABI_ALIGNMENT - S,92			offset + ABI_ALIGNMENT - S,93			offset + ABI_ALIGNMENT94		)95	}9697	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {98		let offset = self.offset;99		self.offset += ABI_ALIGNMENT;100		Self::read_pad(101			self.buf,102			offset,103			offset + S, 104			offset + ABI_ALIGNMENT,105			offset,106			offset + S107		)108	}109	110	pub fn address(&mut self) -> Result<H160> {111		Ok(H160(self.read_padleft()?))112	}113114	pub fn bool(&mut self) -> Result<bool> {115		let data: [u8; 1] = self.read_padleft()?;116		match data[0] {117			0 => Ok(false),118			1 => Ok(true),119			_ => Err(Error::Error(ExitError::InvalidRange)),120		}121	}122123	pub fn bytes4(&mut self) -> Result<[u8; 4]> {124		self.read_padright()125	}126127	pub fn bytes(&mut self) -> Result<Vec<u8>> {128		let mut subresult = self.subresult()?;129		let length = subresult.read_usize()?;130		if subresult.buf.len() <= subresult.offset + length {131			return Err(Error::Error(ExitError::OutOfOffset));132		}133		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())134	}135	pub fn string(&mut self) -> Result<string> {136		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))137	}138139	pub fn uint8(&mut self) -> Result<u8> {140		Ok(self.read_padleft::<1>()?[0])141	}142143	pub fn uint32(&mut self) -> Result<u32> {144		Ok(u32::from_be_bytes(self.read_padleft()?))145	}146147	pub fn uint128(&mut self) -> Result<u128> {148		Ok(u128::from_be_bytes(self.read_padleft()?))149	}150151	pub fn uint256(&mut self) -> Result<U256> {152		let buf: [u8; 32] = self.read_padleft()?;153		Ok(U256::from_big_endian(&buf))154	}155156	pub fn uint64(&mut self) -> Result<u64> {157		Ok(u64::from_be_bytes(self.read_padleft()?))158	}159160	pub fn read_usize(&mut self) -> Result<usize> {161		Ok(usize::from_be_bytes(self.read_padleft()?))162	}163164	fn subresult(&mut self) -> Result<AbiReader<'i>> {165		let offset = self.read_usize()?;166		if offset + self.subresult_offset > self.buf.len() {167			return Err(Error::Error(ExitError::InvalidRange));168		}169		Ok(AbiReader {170			buf: self.buf,171			subresult_offset: offset + self.subresult_offset,172			offset: offset + self.subresult_offset,173		})174	}175176	pub fn is_finished(&self) -> bool {177		self.buf.len() == self.offset178	}179}180181#[derive(Default)]182pub struct AbiWriter {183	static_part: Vec<u8>,184	dynamic_part: Vec<(usize, AbiWriter)>,185}186impl AbiWriter {187	pub fn new() -> Self {188		Self::default()189	}190	pub fn new_call(method_id: u32) -> Self {191		let mut val = Self::new();192		val.static_part.extend(&method_id.to_be_bytes());193		val194	}195196	fn write_padleft(&mut self, block: &[u8]) {197		assert!(block.len() <= ABI_ALIGNMENT);198		self.static_part199			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);200		self.static_part.extend(block);201	}202203	fn write_padright(&mut self, bytes: &[u8]) {204		assert!(bytes.len() <= ABI_ALIGNMENT);205		self.static_part.extend(bytes);206		self.static_part207			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);208	}209210	pub fn address(&mut self, address: &H160) {211		self.write_padleft(&address.0)212	}213214	pub fn bool(&mut self, value: &bool) {215		self.write_padleft(&[if *value { 1 } else { 0 }])216	}217218	pub fn uint8(&mut self, value: &u8) {219		self.write_padleft(&[*value])220	}221222	pub fn uint32(&mut self, value: &u32) {223		self.write_padleft(&u32::to_be_bytes(*value))224	}225226	pub fn uint128(&mut self, value: &u128) {227		self.write_padleft(&u128::to_be_bytes(*value))228	}229230	pub fn uint256(&mut self, value: &U256) {231		let mut out = [0; 32];232		value.to_big_endian(&mut out);233		self.write_padleft(&out)234	}235236	pub fn write_usize(&mut self, value: &usize) {237		self.write_padleft(&usize::to_be_bytes(*value))238	}239240	pub fn write_subresult(&mut self, result: Self) {241		self.dynamic_part.push((self.static_part.len(), result));242		// Empty block, to be filled later243		self.write_padleft(&[]);244	}245246	pub fn memory(&mut self, value: &[u8]) {247		let mut sub = Self::new();248		sub.write_usize(&value.len());249		for chunk in value.chunks(ABI_ALIGNMENT) {250			sub.write_padright(chunk);251		}252		self.write_subresult(sub);253	}254255	pub fn string(&mut self, value: &str) {256		self.memory(value.as_bytes())257	}258259	pub fn bytes(&mut self, value: &[u8]) {260		self.memory(value)261	}262263	pub fn finish(mut self) -> Vec<u8> {264		for (static_offset, part) in self.dynamic_part {265			let part_offset = self.static_part.len();266267			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);268			self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()269				..static_offset + ABI_ALIGNMENT]270				.copy_from_slice(&encoded_dynamic_offset);271			self.static_part.extend(part.finish())272		}273		self.static_part274	}275}276277pub trait AbiRead<T> {278	fn abi_read(&mut self) -> Result<T>;279}280281macro_rules! impl_abi_readable {282	($ty:ty, $method:ident) => {283		impl AbiRead<$ty> for AbiReader<'_> {284			fn abi_read(&mut self) -> Result<$ty> {285				self.$method()286			}287		}288	};289}290291impl_abi_readable!(u8, uint8);292impl_abi_readable!(u32, uint32);293impl_abi_readable!(u64, uint64);294impl_abi_readable!(u128, uint128);295impl_abi_readable!(U256, uint256);296impl_abi_readable!([u8; 4], bytes4);297impl_abi_readable!(H160, address);298impl_abi_readable!(Vec<u8>, bytes);299impl_abi_readable!(bool, bool);300impl_abi_readable!(string, string);301302mod sealed {303	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead304	pub trait CanBePlacedInVec {}305}306307impl sealed::CanBePlacedInVec for U256 {}308impl sealed::CanBePlacedInVec for string {}309impl sealed::CanBePlacedInVec for H160 {}310311impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>312where313	Self: AbiRead<R>,314{315	fn abi_read(&mut self) -> Result<Vec<R>> {316		let mut sub = self.subresult()?;317		let size = sub.read_usize()?;318		sub.subresult_offset = sub.offset;319		let mut out = Vec::with_capacity(size);320		for _ in 0..size {321			out.push(<Self as AbiRead<R>>::abi_read(&mut sub)?);322		}323		Ok(out)324	}325}326327macro_rules! impl_tuples {328	($($ident:ident)+) => {329		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}330		impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>331		where332			$(Self: AbiRead<$ident>),+333		{334			fn abi_read(&mut self) -> Result<($($ident,)+)> {335				let mut subresult = self.subresult()?;336				Ok((337					$(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+338				))339			}340		}341	};342}343344impl_tuples! {A}345impl_tuples! {A B}346impl_tuples! {A B C}347impl_tuples! {A B C D}348impl_tuples! {A B C D E}349impl_tuples! {A B C D E F}350impl_tuples! {A B C D E F G}351impl_tuples! {A B C D E F G H}352impl_tuples! {A B C D E F G H I}353impl_tuples! {A B C D E F G H I J}354355pub trait AbiWrite {356	fn abi_write(&self, writer: &mut AbiWriter);357	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {358		let mut writer = AbiWriter::new();359		self.abi_write(&mut writer);360		Ok(writer.into())361	}362}363364impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {365	// this particular AbiWrite implementation should be split to another trait,366	// which only implements [`to_result`]367	//368	// But due to lack of specialization feature in stable Rust, we can't have369	// blanket impl of this trait `for T where T: AbiWrite`, so here we abusing370	// default trait methods for it371	fn abi_write(&self, _writer: &mut AbiWriter) {372		debug_assert!(false, "shouldn't be called, see comment")373	}374	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {375		match self {376			Ok(v) => Ok(WithPostDispatchInfo {377				post_info: v.post_info.clone(),378				data: {379					let mut out = AbiWriter::new();380					v.data.abi_write(&mut out);381					out382				},383			}),384			Err(e) => Err(e.clone()),385		}386	}387}388389macro_rules! impl_abi_writeable {390	($ty:ty, $method:ident) => {391		impl AbiWrite for $ty {392			fn abi_write(&self, writer: &mut AbiWriter) {393				writer.$method(&self)394			}395		}396	};397}398399impl_abi_writeable!(u8, uint8);400impl_abi_writeable!(u32, uint32);401impl_abi_writeable!(u128, uint128);402impl_abi_writeable!(U256, uint256);403impl_abi_writeable!(H160, address);404impl_abi_writeable!(bool, bool);405impl_abi_writeable!(&str, string);406impl AbiWrite for &string {407	fn abi_write(&self, writer: &mut AbiWriter) {408		writer.string(self)409	}410}411impl AbiWrite for &Vec<u8> {412	fn abi_write(&self, writer: &mut AbiWriter) {413		writer.bytes(self)414	}415}416417impl AbiWrite for () {418	fn abi_write(&self, _writer: &mut AbiWriter) {}419}420421#[macro_export]422macro_rules! abi_decode {423	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {424		$(425			let $name = $reader.$typ()?;426		)+427	}428}429#[macro_export]430macro_rules! abi_encode {431	($($typ:ident($value:expr)),* $(,)?) => {{432		#[allow(unused_mut)]433		let mut writer = ::evm_coder::abi::AbiWriter::new();434		$(435			writer.$typ($value);436		)*437		writer438	}};439	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{440		#[allow(unused_mut)]441		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);442		$(443			writer.$typ($value);444		)*445		writer446	}}447}448449#[cfg(test)]450pub mod test {451	use crate::{452		abi::AbiRead,453		types::{string, uint256},454	};455456	use super::{AbiReader, AbiWriter};457	use hex_literal::hex;458459	#[test]460	fn dynamic_after_static() {461		let mut encoder = AbiWriter::new();462		encoder.bool(&true);463		encoder.string("test");464		let encoded = encoder.finish();465466		let mut encoder = AbiWriter::new();467		encoder.bool(&true);468		// Offset to subresult469		encoder.uint32(&(32 * 2));470		// Len of "test"471		encoder.uint32(&4);472		encoder.write_padright(&[b't', b'e', b's', b't']);473		let alternative_encoded = encoder.finish();474475		assert_eq!(encoded, alternative_encoded);476477		let mut decoder = AbiReader::new(&encoded);478		assert_eq!(decoder.bool().unwrap(), true);479		assert_eq!(decoder.string().unwrap(), "test");480	}481482	#[test]483	fn mint_sample() {484		let (call, mut decoder) = AbiReader::new_call(&hex!(485			"486				50bb4e7f487				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374488				0000000000000000000000000000000000000000000000000000000000000001489				0000000000000000000000000000000000000000000000000000000000000060490				0000000000000000000000000000000000000000000000000000000000000008491				5465737420555249000000000000000000000000000000000000000000000000492			"493		))494		.unwrap();495		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));496		assert_eq!(497			format!("{:?}", decoder.address().unwrap()),498			"0xad2c0954693c2b5404b7e50967d3481bea432374"499		);500		assert_eq!(decoder.uint32().unwrap(), 1);501		assert_eq!(decoder.string().unwrap(), "Test URI");502	}503504	#[test]505	fn mint_bulk() {506		let (call, mut decoder) = AbiReader::new_call(&hex!(507			"508				36543006509				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address510				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]511				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]512513				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem514				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem515				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem516517				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60518				0000000000000000000000000000000000000000000000000000000000000040 // offset of string519				000000000000000000000000000000000000000000000000000000000000000a // size of string520				5465737420555249203000000000000000000000000000000000000000000000 // string521522				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0523				0000000000000000000000000000000000000000000000000000000000000040 // offset of string524				000000000000000000000000000000000000000000000000000000000000000a // size of string525				5465737420555249203100000000000000000000000000000000000000000000 // string526527				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160528				0000000000000000000000000000000000000000000000000000000000000040 // offset of string529				000000000000000000000000000000000000000000000000000000000000000a // size of string530				5465737420555249203200000000000000000000000000000000000000000000 // string531			"532		))533		.unwrap();534		assert_eq!(call, u32::to_be_bytes(0x36543006));535		let _ = decoder.address().unwrap();536		let data =537			<AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();538		assert_eq!(539			data,540			vec![541				(1.into(), "Test URI 0".to_string()),542				(11.into(), "Test URI 1".to_string()),543				(12.into(), "Test URI 2".to_string())544			]545		);546	}547}
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//! TODO: I misunterstood therminology, abi IS rlp encoded, so18//! this module should be replaced with rlp crate1920#![allow(dead_code)]2122#[cfg(not(feature = "std"))]23use alloc::vec::Vec;24use evm_core::ExitError;25use primitive_types::{H160, U256};2627use crate::{28	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},29	types::{string, self},30};31use crate::execution::Result;3233const ABI_ALIGNMENT: usize = 32;3435#[derive(Clone)]36pub struct AbiReader<'i> {37	buf: &'i [u8],38	subresult_offset: usize,39	offset: usize,40}41impl<'i> AbiReader<'i> {42	pub fn new(buf: &'i [u8]) -> Self {43		Self {44			buf,45			subresult_offset: 0,46			offset: 0,47		}48	}49	pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {50		if buf.len() < 4 {51			return Err(Error::Error(ExitError::OutOfOffset));52		}53		let mut method_id = [0; 4];54		method_id.copy_from_slice(&buf[0..4]);5556		Ok((57			method_id,58			Self {59				buf,60				subresult_offset: 4,61				offset: 4,62			},63		))64	}6566	fn read_pad<const S: usize>(67		buf: &[u8],68		offset: usize,69		pad_start: usize,70		pad_size: usize,71		block_start: usize,72		block_size: usize,73	) -> Result<[u8; S]> {74		if buf.len() - offset < ABI_ALIGNMENT {75			return Err(Error::Error(ExitError::OutOfOffset));76		}77		let mut block = [0; S];78		// Verify padding is empty79		if !buf[pad_start..pad_size].iter().all(|&v| v == 0) {80			return Err(Error::Error(ExitError::InvalidRange));81		}82		block.copy_from_slice(&buf[block_start..block_size]);83		Ok(block)84	}8586	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {87		let offset = self.offset;88		self.offset += ABI_ALIGNMENT;89		Self::read_pad(90			self.buf,91			offset,92			offset,93			offset + ABI_ALIGNMENT - S,94			offset + ABI_ALIGNMENT - S,95			offset + ABI_ALIGNMENT,96		)97	}9899	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {100		let offset = self.offset;101		self.offset += ABI_ALIGNMENT;102		Self::read_pad(103			self.buf,104			offset,105			offset + S,106			offset + ABI_ALIGNMENT,107			offset,108			offset + S,109		)110	}111112	pub fn address(&mut self) -> Result<H160> {113		Ok(H160(self.read_padleft()?))114	}115116	pub fn bool(&mut self) -> Result<bool> {117		let data: [u8; 1] = self.read_padleft()?;118		match data[0] {119			0 => Ok(false),120			1 => Ok(true),121			_ => Err(Error::Error(ExitError::InvalidRange)),122		}123	}124125	pub fn bytes4(&mut self) -> Result<[u8; 4]> {126		self.read_padright()127	}128129	pub fn bytes(&mut self) -> Result<Vec<u8>> {130		let mut subresult = self.subresult()?;131		let length = subresult.read_usize()?;132		if subresult.buf.len() <= subresult.offset + length {133			return Err(Error::Error(ExitError::OutOfOffset));134		}135		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())136	}137	pub fn string(&mut self) -> Result<string> {138		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))139	}140141	pub fn uint8(&mut self) -> Result<u8> {142		Ok(self.read_padleft::<1>()?[0])143	}144145	pub fn uint32(&mut self) -> Result<u32> {146		Ok(u32::from_be_bytes(self.read_padleft()?))147	}148149	pub fn uint128(&mut self) -> Result<u128> {150		Ok(u128::from_be_bytes(self.read_padleft()?))151	}152153	pub fn uint256(&mut self) -> Result<U256> {154		let buf: [u8; 32] = self.read_padleft()?;155		Ok(U256::from_big_endian(&buf))156	}157158	pub fn uint64(&mut self) -> Result<u64> {159		Ok(u64::from_be_bytes(self.read_padleft()?))160	}161162	pub fn read_usize(&mut self) -> Result<usize> {163		Ok(usize::from_be_bytes(self.read_padleft()?))164	}165166	fn subresult(&mut self) -> Result<AbiReader<'i>> {167		let offset = self.read_usize()?;168		if offset + self.subresult_offset > self.buf.len() {169			return Err(Error::Error(ExitError::InvalidRange));170		}171		Ok(AbiReader {172			buf: self.buf,173			subresult_offset: offset + self.subresult_offset,174			offset: offset + self.subresult_offset,175		})176	}177178	pub fn is_finished(&self) -> bool {179		self.buf.len() == self.offset180	}181}182183#[derive(Default)]184pub struct AbiWriter {185	static_part: Vec<u8>,186	dynamic_part: Vec<(usize, AbiWriter)>,187}188impl AbiWriter {189	pub fn new() -> Self {190		Self::default()191	}192	pub fn new_call(method_id: u32) -> Self {193		let mut val = Self::new();194		val.static_part.extend(&method_id.to_be_bytes());195		val196	}197198	fn write_padleft(&mut self, block: &[u8]) {199		assert!(block.len() <= ABI_ALIGNMENT);200		self.static_part201			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);202		self.static_part.extend(block);203	}204205	fn write_padright(&mut self, bytes: &[u8]) {206		assert!(bytes.len() <= ABI_ALIGNMENT);207		self.static_part.extend(bytes);208		self.static_part209			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);210	}211212	pub fn address(&mut self, address: &H160) {213		self.write_padleft(&address.0)214	}215216	pub fn bool(&mut self, value: &bool) {217		self.write_padleft(&[if *value { 1 } else { 0 }])218	}219220	pub fn uint8(&mut self, value: &u8) {221		self.write_padleft(&[*value])222	}223224	pub fn uint32(&mut self, value: &u32) {225		self.write_padleft(&u32::to_be_bytes(*value))226	}227228	pub fn uint128(&mut self, value: &u128) {229		self.write_padleft(&u128::to_be_bytes(*value))230	}231232	pub fn uint256(&mut self, value: &U256) {233		let mut out = [0; 32];234		value.to_big_endian(&mut out);235		self.write_padleft(&out)236	}237238	pub fn write_usize(&mut self, value: &usize) {239		self.write_padleft(&usize::to_be_bytes(*value))240	}241242	pub fn write_subresult(&mut self, result: Self) {243		self.dynamic_part.push((self.static_part.len(), result));244		// Empty block, to be filled later245		self.write_padleft(&[]);246	}247248	pub fn memory(&mut self, value: &[u8]) {249		let mut sub = Self::new();250		sub.write_usize(&value.len());251		for chunk in value.chunks(ABI_ALIGNMENT) {252			sub.write_padright(chunk);253		}254		self.write_subresult(sub);255	}256257	pub fn string(&mut self, value: &str) {258		self.memory(value.as_bytes())259	}260261	pub fn bytes(&mut self, value: &[u8]) {262		self.memory(value)263	}264265	pub fn finish(mut self) -> Vec<u8> {266		for (static_offset, part) in self.dynamic_part {267			let part_offset = self.static_part.len();268269			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);270			self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()271				..static_offset + ABI_ALIGNMENT]272				.copy_from_slice(&encoded_dynamic_offset);273			self.static_part.extend(part.finish())274		}275		self.static_part276	}277}278279pub trait AbiRead<T> {280	fn abi_read(&mut self) -> Result<T>;281}282283macro_rules! impl_abi_readable {284	($ty:ty, $method:ident) => {285		impl AbiRead<$ty> for AbiReader<'_> {286			fn abi_read(&mut self) -> Result<$ty> {287				self.$method()288			}289		}290	};291}292293impl_abi_readable!(u8, uint8);294impl_abi_readable!(u32, uint32);295impl_abi_readable!(u64, uint64);296impl_abi_readable!(u128, uint128);297impl_abi_readable!(U256, uint256);298impl_abi_readable!([u8; 4], bytes4);299impl_abi_readable!(H160, address);300impl_abi_readable!(Vec<u8>, bytes);301impl_abi_readable!(bool, bool);302impl_abi_readable!(string, string);303304mod sealed {305	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead306	pub trait CanBePlacedInVec {}307}308309impl sealed::CanBePlacedInVec for U256 {}310impl sealed::CanBePlacedInVec for string {}311impl sealed::CanBePlacedInVec for H160 {}312313impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>314where315	Self: AbiRead<R>,316{317	fn abi_read(&mut self) -> Result<Vec<R>> {318		let mut sub = self.subresult()?;319		let size = sub.read_usize()?;320		sub.subresult_offset = sub.offset;321		let mut out = Vec::with_capacity(size);322		for _ in 0..size {323			out.push(<Self as AbiRead<R>>::abi_read(&mut sub)?);324		}325		Ok(out)326	}327}328329macro_rules! impl_tuples {330	($($ident:ident)+) => {331		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}332		impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>333		where334			$(Self: AbiRead<$ident>),+335		{336			fn abi_read(&mut self) -> Result<($($ident,)+)> {337				let mut subresult = self.subresult()?;338				Ok((339					$(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+340				))341			}342		}343	};344}345346impl_tuples! {A}347impl_tuples! {A B}348impl_tuples! {A B C}349impl_tuples! {A B C D}350impl_tuples! {A B C D E}351impl_tuples! {A B C D E F}352impl_tuples! {A B C D E F G}353impl_tuples! {A B C D E F G H}354impl_tuples! {A B C D E F G H I}355impl_tuples! {A B C D E F G H I J}356357pub trait AbiWrite {358	fn abi_write(&self, writer: &mut AbiWriter);359	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {360		let mut writer = AbiWriter::new();361		self.abi_write(&mut writer);362		Ok(writer.into())363	}364}365366impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {367	// this particular AbiWrite implementation should be split to another trait,368	// which only implements [`to_result`]369	//370	// But due to lack of specialization feature in stable Rust, we can't have371	// blanket impl of this trait `for T where T: AbiWrite`, so here we abusing372	// default trait methods for it373	fn abi_write(&self, _writer: &mut AbiWriter) {374		debug_assert!(false, "shouldn't be called, see comment")375	}376	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {377		match self {378			Ok(v) => Ok(WithPostDispatchInfo {379				post_info: v.post_info.clone(),380				data: {381					let mut out = AbiWriter::new();382					v.data.abi_write(&mut out);383					out384				},385			}),386			Err(e) => Err(e.clone()),387		}388	}389}390391macro_rules! impl_abi_writeable {392	($ty:ty, $method:ident) => {393		impl AbiWrite for $ty {394			fn abi_write(&self, writer: &mut AbiWriter) {395				writer.$method(&self)396			}397		}398	};399}400401impl_abi_writeable!(u8, uint8);402impl_abi_writeable!(u32, uint32);403impl_abi_writeable!(u128, uint128);404impl_abi_writeable!(U256, uint256);405impl_abi_writeable!(H160, address);406impl_abi_writeable!(bool, bool);407impl_abi_writeable!(&str, string);408impl AbiWrite for &string {409	fn abi_write(&self, writer: &mut AbiWriter) {410		writer.string(self)411	}412}413impl AbiWrite for &Vec<u8> {414	fn abi_write(&self, writer: &mut AbiWriter) {415		writer.bytes(self)416	}417}418419impl AbiWrite for () {420	fn abi_write(&self, _writer: &mut AbiWriter) {}421}422423#[macro_export]424macro_rules! abi_decode {425	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {426		$(427			let $name = $reader.$typ()?;428		)+429	}430}431#[macro_export]432macro_rules! abi_encode {433	($($typ:ident($value:expr)),* $(,)?) => {{434		#[allow(unused_mut)]435		let mut writer = ::evm_coder::abi::AbiWriter::new();436		$(437			writer.$typ($value);438		)*439		writer440	}};441	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{442		#[allow(unused_mut)]443		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);444		$(445			writer.$typ($value);446		)*447		writer448	}}449}450451#[cfg(test)]452pub mod test {453	use crate::{454		abi::AbiRead,455		types::{string, uint256},456	};457458	use super::{AbiReader, AbiWriter};459	use hex_literal::hex;460461	#[test]462	fn dynamic_after_static() {463		let mut encoder = AbiWriter::new();464		encoder.bool(&true);465		encoder.string("test");466		let encoded = encoder.finish();467468		let mut encoder = AbiWriter::new();469		encoder.bool(&true);470		// Offset to subresult471		encoder.uint32(&(32 * 2));472		// Len of "test"473		encoder.uint32(&4);474		encoder.write_padright(&[b't', b'e', b's', b't']);475		let alternative_encoded = encoder.finish();476477		assert_eq!(encoded, alternative_encoded);478479		let mut decoder = AbiReader::new(&encoded);480		assert_eq!(decoder.bool().unwrap(), true);481		assert_eq!(decoder.string().unwrap(), "test");482	}483484	#[test]485	fn mint_sample() {486		let (call, mut decoder) = AbiReader::new_call(&hex!(487			"488				50bb4e7f489				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374490				0000000000000000000000000000000000000000000000000000000000000001491				0000000000000000000000000000000000000000000000000000000000000060492				0000000000000000000000000000000000000000000000000000000000000008493				5465737420555249000000000000000000000000000000000000000000000000494			"495		))496		.unwrap();497		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));498		assert_eq!(499			format!("{:?}", decoder.address().unwrap()),500			"0xad2c0954693c2b5404b7e50967d3481bea432374"501		);502		assert_eq!(decoder.uint32().unwrap(), 1);503		assert_eq!(decoder.string().unwrap(), "Test URI");504	}505506	#[test]507	fn mint_bulk() {508		let (call, mut decoder) = AbiReader::new_call(&hex!(509			"510				36543006511				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address512				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]513				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]514515				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem516				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem517				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem518519				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60520				0000000000000000000000000000000000000000000000000000000000000040 // offset of string521				000000000000000000000000000000000000000000000000000000000000000a // size of string522				5465737420555249203000000000000000000000000000000000000000000000 // string523524				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0525				0000000000000000000000000000000000000000000000000000000000000040 // offset of string526				000000000000000000000000000000000000000000000000000000000000000a // size of string527				5465737420555249203100000000000000000000000000000000000000000000 // string528529				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160530				0000000000000000000000000000000000000000000000000000000000000040 // offset of string531				000000000000000000000000000000000000000000000000000000000000000a // size of string532				5465737420555249203200000000000000000000000000000000000000000000 // string533			"534		))535		.unwrap();536		assert_eq!(call, u32::to_be_bytes(0x36543006));537		let _ = decoder.address().unwrap();538		let data =539			<AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();540		assert_eq!(541			data,542			vec![543				(1.into(), "Test URI 0".to_string()),544				(11.into(), "Test URI 1".to_string()),545				(12.into(), "Test URI 2".to_string())546			]547		);548	}549}
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -489,7 +489,11 @@
 	) -> fmt::Result {
 		const ZERO_BYTES: [u8; 4] = [0; 4];
 		if self.selector != ZERO_BYTES {
-			writeln!(out, "// Selector: {:0>8x}", u32::from_be_bytes(self.selector))?;
+			writeln!(
+				out,
+				"// Selector: {:0>8x}",
+				u32::from_be_bytes(self.selector)
+			)?;
 		}
 		if is_impl {
 			write!(out, "contract ")?;