git.delta.rocks / unique-network / refs/commits / 4c1a924fb18b

difftreelog

refactor CanBePlacedInVec

Trubnikov Sergey2022-11-02parent: #527498b.patch.diff
in: master

2 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
@@ -21,9 +21,8 @@
 // https://doc.rust-lang.org/reference/procedural-macros.html
 
 use proc_macro2::TokenStream;
-use quote::{quote, ToTokens, format_ident};
+use quote::{quote, format_ident};
 use inflector::cases;
-use std::fmt::Write;
 use syn::{
 	Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,
 	MetaNameValue, PatType, PathArguments, ReturnType, Type,
@@ -33,8 +32,8 @@
 };
 
 use crate::{
-	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,
-	parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,
+	parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment, parse_result_ok,
+	pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,
 	snake_ident_to_screaming,
 };
 
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, SIGNATURE_SIZE_LIMIT},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 TypeHelper for $ty {356			fn is_dynamic() -> bool {357				$dynamic358			}359360			fn size() -> usize {361				ABI_ALIGNMENT362			}363		}364		impl AbiRead for $ty {365			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {366				reader.$method()367			}368		}369	};370}371372impl_abi_readable!(bool, bool, false);373impl_abi_readable!(uint8, uint8, false);374impl_abi_readable!(uint32, uint32, false);375impl_abi_readable!(uint64, uint64, false);376impl_abi_readable!(uint128, uint128, false);377impl_abi_readable!(uint256, uint256, false);378impl_abi_readable!(bytes4, bytes4, false);379impl_abi_readable!(address, address, false);380impl_abi_readable!(string, string, true);381382impl TypeHelper for bytes {383	fn is_dynamic() -> bool {384		true385	}386	fn size() -> usize {387		ABI_ALIGNMENT388	}389}390impl AbiRead for bytes {391	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {392		Ok(bytes(reader.bytes()?))393	}394}395396mod sealed {397	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead398	pub trait CanBePlacedInVec {}399}400401impl sealed::CanBePlacedInVec for U256 {}402impl sealed::CanBePlacedInVec for string {}403impl sealed::CanBePlacedInVec for H160 {}404impl sealed::CanBePlacedInVec for EthCrossAccount {}405406impl<R: AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {407	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {408		let mut sub = reader.subresult(None)?;409		let size = sub.uint32()? as usize;410		sub.subresult_offset = sub.offset;411		let mut out = Vec::with_capacity(size);412		for _ in 0..size {413			out.push(<R>::abi_read(&mut sub)?);414		}415		Ok(out)416	}417}418419impl<R: Signature> Signature for Vec<R> {420	make_signature!(new nameof(R) fixed("[]"));421}422423impl TypeHelper for EthCrossAccount {424	fn is_dynamic() -> bool {425		address::is_dynamic() || uint256::is_dynamic()426	}427428	fn size() -> usize {429		<address as TypeHelper>::size() + <uint256 as TypeHelper>::size()430	}431}432433impl AbiRead for EthCrossAccount {434	fn abi_read(reader: &mut AbiReader) -> Result<EthCrossAccount> {435		let size = if !EthCrossAccount::is_dynamic() {436			Some(<EthCrossAccount as TypeHelper>::size())437		} else {438			None439		};440		let mut subresult = reader.subresult(size)?;441		let eth = <address>::abi_read(&mut subresult)?;442		let sub = <uint256>::abi_read(&mut subresult)?;443444		Ok(EthCrossAccount { eth, sub })445	}446}447448impl AbiWrite for EthCrossAccount {449	fn abi_write(&self, writer: &mut AbiWriter) {450		self.eth.abi_write(writer);451		self.sub.abi_write(writer);452	}453}454455macro_rules! impl_tuples {456	($($ident:ident)+) => {457		impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+)458		where459			$(460				$ident: TypeHelper,461			)+462		{463			fn is_dynamic() -> bool {464				false465				$(466					|| <$ident>::is_dynamic()467				)*468			}469470			fn size() -> usize {471				0 $(+ <$ident>::size())+472			}473		}474475		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}476477		impl<$($ident),+> AbiRead for ($($ident,)+)478		where479			$($ident: AbiRead,)+480			($($ident,)+): TypeHelper,481		{482			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {483				let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };484				let mut subresult = reader.subresult(size)?;485				Ok((486					$(<$ident>::abi_read(&mut subresult)?,)+487				))488			}489		}490491		#[allow(non_snake_case)]492		impl<$($ident),+> AbiWrite for ($($ident,)+)493		where494			$($ident: AbiWrite,)+495		{496			fn abi_write(&self, writer: &mut AbiWriter) {497				let ($($ident,)+) = self;498				if writer.is_dynamic {499					let mut sub = AbiWriter::new();500					$($ident.abi_write(&mut sub);)+501					writer.write_subresult(sub);502				} else {503					$($ident.abi_write(writer);)+504				}505			}506		}507508		impl<$($ident),+> Signature for ($($ident,)+)509		where510		$($ident: Signature,)+511		{512			make_signature!(513				new fixed("(")514				$(nameof($ident) fixed(","))+515				shift_left(1)516				fixed(")")517			);518		}519	};520}521522impl_tuples! {A}523impl_tuples! {A B}524impl_tuples! {A B C}525impl_tuples! {A B C D}526impl_tuples! {A B C D E}527impl_tuples! {A B C D E F}528impl_tuples! {A B C D E F G}529impl_tuples! {A B C D E F G H}530impl_tuples! {A B C D E F G H I}531impl_tuples! {A B C D E F G H I J}532533/// For questions about inability to provide custom implementations,534/// see [`AbiRead`]535pub trait AbiWrite {536	/// Write value to end of specified encoder537	fn abi_write(&self, writer: &mut AbiWriter);538	/// Specialization for [`crate::solidity_interface`] implementation,539	/// see comment in `impl AbiWrite for ResultWithPostInfo`540	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {541		let mut writer = AbiWriter::new();542		self.abi_write(&mut writer);543		Ok(writer.into())544	}545}546547/// This particular AbiWrite implementation should be split to another trait,548/// which only implements `to_result`, but due to lack of specialization feature549/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,550/// so here we abusing default trait methods for it551impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {552	fn abi_write(&self, _writer: &mut AbiWriter) {553		debug_assert!(false, "shouldn't be called, see comment")554	}555	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {556		match self {557			Ok(v) => Ok(WithPostDispatchInfo {558				post_info: v.post_info.clone(),559				data: {560					let mut out = AbiWriter::new();561					v.data.abi_write(&mut out);562					out563				},564			}),565			Err(e) => Err(e.clone()),566		}567	}568}569570macro_rules! impl_abi_writeable {571	($ty:ty, $method:ident) => {572		impl AbiWrite for $ty {573			fn abi_write(&self, writer: &mut AbiWriter) {574				writer.$method(&self)575			}576		}577	};578}579580impl_abi_writeable!(u8, uint8);581impl_abi_writeable!(u32, uint32);582impl_abi_writeable!(u128, uint128);583impl_abi_writeable!(U256, uint256);584impl_abi_writeable!(H160, address);585impl_abi_writeable!(bool, bool);586impl_abi_writeable!(&str, string);587588impl AbiWrite for string {589	fn abi_write(&self, writer: &mut AbiWriter) {590		writer.string(self)591	}592}593594impl AbiWrite for bytes {595	fn abi_write(&self, writer: &mut AbiWriter) {596		writer.bytes(self.0.as_slice())597	}598}599600impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {601	fn abi_write(&self, writer: &mut AbiWriter) {602		let is_dynamic = T::is_dynamic();603		let mut sub = if is_dynamic {604			AbiWriter::new_dynamic(is_dynamic)605		} else {606			AbiWriter::new()607		};608609		// Write items count610		(self.len() as u32).abi_write(&mut sub);611612		for item in self {613			item.abi_write(&mut sub);614		}615		writer.write_subresult(sub);616	}617}618619impl AbiWrite for () {620	fn abi_write(&self, _writer: &mut AbiWriter) {}621}622623/// Helper macros to parse reader into variables624#[deprecated]625#[macro_export]626macro_rules! abi_decode {627	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {628		$(629			let $name = $reader.$typ()?;630		)+631	}632}633634/// Helper macros to construct RLP-encoded buffer635#[deprecated]636#[macro_export]637macro_rules! abi_encode {638	($($typ:ident($value:expr)),* $(,)?) => {{639		#[allow(unused_mut)]640		let mut writer = ::evm_coder::abi::AbiWriter::new();641		$(642			writer.$typ($value);643		)*644		writer645	}};646	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{647		#[allow(unused_mut)]648		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);649		$(650			writer.$typ($value);651		)*652		writer653	}}654}655656#[cfg(test)]657pub mod test {658	use crate::{659		abi::{AbiRead, AbiWrite},660		types::*,661	};662663	use super::{AbiReader, AbiWriter};664	use hex_literal::hex;665	use primitive_types::{H160, U256};666	use concat_idents::concat_idents;667668	macro_rules! test_impl {669		($name:ident, $type:ty, $function_identifier:expr, $decoded_data:expr, $encoded_data:expr) => {670			concat_idents!(test_name = encode_decode_, $name {671				#[test]672				fn test_name() {673					let function_identifier: u32 = $function_identifier;674					let decoded_data = $decoded_data;675					let encoded_data = $encoded_data;676677					let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();678					assert_eq!(call, u32::to_be_bytes(function_identifier));679					let data = <$type>::abi_read(&mut decoder).unwrap();680					assert_eq!(data, decoded_data);681682					let mut writer = AbiWriter::new_call(function_identifier);683					decoded_data.abi_write(&mut writer);684					let ed = writer.finish();685					similar_asserts::assert_eq!(encoded_data, ed.as_slice());686				}687			});688		};689	}690691	macro_rules! test_impl_uint {692		($type:ident) => {693			test_impl!(694				$type,695				$type,696				0xdeadbeef,697				255 as $type,698				&hex!(699					"700						deadbeef701						00000000000000000000000000000000000000000000000000000000000000ff702					"703				)704			);705		};706	}707708	test_impl_uint!(uint8);709	test_impl_uint!(uint32);710	test_impl_uint!(uint128);711712	test_impl!(713		uint256,714		uint256,715		0xdeadbeef,716		U256([255, 0, 0, 0]),717		&hex!(718			"719				deadbeef720				00000000000000000000000000000000000000000000000000000000000000ff721			"722		)723	);724725	test_impl!(726		vec_tuple_address_uint256,727		Vec<(address, uint256)>,728		0x1ACF2D55,729		vec![730			(731				H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),732				U256([10, 0, 0, 0]),733			),734			(735				H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),736				U256([20, 0, 0, 0]),737			),738			(739				H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),740				U256([30, 0, 0, 0]),741			),742		],743		&hex!(744			"745				1ACF2D55746				0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]747				0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]748	749				0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address750				000000000000000000000000000000000000000000000000000000000000000A // uint256751	752				000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address753				0000000000000000000000000000000000000000000000000000000000000014 // uint256754	755				0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address756				000000000000000000000000000000000000000000000000000000000000001E // uint256757			"758		)759	);760761	test_impl!(762		vec_tuple_uint256_string,763		Vec<(uint256, string)>,764		0xdeadbeef,765		vec![766			(1.into(), "Test URI 0".to_string()),767			(11.into(), "Test URI 1".to_string()),768			(12.into(), "Test URI 2".to_string()),769		],770		&hex!(771			"772				deadbeef773				0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]774				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]775776				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem777				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem778				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem779780				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60781				0000000000000000000000000000000000000000000000000000000000000040 // offset of string782				000000000000000000000000000000000000000000000000000000000000000a // size of string783				5465737420555249203000000000000000000000000000000000000000000000 // string784785				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0786				0000000000000000000000000000000000000000000000000000000000000040 // offset of string787				000000000000000000000000000000000000000000000000000000000000000a // size of string788				5465737420555249203100000000000000000000000000000000000000000000 // string789790				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160791				0000000000000000000000000000000000000000000000000000000000000040 // offset of string792				000000000000000000000000000000000000000000000000000000000000000a // size of string793				5465737420555249203200000000000000000000000000000000000000000000 // string794			"795		)796	);797798	#[test]799	fn dynamic_after_static() {800		let mut encoder = AbiWriter::new();801		encoder.bool(&true);802		encoder.string("test");803		let encoded = encoder.finish();804805		let mut encoder = AbiWriter::new();806		encoder.bool(&true);807		// Offset to subresult808		encoder.uint32(&(32 * 2));809		// Len of "test"810		encoder.uint32(&4);811		encoder.write_padright(&[b't', b'e', b's', b't']);812		let alternative_encoded = encoder.finish();813814		assert_eq!(encoded, alternative_encoded);815816		let mut decoder = AbiReader::new(&encoded);817		assert!(decoder.bool().unwrap());818		assert_eq!(decoder.string().unwrap(), "test");819	}820821	#[test]822	fn mint_sample() {823		let (call, mut decoder) = AbiReader::new_call(&hex!(824			"825				50bb4e7f826				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374827				0000000000000000000000000000000000000000000000000000000000000001828				0000000000000000000000000000000000000000000000000000000000000060829				0000000000000000000000000000000000000000000000000000000000000008830				5465737420555249000000000000000000000000000000000000000000000000831			"832		))833		.unwrap();834		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));835		assert_eq!(836			format!("{:?}", decoder.address().unwrap()),837			"0xad2c0954693c2b5404b7e50967d3481bea432374"838		);839		assert_eq!(decoder.uint32().unwrap(), 1);840		assert_eq!(decoder.string().unwrap(), "Test URI");841	}842843	#[test]844	fn parse_vec_with_dynamic_type() {845		let decoded_data = (846			0x36543006,847			vec![848				(1.into(), "Test URI 0".to_string()),849				(11.into(), "Test URI 1".to_string()),850				(12.into(), "Test URI 2".to_string()),851			],852		);853854		let encoded_data = &hex!(855			"856				36543006857				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address858				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]859				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]860861				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem862				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem863				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem864865				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60866				0000000000000000000000000000000000000000000000000000000000000040 // offset of string867				000000000000000000000000000000000000000000000000000000000000000a // size of string868				5465737420555249203000000000000000000000000000000000000000000000 // string869870				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0871				0000000000000000000000000000000000000000000000000000000000000040 // offset of string872				000000000000000000000000000000000000000000000000000000000000000a // size of string873				5465737420555249203100000000000000000000000000000000000000000000 // string874875				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160876				0000000000000000000000000000000000000000000000000000000000000040 // offset of string877				000000000000000000000000000000000000000000000000000000000000000a // size of string878				5465737420555249203200000000000000000000000000000000000000000000 // string879			"880		);881882		let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();883		assert_eq!(call, u32::to_be_bytes(decoded_data.0));884		let address = decoder.address().unwrap();885		let data = <Vec<(uint256, string)>>::abi_read(&mut decoder).unwrap();886		assert_eq!(data, decoded_data.1);887888		let mut writer = AbiWriter::new_call(decoded_data.0);889		address.abi_write(&mut writer);890		decoded_data.1.abi_write(&mut writer);891		let ed = writer.finish();892		similar_asserts::assert_eq!(encoded_data, ed.as_slice());893	}894}
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, SIGNATURE_SIZE_LIMIT},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	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			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)[]761	762				0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address763				000000000000000000000000000000000000000000000000000000000000000A // uint256764	765				000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address766				0000000000000000000000000000000000000000000000000000000000000014 // uint256767	768				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}