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

difftreelog

fix solidity param parser

Trubnikov Sergey2022-11-17parent: #2bb7a04.patch.diff
in: master

4 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
@@ -404,7 +404,11 @@
 		let name = &self.name;
 		let ty = &self.ty;
 		quote! {
-			#name: <#ty>::abi_read(reader)?
+			#name: {
+				let value = <#ty as ::evm_coder::abi::AbiRead>::abi_read(reader)?;
+				if !is_dynamic {reader.seek(<#ty as ::evm_coder::abi::AbiType>::size())};
+				value
+			}
 		}
 	}
 
@@ -630,17 +634,18 @@
 		let pascal_name = &self.pascal_name;
 		let screaming_name = &self.screaming_name;
 		if self.has_normal_args {
-			let parsers = self
-				.args
-				.iter()
-				.filter(|a| !a.is_special())
-				.map(|a| a.expand_parse());
+			let args_iter = self.args.iter().filter(|a| !a.is_special());
+			let arg_type = args_iter.clone().map(|a| &a.ty);
+			let parsers = args_iter.map(|a| a.expand_parse());
 			quote! {
-				Self::#screaming_name => return Ok(Some(Self::#pascal_name {
-					#(
-						#parsers,
-					)*
-				}))
+				Self::#screaming_name => {
+					let is_dynamic = false #(|| <#arg_type as ::evm_coder::abi::AbiType>::is_dynamic())*;
+					return Ok(Some(Self::#pascal_name {
+						#(
+							#parsers,
+						)*
+					}))
+				}
 			}
 		} else {
 			quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }
modifiedcrates/evm-coder/src/abi/impls.rsdiffbeforeafterboth
before · crates/evm-coder/src/abi/impls.rs
1use crate::{2	execution::{Result, ResultWithPostInfo, WithPostDispatchInfo},3	types::*,4	make_signature,5	custom_signature::SignatureUnit,6};7use super::{traits::*, ABI_ALIGNMENT, AbiReader, AbiWriter};8use primitive_types::{U256, H160};910#[cfg(not(feature = "std"))]11use alloc::vec::Vec;1213macro_rules! impl_abi_readable {14	($ty:ty, $method:ident, $dynamic:literal) => {15		impl sealed::CanBePlacedInVec for $ty {}1617		impl AbiType for $ty {18			const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($ty)));1920			fn is_dynamic() -> bool {21				$dynamic22			}2324			fn size() -> usize {25				ABI_ALIGNMENT26			}27		}2829		impl AbiRead for $ty {30			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {31				reader.$method()32			}33		}34	};35}3637impl_abi_readable!(uint32, uint32, false);38impl_abi_readable!(uint64, uint64, false);39impl_abi_readable!(uint128, uint128, false);40impl_abi_readable!(uint256, uint256, false);41impl_abi_readable!(bytes4, bytes4, false);42impl_abi_readable!(address, address, false);43impl_abi_readable!(string, string, true);4445impl sealed::CanBePlacedInVec for bool {}4647impl AbiType for bool {48	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bool"));4950	fn is_dynamic() -> bool {51		false52	}53	fn size() -> usize {54		ABI_ALIGNMENT55	}56}57impl AbiRead for bool {58	fn abi_read(reader: &mut AbiReader) -> Result<bool> {59		reader.bool()60	}61}6263impl AbiType for uint8 {64	const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));6566	fn is_dynamic() -> bool {67		false68	}69	fn size() -> usize {70		ABI_ALIGNMENT71	}72}73impl AbiRead for uint8 {74	fn abi_read(reader: &mut AbiReader) -> Result<uint8> {75		reader.uint8()76	}77}7879impl AbiType for bytes {80	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bytes"));8182	fn is_dynamic() -> bool {83		true84	}85	fn size() -> usize {86		ABI_ALIGNMENT87	}88}89impl AbiRead for bytes {90	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {91		Ok(bytes(reader.bytes()?))92	}93}9495impl<R: AbiType + AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {96	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {97		let mut sub = reader.subresult(None)?;98		let size = sub.uint32()? as usize;99		sub.subresult_offset = sub.offset;100		let mut out = Vec::with_capacity(size);101		for _ in 0..size {102			out.push(<R>::abi_read(&mut sub)?);103			if !<R>::is_dynamic() {104				sub.subresult_offset += <R>::size()105			};106		}107		Ok(out)108	}109}110111impl<R: AbiType> AbiType for Vec<R> {112	const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]"));113114	fn is_dynamic() -> bool {115		true116	}117118	fn size() -> usize {119		ABI_ALIGNMENT120	}121}122123impl sealed::CanBePlacedInVec for Property {}124125impl AbiType for Property {126	const SIGNATURE: SignatureUnit = make_signature!(new fixed("(string,bytes)"));127128	fn is_dynamic() -> bool {129		string::is_dynamic() || bytes::is_dynamic()130	}131132	fn size() -> usize {133		<string as AbiType>::size() + <bytes as AbiType>::size()134	}135}136137impl AbiRead for Property {138	fn abi_read(reader: &mut AbiReader) -> Result<Property> {139		let size = if !Property::is_dynamic() {140			Some(<Property as AbiType>::size())141		} else {142			None143		};144		let mut subresult = reader.subresult(size)?;145		let key = <string>::abi_read(&mut subresult)?;146		let value = <bytes>::abi_read(&mut subresult)?;147148		Ok(Property { key, value })149	}150}151152impl AbiWrite for Property {153	fn abi_write(&self, writer: &mut AbiWriter) {154		(&self.key, &self.value).abi_write(writer);155	}156}157158macro_rules! impl_abi_writeable {159	($ty:ty, $method:ident) => {160		impl AbiWrite for $ty {161			fn abi_write(&self, writer: &mut AbiWriter) {162				writer.$method(&self)163			}164		}165	};166}167168impl_abi_writeable!(u8, uint8);169impl_abi_writeable!(u32, uint32);170impl_abi_writeable!(u128, uint128);171impl_abi_writeable!(U256, uint256);172impl_abi_writeable!(H160, address);173impl_abi_writeable!(bool, bool);174impl_abi_writeable!(&str, string);175176impl AbiWrite for string {177	fn abi_write(&self, writer: &mut AbiWriter) {178		writer.string(self)179	}180}181182impl AbiWrite for bytes {183	fn abi_write(&self, writer: &mut AbiWriter) {184		writer.bytes(self.0.as_slice())185	}186}187188impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {189	fn abi_write(&self, writer: &mut AbiWriter) {190		let is_dynamic = T::is_dynamic();191		let mut sub = if is_dynamic {192			AbiWriter::new_dynamic(is_dynamic)193		} else {194			AbiWriter::new()195		};196197		// Write items count198		(self.len() as u32).abi_write(&mut sub);199200		for item in self {201			item.abi_write(&mut sub);202		}203		writer.write_subresult(sub);204	}205}206207impl AbiWrite for () {208	fn abi_write(&self, _writer: &mut AbiWriter) {}209}210211/// This particular AbiWrite implementation should be split to another trait,212/// which only implements `to_result`, but due to lack of specialization feature213/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,214/// so here we abusing default trait methods for it215impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {216	fn abi_write(&self, _writer: &mut AbiWriter) {217		debug_assert!(false, "shouldn't be called, see comment")218	}219	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {220		match self {221			Ok(v) => Ok(WithPostDispatchInfo {222				post_info: v.post_info.clone(),223				data: {224					let mut out = AbiWriter::new();225					v.data.abi_write(&mut out);226					out227				},228			}),229			Err(e) => Err(e.clone()),230		}231	}232}233234macro_rules! impl_tuples {235	($($ident:ident)+) => {236		impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)237		where238        $(239            $ident: AbiType,240        )+241		{242            const SIGNATURE: SignatureUnit = make_signature!(243                new fixed("(")244                $(nameof(<$ident>::SIGNATURE) fixed(","))+245                shift_left(1)246                fixed(")")247            );248249			fn is_dynamic() -> bool {250				false251				$(252					|| <$ident>::is_dynamic()253				)*254			}255256			fn size() -> usize {257				0 $(+ <$ident>::size())+258			}259		}260261		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}262263		impl<$($ident),+> AbiRead for ($($ident,)+)264		where265			$($ident: AbiRead + AbiType,)+266			($($ident,)+): AbiType,267		{268			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {269				let is_dynamic = <($($ident,)+)>::is_dynamic();270				let size = if !is_dynamic { Some(<($($ident,)+)>::size()) } else { None };271				let mut subresult = reader.subresult(size)?;272				Ok((273					$({274						let value = <$ident>::abi_read(&mut subresult)?;275						if !is_dynamic {subresult.seek(<$ident as AbiType>::size())};276						value277					},)+278				))279			}280		}281282		#[allow(non_snake_case)]283		impl<$($ident),+> AbiWrite for ($($ident,)+)284		where285			$($ident: AbiWrite + AbiType,)+286		{287			fn abi_write(&self, writer: &mut AbiWriter) {288				let ($($ident,)+) = self;289				if <Self as AbiType>::is_dynamic() {290					let mut sub = AbiWriter::new();291					$($ident.abi_write(&mut sub);)+292					writer.write_subresult(sub);293				} else {294					$($ident.abi_write(writer);)+295				}296			}297		}298	};299}300301impl_tuples! {A}302impl_tuples! {A B}303impl_tuples! {A B C}304impl_tuples! {A B C D}305impl_tuples! {A B C D E}306impl_tuples! {A B C D E F}307impl_tuples! {A B C D E F G}308impl_tuples! {A B C D E F G H}309impl_tuples! {A B C D E F G H I}310impl_tuples! {A B C D E F G H I J}
after · crates/evm-coder/src/abi/impls.rs
1use crate::{2	execution::{Result, ResultWithPostInfo, WithPostDispatchInfo},3	types::*,4	make_signature,5	custom_signature::SignatureUnit,6};7use super::{traits::*, ABI_ALIGNMENT, AbiReader, AbiWriter};8use primitive_types::{U256, H160};910#[cfg(not(feature = "std"))]11use alloc::vec::Vec;1213macro_rules! impl_abi_readable {14	($ty:ty, $method:ident, $dynamic:literal) => {15		impl sealed::CanBePlacedInVec for $ty {}1617		impl AbiType for $ty {18			const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($ty)));1920			fn is_dynamic() -> bool {21				$dynamic22			}2324			fn size() -> usize {25				ABI_ALIGNMENT26			}27		}2829		impl AbiRead for $ty {30			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {31				reader.$method()32			}33		}34	};35}3637impl_abi_readable!(uint32, uint32, false);38impl_abi_readable!(uint64, uint64, false);39impl_abi_readable!(uint128, uint128, false);40impl_abi_readable!(uint256, uint256, false);41impl_abi_readable!(bytes4, bytes4, false);42impl_abi_readable!(address, address, false);43impl_abi_readable!(string, string, true);4445impl sealed::CanBePlacedInVec for bool {}4647impl AbiType for bool {48	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bool"));4950	fn is_dynamic() -> bool {51		false52	}53	fn size() -> usize {54		ABI_ALIGNMENT55	}56}57impl AbiRead for bool {58	fn abi_read(reader: &mut AbiReader) -> Result<bool> {59		reader.bool()60	}61}6263impl AbiType for uint8 {64	const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));6566	fn is_dynamic() -> bool {67		false68	}69	fn size() -> usize {70		ABI_ALIGNMENT71	}72}73impl AbiRead for uint8 {74	fn abi_read(reader: &mut AbiReader) -> Result<uint8> {75		reader.uint8()76	}77}7879impl AbiType for bytes {80	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bytes"));8182	fn is_dynamic() -> bool {83		true84	}85	fn size() -> usize {86		ABI_ALIGNMENT87	}88}89impl AbiRead for bytes {90	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {91		Ok(bytes(reader.bytes()?))92	}93}9495impl<R: AbiType + AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {96	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {97		let mut sub = reader.subresult(None)?;98		let size = sub.uint32()? as usize;99		sub.subresult_offset = sub.offset;100		let mut out = Vec::with_capacity(size);101		for _ in 0..size {102			out.push(<R>::abi_read(&mut sub)?);103			if !<R>::is_dynamic() {104				sub.subresult_offset += <R>::size()105			};106		}107		Ok(out)108	}109}110111impl<R: AbiType> AbiType for Vec<R> {112	const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]"));113114	fn is_dynamic() -> bool {115		true116	}117118	fn size() -> usize {119		ABI_ALIGNMENT120	}121}122123impl sealed::CanBePlacedInVec for Property {}124125impl AbiType for Property {126	const SIGNATURE: SignatureUnit = make_signature!(new fixed("(string,bytes)"));127128	fn is_dynamic() -> bool {129		string::is_dynamic() || bytes::is_dynamic()130	}131132	fn size() -> usize {133		<string as AbiType>::size() + <bytes as AbiType>::size()134	}135}136137impl AbiRead for Property {138	fn abi_read(reader: &mut AbiReader) -> Result<Property> {139		let size = if !Property::is_dynamic() {140			Some(<Property as AbiType>::size())141		} else {142			None143		};144		let mut subresult = reader.subresult(size)?;145		let key = <string>::abi_read(&mut subresult)?;146		let value = <bytes>::abi_read(&mut subresult)?;147148		Ok(Property { key, value })149	}150}151152impl AbiWrite for Property {153	fn abi_write(&self, writer: &mut AbiWriter) {154		(&self.key, &self.value).abi_write(writer);155	}156}157158macro_rules! impl_abi_writeable {159	($ty:ty, $method:ident) => {160		impl AbiWrite for $ty {161			fn abi_write(&self, writer: &mut AbiWriter) {162				writer.$method(&self)163			}164		}165	};166}167168impl_abi_writeable!(u8, uint8);169impl_abi_writeable!(u32, uint32);170impl_abi_writeable!(u128, uint128);171impl_abi_writeable!(U256, uint256);172impl_abi_writeable!(H160, address);173impl_abi_writeable!(bool, bool);174impl_abi_writeable!(&str, string);175176impl AbiWrite for string {177	fn abi_write(&self, writer: &mut AbiWriter) {178		writer.string(self)179	}180}181182impl AbiWrite for bytes {183	fn abi_write(&self, writer: &mut AbiWriter) {184		writer.bytes(self.0.as_slice())185	}186}187188impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {189	fn abi_write(&self, writer: &mut AbiWriter) {190		let is_dynamic = T::is_dynamic();191		let mut sub = if is_dynamic {192			AbiWriter::new_dynamic(is_dynamic)193		} else {194			AbiWriter::new()195		};196197		// Write items count198		(self.len() as u32).abi_write(&mut sub);199200		for item in self {201			item.abi_write(&mut sub);202		}203		writer.write_subresult(sub);204	}205}206207impl AbiWrite for () {208	fn abi_write(&self, _writer: &mut AbiWriter) {}209}210211/// This particular AbiWrite implementation should be split to another trait,212/// which only implements `to_result`, but due to lack of specialization feature213/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,214/// so here we abusing default trait methods for it215impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {216	fn abi_write(&self, _writer: &mut AbiWriter) {217		debug_assert!(false, "shouldn't be called, see comment")218	}219	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {220		match self {221			Ok(v) => Ok(WithPostDispatchInfo {222				post_info: v.post_info.clone(),223				data: {224					let mut out = AbiWriter::new();225					v.data.abi_write(&mut out);226					out227				},228			}),229			Err(e) => Err(e.clone()),230		}231	}232}233234macro_rules! impl_tuples {235	($($ident:ident)+) => {236		impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)237		where238        $(239            $ident: AbiType,240        )+241		{242            const SIGNATURE: SignatureUnit = make_signature!(243                new fixed("(")244                $(nameof(<$ident>::SIGNATURE) fixed(","))+245                shift_left(1)246                fixed(")")247            );248249			fn is_dynamic() -> bool {250				false251				$(252					|| <$ident>::is_dynamic()253				)*254			}255256			fn size() -> usize {257				0 $(+ <$ident>::size())+258			}259		}260261		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}262263		impl<$($ident),+> AbiRead for ($($ident,)+)264		where265			Self: AbiType,266			$($ident: AbiRead + AbiType,)+267		{268			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {269				let is_dynamic = <Self>::is_dynamic();270				let size = if !is_dynamic { Some(<Self>::size()) } else { None };271				let mut subresult = reader.subresult(size)?;272				Ok((273					$({274						let value = <$ident>::abi_read(&mut subresult)?;275						if !is_dynamic {subresult.seek(<$ident as AbiType>::size())};276						value277					},)+278				))279			}280		}281282		#[allow(non_snake_case)]283		impl<$($ident),+> AbiWrite for ($($ident,)+)284		where285			$($ident: AbiWrite + AbiType,)+286		{287			fn abi_write(&self, writer: &mut AbiWriter) {288				let ($($ident,)+) = self;289				if <Self as AbiType>::is_dynamic() {290					let mut sub = AbiWriter::new();291					$($ident.abi_write(&mut sub);)+292					writer.write_subresult(sub);293				} else {294					$($ident.abi_write(writer);)+295				}296			}297		}298	};299}300301impl_tuples! {A}302impl_tuples! {A B}303impl_tuples! {A B C}304impl_tuples! {A B C D}305impl_tuples! {A B C D E}306impl_tuples! {A B C D E F}307impl_tuples! {A B C D E F G}308impl_tuples! {A B C D E F G H}309impl_tuples! {A B C D E F G H I}310impl_tuples! {A B C D E F G H I J}
modifiedcrates/evm-coder/src/abi/test.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi/test.rs
+++ b/crates/evm-coder/src/abi/test.rs
@@ -450,6 +450,24 @@
 }
 
 #[test]
+fn encode_decode_tuple0_tuple1_uint8_uint8_tuple1_uint8_uint8_and_uint8() {
+	test_impl::<((u8, u8), (u8, u8), u8)>(
+		0xdeadbeef,
+		((10, 11), (12, 13), 14),
+		&hex!(
+			"
+                deadbeef
+                000000000000000000000000000000000000000000000000000000000000000a
+                000000000000000000000000000000000000000000000000000000000000000b
+                000000000000000000000000000000000000000000000000000000000000000c
+                000000000000000000000000000000000000000000000000000000000000000d
+                000000000000000000000000000000000000000000000000000000000000000e
+            "
+		),
+	);
+}
+
+#[test]
 fn encode_decode_tuple0_tuple1_string() {
 	test_impl::<((String,),)>(
 		0xdeadbeef,
@@ -525,3 +543,19 @@
 		),
 	);
 }
+
+#[test]
+fn parse_multiple_params() {
+	let encoded_data = hex!(
+		"
+            deadbeef
+            000000000000000000000000000000000000000000000000000000000000000a
+            000000000000000000000000000000000000000000000000000000000000000b
+        "
+	);
+	let (_, mut decoder) = AbiReader::new_call(&encoded_data).unwrap();
+	let p1 = <u8>::abi_read(&mut decoder).unwrap();
+	let p2 = <u8>::abi_read(&mut decoder).unwrap();
+	assert_eq!(p1, 0x0a);
+	assert_eq!(p2, 0x0b);
+}
modifiedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ b/crates/evm-coder/tests/abi_derive_generation.rs
@@ -619,3 +619,35 @@
 		},
 	);
 }
+
+#[derive(AbiCoder, PartialEq, Debug)]
+struct TypeStruct2SimpleStruct1Simple {
+	_a: TypeStruct2SimpleParam,
+	_b: TypeStruct2SimpleParam,
+	_c: u8,
+}
+#[derive(AbiCoder, PartialEq, Debug)]
+struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);
+
+#[test]
+fn codec_struct_2_struct_simple_1_simple() {
+	let _a = 0xff;
+	let _b = 0xbeefbaba;
+	test_impl::<
+		((u8, u32), (u8, u32), u8),
+		TupleStruct2SimpleStruct1Simple,
+		TypeStruct2SimpleStruct1Simple,
+	>(
+		((_a, _b), (_a, _b), _a),
+		TupleStruct2SimpleStruct1Simple(
+			TupleStruct2SimpleParam(_a, _b),
+			TupleStruct2SimpleParam(_a, _b),
+			_a,
+		),
+		TypeStruct2SimpleStruct1Simple {
+			_a: TypeStruct2SimpleParam { _a, _b },
+			_b: TypeStruct2SimpleParam { _a, _b },
+			_c: _a,
+		},
+	);
+}