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

difftreelog

feat generate solidity and abi traits for enums

Trubnikov Sergey2022-11-29parent: #a1ef1e7.patch.diff
in: master

3 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive.rs
+++ b/crates/evm-coder/procedural/src/abi_derive.rs
@@ -44,13 +44,14 @@
 	let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());
 
 	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
-	let abi_type = impl_abi_type(name, tuple_type.clone());
-	let abi_read = impl_abi_read(name, tuple_type, tuple_names, struct_from_tuple);
-	let abi_write = impl_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);
-	let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);
-	let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count);
+	let abi_type = impl_struct_abi_type(name, tuple_type.clone());
+	let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);
+	let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);
+	let solidity_type = impl_struct_solidity_type(name, field_types.clone(), params_count);
+	let solidity_type_name =
+		impl_struct_solidity_type_name(name, field_types.clone(), params_count);
 	let solidity_struct_collect =
-		impl_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;
+		impl_struct_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;
 
 	Ok(quote! {
 		#can_be_plcaed_in_vec
@@ -69,14 +70,177 @@
 ) -> syn::Result<proc_macro2::TokenStream> {
 	let name = &ast.ident;
 	check_repr_u8(name, &ast.attrs)?;
-	check_option_validity(de)?;
+	let option_count = check_and_count_option(de)?;
+	let enum_options = de.variants.iter().map(|v| &v.ident);
+
+	let from = impl_enum_from_u8(name, enum_options.clone());
+	let solidity_option = impl_solidity_option(name, enum_options.clone());
+	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
+	let abi_type = impl_enum_abi_type(name);
+	let abi_read = impl_enum_abi_read(name);
+	let abi_write = impl_enum_abi_write(name);
+	let solidity_type_name = impl_enum_solidity_type_name(name, enum_options.clone());
+	let solidity_struct_collect =
+		impl_enum_solidity_struct_collect(name, enum_options, option_count);
+
+	Ok(quote! {
+		#from
+		#solidity_option
+		#can_be_plcaed_in_vec
+		#abi_type
+		#abi_read
+		#abi_write
+		#solidity_type_name
+		#solidity_struct_collect
+	})
+}
+
+fn impl_solidity_option<'a>(
+	name: &proc_macro2::Ident,
+	enum_options: impl Iterator<Item = &'a syn::Ident>,
+) -> proc_macro2::TokenStream {
+	let enum_options = enum_options.map(|opt| {
+		let s = name.to_string() + "." + opt.to_string().as_str();
+		let as_string = proc_macro2::Literal::string(s.as_str());
+		quote!(#name::#opt => #as_string,)
+	});
+	quote!(
+		impl ::evm_coder::solidity::SolidityEnum for #name {
+			fn solidity_option(&self) -> &str {
+				match <#name>::default() {
+					#(#enum_options)*
+				}
+			}
+		}
+	)
+}
+
+fn impl_enum_from_u8<'a>(
+	name: &proc_macro2::Ident,
+	enum_options: impl Iterator<Item = &'a syn::Ident>,
+) -> proc_macro2::TokenStream {
+	let enum_options = enum_options.enumerate().map(|(i, opt)| {
+		let n = proc_macro2::Literal::u8_suffixed(i as u8);
+		quote! {#n => Ok(#name::#opt),}
+	});
+	quote!(
+		impl TryFrom<u8> for #name {
+			type Error = &'static str;
+
+			fn try_from(value: u8) -> ::std::result::Result<Self, Self::Error> {
+				const err: &'static str = "Not convertible";
+				match value {
+					#(#enum_options)*
+					_ => Err(err)
+				}
+			}
+		}
+	)
+}
 
-	dbg!(&de);
+fn impl_enum_abi_type(name: &syn::Ident) -> proc_macro2::TokenStream {
+	quote! {
+		impl ::evm_coder::abi::AbiType for #name {
+			const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <u8 as ::evm_coder::abi::AbiType>::SIGNATURE;
 
-	Ok(quote!())
+			fn is_dynamic() -> bool {
+				<u8 as ::evm_coder::abi::AbiType>::is_dynamic()
+			}
+			fn size() -> usize {
+				<u8 as ::evm_coder::abi::AbiType>::size()
+			}
+		}
+	}
 }
 
-fn check_option_validity(de: &syn::DataEnum) -> syn::Result<()> {
+fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream {
+	quote!(
+		impl ::evm_coder::abi::AbiRead for #name {
+			fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {
+				Ok(
+					<u8 as ::evm_coder::abi::AbiRead>::abi_read(reader)?
+						.try_into()?
+				)
+			}
+		}
+	)
+}
+
+fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream {
+	quote!(
+		impl ::evm_coder::abi::AbiWrite for #name {
+			fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {
+				::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer);
+			}
+		}
+	)
+}
+
+fn impl_enum_solidity_type_name<'a>(
+	name: &syn::Ident,
+	enum_options: impl Iterator<Item = &'a syn::Ident>,
+) -> proc_macro2::TokenStream {
+	let enum_options = enum_options.map(|opt| quote!(,));
+	quote!(
+		#[cfg(feature = "stubgen")]
+		impl ::evm_coder::solidity::SolidityTypeName for #name {
+			fn solidity_name(
+				writer: &mut impl ::core::fmt::Write,
+				tc: &::evm_coder::solidity::TypeCollector,
+			) -> ::core::fmt::Result {
+				write!(writer, "{}", tc.collect_struct::<Self>())
+			}
+
+			fn is_simple() -> bool {
+				true
+			}
+
+			fn solidity_default(
+				writer: &mut impl ::core::fmt::Write,
+				tc: &::evm_coder::solidity::TypeCollector,
+			) -> ::core::fmt::Result {
+				write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default()))
+			}
+		}
+	)
+}
+
+fn impl_enum_solidity_struct_collect<'a>(
+	name: &syn::Ident,
+	enum_options: impl Iterator<Item = &'a syn::Ident>,
+	option_count: usize,
+) -> proc_macro2::TokenStream {
+	let string_name = name.to_string();
+	let enum_options = enum_options.enumerate().map(|(i, opt)| {
+		let opt = proc_macro2::Literal::string(opt.to_string().as_str());
+		let comma = if i != option_count - 1 { "," } else { "" };
+		quote! {
+			writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option");
+		}
+	});
+	quote!(
+		#[cfg(feature = "stubgen")]
+		impl ::evm_coder::solidity::StructCollect for #name {
+			fn name() -> String {
+				#string_name.into()
+			}
+
+			fn declaration() -> String {
+				use std::fmt::Write;
+
+				let mut str = String::new();
+				// #(#docs)*
+				writeln!(str, "enum {} {{", <Self as ::evm_coder::solidity::StructCollect>::name()).unwrap();
+				#(#enum_options)*
+				writeln!(str, "}}").unwrap();
+				str
+			}
+		}
+	)
+}
+
+fn check_and_count_option(de: &syn::DataEnum) -> syn::Result<usize> {
+	let mut count = 0;
 	for error in de.variants.iter().filter_map(|v| {
 		if !v.fields.is_empty() {
 			Some(Err(syn::Error::new(
@@ -89,13 +253,14 @@
 				"Enumeration options should not have an explicit specified value",
 			)))
 		} else {
+			count += 1;
 			None
 		}
 	}) {
 		return error;
 	}
 
-	Ok(())
+	Ok(count)
 }
 
 fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {
@@ -271,7 +436,7 @@
 	}
 }
 
-fn impl_abi_type(
+fn impl_struct_abi_type(
 	name: &syn::Ident,
 	tuple_type: proc_macro2::TokenStream,
 ) -> proc_macro2::TokenStream {
@@ -288,7 +453,7 @@
 	}
 }
 
-fn impl_abi_read(
+fn impl_struct_abi_read(
 	name: &syn::Ident,
 	tuple_type: proc_macro2::TokenStream,
 	tuple_names: proc_macro2::TokenStream,
@@ -304,7 +469,7 @@
 	)
 }
 
-fn impl_abi_write(
+fn impl_struct_abi_write(
 	name: &syn::Ident,
 	_is_named_fields: bool,
 	tuple_type: proc_macro2::TokenStream,
@@ -319,7 +484,7 @@
 	)
 }
 
-fn impl_solidity_type<'a>(
+fn impl_struct_solidity_type<'a>(
 	name: &syn::Ident,
 	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
 	params_count: usize,
@@ -347,7 +512,7 @@
 	}
 }
 
-fn impl_solidity_type_name<'a>(
+fn impl_struct_solidity_type_name<'a>(
 	name: &syn::Ident,
 	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
 	params_count: usize,
@@ -390,7 +555,7 @@
 	}
 }
 
-fn impl_solidity_struct_collect<'a>(
+fn impl_struct_solidity_struct_collect<'a>(
 	name: &syn::Ident,
 	field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,
 	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
modifiedcrates/evm-coder/src/solidity/traits.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/traits.rs
+++ b/crates/evm-coder/src/solidity/traits.rs
@@ -8,6 +8,10 @@
 	fn declaration() -> String;
 }
 
+pub trait SolidityEnum: 'static {
+	fn solidity_option(&self) -> &str;
+}
+
 pub trait SolidityTypeName: 'static {
 	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
 	/// "simple" types are stored inline, no `memory` modifier should be used in solidity
modifiedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
before · crates/evm-coder/tests/abi_derive_generation.rs
1mod test_struct {2	use evm_coder_procedural::AbiCoder;3	use evm_coder::types::bytes;45	#[test]6	fn empty_struct() {7		let t = trybuild::TestCases::new();8		t.compile_fail("tests/build_failed/abi_derive_struct_generation.rs");9	}1011	#[derive(AbiCoder, PartialEq, Debug)]12	struct TypeStruct1SimpleParam {13		_a: u8,14	}1516	#[derive(AbiCoder, PartialEq, Debug)]17	struct TypeStruct1DynamicParam {18		_a: String,19	}2021	#[derive(AbiCoder, PartialEq, Debug)]22	struct TypeStruct2SimpleParam {23		_a: u8,24		_b: u32,25	}2627	#[derive(AbiCoder, PartialEq, Debug)]28	struct TypeStruct2DynamicParam {29		_a: String,30		_b: bytes,31	}3233	#[derive(AbiCoder, PartialEq, Debug)]34	struct TypeStruct2MixedParam {35		_a: u8,36		_b: bytes,37	}3839	#[derive(AbiCoder, PartialEq, Debug)]40	struct TypeStruct1DerivedSimpleParam {41		_a: TypeStruct1SimpleParam,42	}4344	#[derive(AbiCoder, PartialEq, Debug)]45	struct TypeStruct2DerivedSimpleParam {46		_a: TypeStruct1SimpleParam,47		_b: TypeStruct2SimpleParam,48	}4950	#[derive(AbiCoder, PartialEq, Debug)]51	struct TypeStruct1DerivedDynamicParam {52		_a: TypeStruct1DynamicParam,53	}5455	#[derive(AbiCoder, PartialEq, Debug)]56	struct TypeStruct2DerivedDynamicParam {57		_a: TypeStruct1DynamicParam,58		_b: TypeStruct2DynamicParam,59	}6061	/// Some docs62	/// At multi63	/// line64	#[derive(AbiCoder, PartialEq, Debug)]65	struct TypeStruct3DerivedMixedParam {66		/// Docs for A67		/// multi68		/// line69		_a: TypeStruct1SimpleParam,70		/// Docs for B71		_b: TypeStruct2DynamicParam,72		/// Docs for C73		_c: TypeStruct2MixedParam,74	}7576	#[test]77	#[cfg(feature = "stubgen")]78	fn struct_collect_TypeStruct3DerivedMixedParam() {79		assert_eq!(80			<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),81			"TypeStruct3DerivedMixedParam"82		);83		assert_eq!(84			<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),85			r#"/// @dev Some docs86/// At multi87/// line88struct TypeStruct3DerivedMixedParam {89	/// @dev Docs for A90	/// multi91	/// line92	TypeStruct1SimpleParam _a;93	/// @dev Docs for B94	TypeStruct2DynamicParam _b;95	/// @dev Docs for C96	TypeStruct2MixedParam _c;97}98"#99		);100	}101102	#[test]103	fn impl_abi_type_signature() {104		assert_eq!(105			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE106				.as_str()107				.unwrap(),108			"(uint8)"109		);110		assert_eq!(111			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE112				.as_str()113				.unwrap(),114			"(string)"115		);116		assert_eq!(117			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE118				.as_str()119				.unwrap(),120			"(uint8,uint32)"121		);122		assert_eq!(123			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE124				.as_str()125				.unwrap(),126			"(string,bytes)"127		);128		assert_eq!(129			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE130				.as_str()131				.unwrap(),132			"(uint8,bytes)"133		);134		assert_eq!(135			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE136				.as_str()137				.unwrap(),138			"((uint8))"139		);140		assert_eq!(141			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE142				.as_str()143				.unwrap(),144			"((uint8),(uint8,uint32))"145		);146		assert_eq!(147			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE148				.as_str()149				.unwrap(),150			"((string))"151		);152		assert_eq!(153			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE154				.as_str()155				.unwrap(),156			"((string),(string,bytes))"157		);158		assert_eq!(159			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE160				.as_str()161				.unwrap(),162			"((uint8),(string,bytes),(uint8,bytes))"163		);164	}165166	#[test]167	fn impl_abi_type_is_dynamic() {168		assert_eq!(169			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),170			false171		);172		assert_eq!(173			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),174			true175		);176		assert_eq!(177			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),178			false179		);180		assert_eq!(181			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),182			true183		);184		assert_eq!(185			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),186			true187		);188		assert_eq!(189			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),190			false191		);192		assert_eq!(193			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),194			false195		);196		assert_eq!(197			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),198			true199		);200		assert_eq!(201			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),202			true203		);204		assert_eq!(205			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),206			true207		);208	}209210	#[test]211	fn impl_abi_type_size() {212		const ABI_ALIGNMENT: usize = 32;213		assert_eq!(214			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),215			ABI_ALIGNMENT216		);217		assert_eq!(218			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),219			ABI_ALIGNMENT220		);221		assert_eq!(222			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),223			ABI_ALIGNMENT * 2224		);225		assert_eq!(226			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),227			ABI_ALIGNMENT * 2228		);229		assert_eq!(230			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),231			ABI_ALIGNMENT * 2232		);233		assert_eq!(234			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),235			ABI_ALIGNMENT236		);237		assert_eq!(238			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),239			ABI_ALIGNMENT * 3240		);241		assert_eq!(242			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),243			ABI_ALIGNMENT244		);245		assert_eq!(246			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),247			ABI_ALIGNMENT * 3248		);249		assert_eq!(250			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),251			ABI_ALIGNMENT * 5252		);253	}254255	#[derive(AbiCoder, PartialEq, Debug)]256	struct TupleStruct1SimpleParam(u8);257258	#[derive(AbiCoder, PartialEq, Debug)]259	struct TupleStruct1DynamicParam(String);260261	#[derive(AbiCoder, PartialEq, Debug)]262	struct TupleStruct2SimpleParam(u8, u32);263264	#[derive(AbiCoder, PartialEq, Debug)]265	struct TupleStruct2DynamicParam(String, bytes);266267	#[derive(AbiCoder, PartialEq, Debug)]268	struct TupleStruct2MixedParam(u8, bytes);269270	#[derive(AbiCoder, PartialEq, Debug)]271	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);272273	#[derive(AbiCoder, PartialEq, Debug)]274	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);275276	#[derive(AbiCoder, PartialEq, Debug)]277	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);278279	#[derive(AbiCoder, PartialEq, Debug)]280	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);281282	/// Some docs283	/// At multi284	/// line285	#[derive(AbiCoder, PartialEq, Debug)]286	struct TupleStruct3DerivedMixedParam(287		/// Docs for A288		/// multi289		/// line290		TupleStruct1SimpleParam,291		/// Docs for B292		TupleStruct2DynamicParam,293		/// Docs for C294		TupleStruct2MixedParam,295	);296297	#[test]298	#[cfg(feature = "stubgen")]299	fn struct_collect_TupleStruct3DerivedMixedParam() {300		assert_eq!(301			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),302			"TupleStruct3DerivedMixedParam"303		);304		assert_eq!(305			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),306			r#"/// @dev Some docs307/// At multi308/// line309struct TupleStruct3DerivedMixedParam {310	/// @dev Docs for A311	/// multi312	/// line313	TupleStruct1SimpleParam field0;314	/// @dev Docs for B315	TupleStruct2DynamicParam field1;316	/// @dev Docs for C317	TupleStruct2MixedParam field2;318}319"#320		);321	}322323	#[test]324	fn impl_abi_type_signature_same_for_structs() {325		assert_eq!(326			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE327				.as_str()328				.unwrap(),329			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE330				.as_str()331				.unwrap()332		);333		assert_eq!(334			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE335				.as_str()336				.unwrap(),337			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE338				.as_str()339				.unwrap()340		);341		assert_eq!(342			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE343				.as_str()344				.unwrap(),345			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE346				.as_str()347				.unwrap()348		);349		assert_eq!(350			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE351				.as_str()352				.unwrap(),353			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE354				.as_str()355				.unwrap()356		);357		assert_eq!(358			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE359				.as_str()360				.unwrap(),361			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE362				.as_str()363				.unwrap(),364		);365		assert_eq!(366			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE367				.as_str()368				.unwrap(),369			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE370				.as_str()371				.unwrap(),372		);373		assert_eq!(374			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE375				.as_str()376				.unwrap(),377			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE378				.as_str()379				.unwrap(),380		);381		assert_eq!(382			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE383				.as_str()384				.unwrap(),385			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE386				.as_str()387				.unwrap(),388		);389		assert_eq!(390			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE391				.as_str()392				.unwrap(),393			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE394				.as_str()395				.unwrap(),396		);397		assert_eq!(398			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE399				.as_str()400				.unwrap(),401			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE402				.as_str()403				.unwrap(),404		);405	}406407	#[test]408	fn impl_abi_type_is_dynamic_same_for_structs() {409		assert_eq!(410			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),411			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()412		);413		assert_eq!(414			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),415			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()416		);417		assert_eq!(418			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),419			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()420		);421		assert_eq!(422			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),423			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()424		);425		assert_eq!(426			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),427			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()428		);429		assert_eq!(430			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),431			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()432		);433		assert_eq!(434			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),435			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()436		);437		assert_eq!(438			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),439			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()440		);441		assert_eq!(442			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),443			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()444		);445		assert_eq!(446			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),447			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()448		);449	}450451	#[test]452	fn impl_abi_type_size_same_for_structs() {453		assert_eq!(454			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),455			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()456		);457		assert_eq!(458			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),459			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()460		);461		assert_eq!(462			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),463			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()464		);465		assert_eq!(466			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),467			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()468		);469		assert_eq!(470			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),471			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()472		);473		assert_eq!(474			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),475			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()476		);477		assert_eq!(478			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),479			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()480		);481		assert_eq!(482			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),483			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()484		);485		assert_eq!(486			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),487			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()488		);489		assert_eq!(490			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),491			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()492		);493	}494495	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;496497	fn test_impl<Tuple, TupleStruct, TypeStruct>(498		tuple_data: Tuple,499		tuple_struct_data: TupleStruct,500		type_struct_data: TypeStruct,501	) where502		TypeStruct: evm_coder::abi::AbiWrite503			+ evm_coder::abi::AbiRead504			+ std::cmp::PartialEq505			+ std::fmt::Debug,506		TupleStruct: evm_coder::abi::AbiWrite507			+ evm_coder::abi::AbiRead508			+ std::cmp::PartialEq509			+ std::fmt::Debug,510		Tuple: evm_coder::abi::AbiWrite511			+ evm_coder::abi::AbiRead512			+ std::cmp::PartialEq513			+ std::fmt::Debug,514	{515		let encoded_type_struct = test_abi_write_impl(&type_struct_data);516		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);517		let encoded_tuple = test_abi_write_impl(&tuple_data);518519		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);520		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);521522		{523			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();524			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();525			assert_eq!(restored_struct_data, type_struct_data);526		}527		{528			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();529			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();530			assert_eq!(restored_struct_data, tuple_struct_data);531		}532533		{534			let (_, mut decoder) =535				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();536			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();537			assert_eq!(restored_tuple_data, tuple_data);538		}539		{540			let (_, mut decoder) =541				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();542			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();543			assert_eq!(restored_tuple_data, tuple_data);544		}545	}546547	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>548	where549		A: evm_coder::abi::AbiWrite550			+ evm_coder::abi::AbiRead551			+ std::cmp::PartialEq552			+ std::fmt::Debug,553	{554		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);555		data.abi_write(&mut writer);556		let encoded_tuple = writer.finish();557		encoded_tuple558	}559560	#[test]561	fn codec_struct_1_simple() {562		let _a = 0xff;563		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(564			(_a,),565			TupleStruct1SimpleParam(_a),566			TypeStruct1SimpleParam { _a },567		);568	}569570	#[test]571	fn codec_struct_1_dynamic() {572		let _a: String = "some string".into();573		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(574			(_a.clone(),),575			TupleStruct1DynamicParam(_a.clone()),576			TypeStruct1DynamicParam { _a },577		);578	}579580	#[test]581	fn codec_struct_1_derived_simple() {582		let _a: u8 = 0xff;583		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(584			((_a,),),585			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),586			TypeStruct1DerivedSimpleParam {587				_a: TypeStruct1SimpleParam { _a },588			},589		);590	}591592	#[test]593	fn codec_struct_1_derived_dynamic() {594		let _a: String = "some string".into();595		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(596			((_a.clone(),),),597			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),598			TypeStruct1DerivedDynamicParam {599				_a: TypeStruct1DynamicParam { _a },600			},601		);602	}603604	#[test]605	fn codec_struct_2_simple() {606		let _a = 0xff;607		let _b = 0xbeefbaba;608		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(609			(_a, _b),610			TupleStruct2SimpleParam(_a, _b),611			TypeStruct2SimpleParam { _a, _b },612		);613	}614615	#[test]616	fn codec_struct_2_dynamic() {617		let _a: String = "some string".into();618		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);619		test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(620			(_a.clone(), _b.clone()),621			TupleStruct2DynamicParam(_a.clone(), _b.clone()),622			TypeStruct2DynamicParam { _a, _b },623		);624	}625626	#[test]627	fn codec_struct_2_mixed() {628		let _a: u8 = 0xff;629		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);630		test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(631			(_a.clone(), _b.clone()),632			TupleStruct2MixedParam(_a.clone(), _b.clone()),633			TypeStruct2MixedParam { _a, _b },634		);635	}636637	#[test]638	fn codec_struct_2_derived_simple() {639		let _a = 0xff;640		let _b = 0xbeefbaba;641		test_impl::<642			((u8,), (u8, u32)),643			TupleStruct2DerivedSimpleParam,644			TypeStruct2DerivedSimpleParam,645		>(646			((_a,), (_a, _b)),647			TupleStruct2DerivedSimpleParam(648				TupleStruct1SimpleParam(_a),649				TupleStruct2SimpleParam(_a, _b),650			),651			TypeStruct2DerivedSimpleParam {652				_a: TypeStruct1SimpleParam { _a },653				_b: TypeStruct2SimpleParam { _a, _b },654			},655		);656	}657658	#[test]659	fn codec_struct_2_derived_dynamic() {660		let _a = "some string".to_string();661		let _b = bytes(vec![0x11, 0x22, 0x33]);662		test_impl::<663			((String,), (String, bytes)),664			TupleStruct2DerivedDynamicParam,665			TypeStruct2DerivedDynamicParam,666		>(667			((_a.clone(),), (_a.clone(), _b.clone())),668			TupleStruct2DerivedDynamicParam(669				TupleStruct1DynamicParam(_a.clone()),670				TupleStruct2DynamicParam(_a.clone(), _b.clone()),671			),672			TypeStruct2DerivedDynamicParam {673				_a: TypeStruct1DynamicParam { _a: _a.clone() },674				_b: TypeStruct2DynamicParam { _a, _b },675			},676		);677	}678679	#[test]680	fn codec_struct_3_derived_mixed() {681		let int = 0xff;682		let by = bytes(vec![0x11, 0x22, 0x33]);683		let string = "some string".to_string();684		test_impl::<685			((u8,), (String, bytes), (u8, bytes)),686			TupleStruct3DerivedMixedParam,687			TypeStruct3DerivedMixedParam,688		>(689			((int,), (string.clone(), by.clone()), (int, by.clone())),690			TupleStruct3DerivedMixedParam(691				TupleStruct1SimpleParam(int),692				TupleStruct2DynamicParam(string.clone(), by.clone()),693				TupleStruct2MixedParam(int, by.clone()),694			),695			TypeStruct3DerivedMixedParam {696				_a: TypeStruct1SimpleParam { _a: int },697				_b: TypeStruct2DynamicParam {698					_a: string.clone(),699					_b: by.clone(),700				},701				_c: TypeStruct2MixedParam { _a: int, _b: by },702			},703		);704	}705706	#[derive(AbiCoder, PartialEq, Debug)]707	struct TypeStruct2SimpleStruct1Simple {708		_a: TypeStruct2SimpleParam,709		_b: TypeStruct2SimpleParam,710		_c: u8,711	}712	#[derive(AbiCoder, PartialEq, Debug)]713	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);714715	#[test]716	fn codec_struct_2_struct_simple_1_simple() {717		let _a = 0xff;718		let _b = 0xbeefbaba;719		test_impl::<720			((u8, u32), (u8, u32), u8),721			TupleStruct2SimpleStruct1Simple,722			TypeStruct2SimpleStruct1Simple,723		>(724			((_a, _b), (_a, _b), _a),725			TupleStruct2SimpleStruct1Simple(726				TupleStruct2SimpleParam(_a, _b),727				TupleStruct2SimpleParam(_a, _b),728				_a,729			),730			TypeStruct2SimpleStruct1Simple {731				_a: TypeStruct2SimpleParam { _a, _b },732				_b: TypeStruct2SimpleParam { _a, _b },733				_c: _a,734			},735		);736	}737}738739mod test_enum {740	use evm_coder::AbiCoder;741742	#[derive(AbiCoder)]743	#[repr(u8)]744	enum Color {745		Red,746		Green,747		Blue,748	}749750	#[test]751	fn empty() {}752753	#[test]754	fn bad_enums() {755		let t = trybuild::TestCases::new();756		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");757	}758}
after · crates/evm-coder/tests/abi_derive_generation.rs
1mod test_struct {2	use evm_coder_procedural::AbiCoder;3	use evm_coder::types::bytes;45	#[test]6	fn empty_struct() {7		let t = trybuild::TestCases::new();8		t.compile_fail("tests/build_failed/abi_derive_struct_generation.rs");9	}1011	#[derive(AbiCoder, PartialEq, Debug)]12	struct TypeStruct1SimpleParam {13		_a: u8,14	}1516	#[derive(AbiCoder, PartialEq, Debug)]17	struct TypeStruct1DynamicParam {18		_a: String,19	}2021	#[derive(AbiCoder, PartialEq, Debug)]22	struct TypeStruct2SimpleParam {23		_a: u8,24		_b: u32,25	}2627	#[derive(AbiCoder, PartialEq, Debug)]28	struct TypeStruct2DynamicParam {29		_a: String,30		_b: bytes,31	}3233	#[derive(AbiCoder, PartialEq, Debug)]34	struct TypeStruct2MixedParam {35		_a: u8,36		_b: bytes,37	}3839	#[derive(AbiCoder, PartialEq, Debug)]40	struct TypeStruct1DerivedSimpleParam {41		_a: TypeStruct1SimpleParam,42	}4344	#[derive(AbiCoder, PartialEq, Debug)]45	struct TypeStruct2DerivedSimpleParam {46		_a: TypeStruct1SimpleParam,47		_b: TypeStruct2SimpleParam,48	}4950	#[derive(AbiCoder, PartialEq, Debug)]51	struct TypeStruct1DerivedDynamicParam {52		_a: TypeStruct1DynamicParam,53	}5455	#[derive(AbiCoder, PartialEq, Debug)]56	struct TypeStruct2DerivedDynamicParam {57		_a: TypeStruct1DynamicParam,58		_b: TypeStruct2DynamicParam,59	}6061	/// Some docs62	/// At multi63	/// line64	#[derive(AbiCoder, PartialEq, Debug)]65	struct TypeStruct3DerivedMixedParam {66		/// Docs for A67		/// multi68		/// line69		_a: TypeStruct1SimpleParam,70		/// Docs for B71		_b: TypeStruct2DynamicParam,72		/// Docs for C73		_c: TypeStruct2MixedParam,74	}7576	#[test]77	#[cfg(feature = "stubgen")]78	fn struct_collect_type_struct3_derived_mixed_param() {79		assert_eq!(80			<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),81			"TypeStruct3DerivedMixedParam"82		);83		assert_eq!(84			<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),85			r#"/// @dev Some docs86/// At multi87/// line88struct TypeStruct3DerivedMixedParam {89	/// @dev Docs for A90	/// multi91	/// line92	TypeStruct1SimpleParam _a;93	/// @dev Docs for B94	TypeStruct2DynamicParam _b;95	/// @dev Docs for C96	TypeStruct2MixedParam _c;97}98"#99		);100	}101102	#[test]103	fn impl_abi_type_signature() {104		assert_eq!(105			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE106				.as_str()107				.unwrap(),108			"(uint8)"109		);110		assert_eq!(111			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE112				.as_str()113				.unwrap(),114			"(string)"115		);116		assert_eq!(117			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE118				.as_str()119				.unwrap(),120			"(uint8,uint32)"121		);122		assert_eq!(123			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE124				.as_str()125				.unwrap(),126			"(string,bytes)"127		);128		assert_eq!(129			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE130				.as_str()131				.unwrap(),132			"(uint8,bytes)"133		);134		assert_eq!(135			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE136				.as_str()137				.unwrap(),138			"((uint8))"139		);140		assert_eq!(141			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE142				.as_str()143				.unwrap(),144			"((uint8),(uint8,uint32))"145		);146		assert_eq!(147			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE148				.as_str()149				.unwrap(),150			"((string))"151		);152		assert_eq!(153			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE154				.as_str()155				.unwrap(),156			"((string),(string,bytes))"157		);158		assert_eq!(159			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE160				.as_str()161				.unwrap(),162			"((uint8),(string,bytes),(uint8,bytes))"163		);164	}165166	#[test]167	fn impl_abi_type_is_dynamic() {168		assert_eq!(169			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),170			false171		);172		assert_eq!(173			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),174			true175		);176		assert_eq!(177			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),178			false179		);180		assert_eq!(181			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),182			true183		);184		assert_eq!(185			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),186			true187		);188		assert_eq!(189			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),190			false191		);192		assert_eq!(193			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),194			false195		);196		assert_eq!(197			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),198			true199		);200		assert_eq!(201			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),202			true203		);204		assert_eq!(205			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),206			true207		);208	}209210	#[test]211	fn impl_abi_type_size() {212		const ABI_ALIGNMENT: usize = 32;213		assert_eq!(214			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),215			ABI_ALIGNMENT216		);217		assert_eq!(218			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),219			ABI_ALIGNMENT220		);221		assert_eq!(222			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),223			ABI_ALIGNMENT * 2224		);225		assert_eq!(226			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),227			ABI_ALIGNMENT * 2228		);229		assert_eq!(230			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),231			ABI_ALIGNMENT * 2232		);233		assert_eq!(234			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),235			ABI_ALIGNMENT236		);237		assert_eq!(238			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),239			ABI_ALIGNMENT * 3240		);241		assert_eq!(242			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),243			ABI_ALIGNMENT244		);245		assert_eq!(246			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),247			ABI_ALIGNMENT * 3248		);249		assert_eq!(250			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),251			ABI_ALIGNMENT * 5252		);253	}254255	#[derive(AbiCoder, PartialEq, Debug)]256	struct TupleStruct1SimpleParam(u8);257258	#[derive(AbiCoder, PartialEq, Debug)]259	struct TupleStruct1DynamicParam(String);260261	#[derive(AbiCoder, PartialEq, Debug)]262	struct TupleStruct2SimpleParam(u8, u32);263264	#[derive(AbiCoder, PartialEq, Debug)]265	struct TupleStruct2DynamicParam(String, bytes);266267	#[derive(AbiCoder, PartialEq, Debug)]268	struct TupleStruct2MixedParam(u8, bytes);269270	#[derive(AbiCoder, PartialEq, Debug)]271	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);272273	#[derive(AbiCoder, PartialEq, Debug)]274	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);275276	#[derive(AbiCoder, PartialEq, Debug)]277	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);278279	#[derive(AbiCoder, PartialEq, Debug)]280	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);281282	/// Some docs283	/// At multi284	/// line285	#[derive(AbiCoder, PartialEq, Debug)]286	struct TupleStruct3DerivedMixedParam(287		/// Docs for A288		/// multi289		/// line290		TupleStruct1SimpleParam,291		/// Docs for B292		TupleStruct2DynamicParam,293		/// Docs for C294		TupleStruct2MixedParam,295	);296297	#[test]298	#[cfg(feature = "stubgen")]299	fn struct_collect_tuple_struct3_derived_mixed_param() {300		assert_eq!(301			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),302			"TupleStruct3DerivedMixedParam"303		);304		assert_eq!(305			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),306			r#"/// @dev Some docs307/// At multi308/// line309struct TupleStruct3DerivedMixedParam {310	/// @dev Docs for A311	/// multi312	/// line313	TupleStruct1SimpleParam field0;314	/// @dev Docs for B315	TupleStruct2DynamicParam field1;316	/// @dev Docs for C317	TupleStruct2MixedParam field2;318}319"#320		);321	}322323	#[test]324	fn impl_abi_type_signature_same_for_structs() {325		assert_eq!(326			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE327				.as_str()328				.unwrap(),329			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE330				.as_str()331				.unwrap()332		);333		assert_eq!(334			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE335				.as_str()336				.unwrap(),337			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE338				.as_str()339				.unwrap()340		);341		assert_eq!(342			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE343				.as_str()344				.unwrap(),345			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE346				.as_str()347				.unwrap()348		);349		assert_eq!(350			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE351				.as_str()352				.unwrap(),353			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE354				.as_str()355				.unwrap()356		);357		assert_eq!(358			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE359				.as_str()360				.unwrap(),361			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE362				.as_str()363				.unwrap(),364		);365		assert_eq!(366			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE367				.as_str()368				.unwrap(),369			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE370				.as_str()371				.unwrap(),372		);373		assert_eq!(374			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE375				.as_str()376				.unwrap(),377			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE378				.as_str()379				.unwrap(),380		);381		assert_eq!(382			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE383				.as_str()384				.unwrap(),385			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE386				.as_str()387				.unwrap(),388		);389		assert_eq!(390			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE391				.as_str()392				.unwrap(),393			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE394				.as_str()395				.unwrap(),396		);397		assert_eq!(398			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE399				.as_str()400				.unwrap(),401			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE402				.as_str()403				.unwrap(),404		);405	}406407	#[test]408	fn impl_abi_type_is_dynamic_same_for_structs() {409		assert_eq!(410			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),411			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()412		);413		assert_eq!(414			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),415			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()416		);417		assert_eq!(418			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),419			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()420		);421		assert_eq!(422			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),423			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()424		);425		assert_eq!(426			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),427			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()428		);429		assert_eq!(430			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),431			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()432		);433		assert_eq!(434			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),435			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()436		);437		assert_eq!(438			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),439			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()440		);441		assert_eq!(442			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),443			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()444		);445		assert_eq!(446			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),447			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()448		);449	}450451	#[test]452	fn impl_abi_type_size_same_for_structs() {453		assert_eq!(454			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),455			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()456		);457		assert_eq!(458			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),459			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()460		);461		assert_eq!(462			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),463			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()464		);465		assert_eq!(466			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),467			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()468		);469		assert_eq!(470			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),471			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()472		);473		assert_eq!(474			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),475			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()476		);477		assert_eq!(478			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),479			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()480		);481		assert_eq!(482			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),483			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()484		);485		assert_eq!(486			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),487			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()488		);489		assert_eq!(490			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),491			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()492		);493	}494495	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;496497	fn test_impl<Tuple, TupleStruct, TypeStruct>(498		tuple_data: Tuple,499		tuple_struct_data: TupleStruct,500		type_struct_data: TypeStruct,501	) where502		TypeStruct: evm_coder::abi::AbiWrite503			+ evm_coder::abi::AbiRead504			+ std::cmp::PartialEq505			+ std::fmt::Debug,506		TupleStruct: evm_coder::abi::AbiWrite507			+ evm_coder::abi::AbiRead508			+ std::cmp::PartialEq509			+ std::fmt::Debug,510		Tuple: evm_coder::abi::AbiWrite511			+ evm_coder::abi::AbiRead512			+ std::cmp::PartialEq513			+ std::fmt::Debug,514	{515		let encoded_type_struct = test_abi_write_impl(&type_struct_data);516		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);517		let encoded_tuple = test_abi_write_impl(&tuple_data);518519		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);520		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);521522		{523			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();524			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();525			assert_eq!(restored_struct_data, type_struct_data);526		}527		{528			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();529			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();530			assert_eq!(restored_struct_data, tuple_struct_data);531		}532533		{534			let (_, mut decoder) =535				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();536			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();537			assert_eq!(restored_tuple_data, tuple_data);538		}539		{540			let (_, mut decoder) =541				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();542			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();543			assert_eq!(restored_tuple_data, tuple_data);544		}545	}546547	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>548	where549		A: evm_coder::abi::AbiWrite550			+ evm_coder::abi::AbiRead551			+ std::cmp::PartialEq552			+ std::fmt::Debug,553	{554		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);555		data.abi_write(&mut writer);556		let encoded_tuple = writer.finish();557		encoded_tuple558	}559560	#[test]561	fn codec_struct_1_simple() {562		let _a = 0xff;563		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(564			(_a,),565			TupleStruct1SimpleParam(_a),566			TypeStruct1SimpleParam { _a },567		);568	}569570	#[test]571	fn codec_struct_1_dynamic() {572		let _a: String = "some string".into();573		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(574			(_a.clone(),),575			TupleStruct1DynamicParam(_a.clone()),576			TypeStruct1DynamicParam { _a },577		);578	}579580	#[test]581	fn codec_struct_1_derived_simple() {582		let _a: u8 = 0xff;583		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(584			((_a,),),585			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),586			TypeStruct1DerivedSimpleParam {587				_a: TypeStruct1SimpleParam { _a },588			},589		);590	}591592	#[test]593	fn codec_struct_1_derived_dynamic() {594		let _a: String = "some string".into();595		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(596			((_a.clone(),),),597			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),598			TypeStruct1DerivedDynamicParam {599				_a: TypeStruct1DynamicParam { _a },600			},601		);602	}603604	#[test]605	fn codec_struct_2_simple() {606		let _a = 0xff;607		let _b = 0xbeefbaba;608		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(609			(_a, _b),610			TupleStruct2SimpleParam(_a, _b),611			TypeStruct2SimpleParam { _a, _b },612		);613	}614615	#[test]616	fn codec_struct_2_dynamic() {617		let _a: String = "some string".into();618		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);619		test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(620			(_a.clone(), _b.clone()),621			TupleStruct2DynamicParam(_a.clone(), _b.clone()),622			TypeStruct2DynamicParam { _a, _b },623		);624	}625626	#[test]627	fn codec_struct_2_mixed() {628		let _a: u8 = 0xff;629		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);630		test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(631			(_a.clone(), _b.clone()),632			TupleStruct2MixedParam(_a.clone(), _b.clone()),633			TypeStruct2MixedParam { _a, _b },634		);635	}636637	#[test]638	fn codec_struct_2_derived_simple() {639		let _a = 0xff;640		let _b = 0xbeefbaba;641		test_impl::<642			((u8,), (u8, u32)),643			TupleStruct2DerivedSimpleParam,644			TypeStruct2DerivedSimpleParam,645		>(646			((_a,), (_a, _b)),647			TupleStruct2DerivedSimpleParam(648				TupleStruct1SimpleParam(_a),649				TupleStruct2SimpleParam(_a, _b),650			),651			TypeStruct2DerivedSimpleParam {652				_a: TypeStruct1SimpleParam { _a },653				_b: TypeStruct2SimpleParam { _a, _b },654			},655		);656	}657658	#[test]659	fn codec_struct_2_derived_dynamic() {660		let _a = "some string".to_string();661		let _b = bytes(vec![0x11, 0x22, 0x33]);662		test_impl::<663			((String,), (String, bytes)),664			TupleStruct2DerivedDynamicParam,665			TypeStruct2DerivedDynamicParam,666		>(667			((_a.clone(),), (_a.clone(), _b.clone())),668			TupleStruct2DerivedDynamicParam(669				TupleStruct1DynamicParam(_a.clone()),670				TupleStruct2DynamicParam(_a.clone(), _b.clone()),671			),672			TypeStruct2DerivedDynamicParam {673				_a: TypeStruct1DynamicParam { _a: _a.clone() },674				_b: TypeStruct2DynamicParam { _a, _b },675			},676		);677	}678679	#[test]680	fn codec_struct_3_derived_mixed() {681		let int = 0xff;682		let by = bytes(vec![0x11, 0x22, 0x33]);683		let string = "some string".to_string();684		test_impl::<685			((u8,), (String, bytes), (u8, bytes)),686			TupleStruct3DerivedMixedParam,687			TypeStruct3DerivedMixedParam,688		>(689			((int,), (string.clone(), by.clone()), (int, by.clone())),690			TupleStruct3DerivedMixedParam(691				TupleStruct1SimpleParam(int),692				TupleStruct2DynamicParam(string.clone(), by.clone()),693				TupleStruct2MixedParam(int, by.clone()),694			),695			TypeStruct3DerivedMixedParam {696				_a: TypeStruct1SimpleParam { _a: int },697				_b: TypeStruct2DynamicParam {698					_a: string.clone(),699					_b: by.clone(),700				},701				_c: TypeStruct2MixedParam { _a: int, _b: by },702			},703		);704	}705706	#[derive(AbiCoder, PartialEq, Debug)]707	struct TypeStruct2SimpleStruct1Simple {708		_a: TypeStruct2SimpleParam,709		_b: TypeStruct2SimpleParam,710		_c: u8,711	}712	#[derive(AbiCoder, PartialEq, Debug)]713	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);714715	#[test]716	fn codec_struct_2_struct_simple_1_simple() {717		let _a = 0xff;718		let _b = 0xbeefbaba;719		test_impl::<720			((u8, u32), (u8, u32), u8),721			TupleStruct2SimpleStruct1Simple,722			TypeStruct2SimpleStruct1Simple,723		>(724			((_a, _b), (_a, _b), _a),725			TupleStruct2SimpleStruct1Simple(726				TupleStruct2SimpleParam(_a, _b),727				TupleStruct2SimpleParam(_a, _b),728				_a,729			),730			TypeStruct2SimpleStruct1Simple {731				_a: TypeStruct2SimpleParam { _a, _b },732				_b: TypeStruct2SimpleParam { _a, _b },733				_c: _a,734			},735		);736	}737}738739mod test_enum {740	use evm_coder::AbiCoder;741742	#[derive(AbiCoder, Default)]743	#[repr(u8)]744	enum Color {745		Red,746		Green,747		#[default]748		Blue,749	}750751	#[test]752	fn empty() {}753754	#[test]755	fn bad_enums() {756		let t = trybuild::TestCases::new();757		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");758	}759}