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

difftreelog

refactor reuse code generation patterns

Yaroslav Bolyukin2022-12-22parent: #81e4f2e.patch.diff
in: master

22 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive/derive_enum.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
@@ -1,20 +1,52 @@
 use quote::quote;
 
+use super::extract_docs;
+
 pub fn impl_solidity_option<'a>(
+	docs: Vec<String>,
 	name: &proc_macro2::Ident,
-	enum_options: impl Iterator<Item = &'a syn::Ident>,
+	enum_options: impl Iterator<Item = &'a syn::Variant> + Clone,
 ) -> proc_macro2::TokenStream {
-	let enum_options = enum_options.map(|opt| {
+	let variant_names = enum_options.clone().map(|opt| {
+		let opt = &opt.ident;
 		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,)
 	});
+	let solidity_name = name.to_string();
+
+	let solidity_fields = enum_options.map(|v| {
+		let docs = extract_docs(&v.attrs).expect("TODO: handle bad docs");
+		let name = v.ident.to_string();
+		quote! {
+			SolidityEnumVariant {
+				docs: &[#(#docs),*],
+				name: #name,
+			}
+		}
+	});
+
 	quote!(
 		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityEnum for #name {
+		impl ::evm_coder::solidity::SolidityEnumTy for #name {
+			fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector) -> String {
+				use evm_coder::solidity::*;
+				use core::fmt::Write;
+				let interface = SolidityEnum {
+					docs: &[#(#docs),*],
+					name: #solidity_name,
+					fields: &[#(
+						#solidity_fields,
+					)*],
+				};
+				let mut out = String::new();
+				let _ = interface.format(&mut out, tc);
+				tc.collect(out);
+				#solidity_name.to_string()
+			}
 			fn solidity_option(&self) -> &str {
 				match self {
-					#(#enum_options)*
+					#(#variant_names)*
 				}
 			}
 		}
@@ -23,11 +55,12 @@
 
 pub fn impl_enum_from_u8<'a>(
 	name: &proc_macro2::Ident,
-	enum_options: impl Iterator<Item = &'a syn::Ident>,
+	enum_options: impl Iterator<Item = &'a syn::Variant>,
 ) -> proc_macro2::TokenStream {
 	let error_str = format!("Value not convertible into enum \"{name}\"");
 	let error_str = proc_macro2::Literal::string(&error_str);
 	let enum_options = enum_options.enumerate().map(|(i, opt)| {
+		let opt = &opt.ident;
 		let n = proc_macro2::Literal::u8_suffixed(i as u8);
 		quote! {#n => Ok(#name::#opt),}
 	});
@@ -83,21 +116,6 @@
 			}
 		}
 	)
-}
-
-pub fn impl_enum_solidity_type<'a>(name: &syn::Ident) -> proc_macro2::TokenStream {
-	quote! {
-		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityType for #name {
-			fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec<String> {
-				Vec::new()
-			}
-
-			fn len() -> usize {
-				1
-			}
-		}
-	}
 }
 
 pub fn impl_enum_solidity_type_name(name: &syn::Ident) -> proc_macro2::TokenStream {
@@ -108,7 +126,7 @@
 				writer: &mut impl ::core::fmt::Write,
 				tc: &::evm_coder::solidity::TypeCollector,
 			) -> ::core::fmt::Result {
-				write!(writer, "{}", tc.collect_struct::<Self>())
+				write!(writer, "{}", tc.collect_enum::<Self>())
 			}
 
 			fn is_simple() -> bool {
@@ -119,49 +137,7 @@
 				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()))
-			}
-		}
-	)
-}
-
-pub fn impl_enum_solidity_struct_collect<'a>(
-	name: &syn::Ident,
-	enum_options: impl Iterator<Item = &'a syn::Ident>,
-	option_count: usize,
-	enum_options_docs: impl Iterator<Item = syn::Result<Vec<proc_macro2::TokenStream>>>,
-	docs: &[proc_macro2::TokenStream],
-) -> proc_macro2::TokenStream {
-	let string_name = name.to_string();
-	let enum_options = enum_options
-		.zip(enum_options_docs)
-		.enumerate()
-		.map(|(i, (opt, doc))| {
-			let opt = proc_macro2::Literal::string(opt.to_string().as_str());
-			let doc = doc.expect("Doc parsing error");
-			let comma = if i != option_count - 1 { "," } else { "" };
-			quote! {
-				#(#doc)*
-				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
+				write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnumTy>::solidity_option(&<#name>::default()))
 			}
 		}
 	)
modifiedcrates/evm-coder/procedural/src/abi_derive/derive_struct.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/derive_struct.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/derive_struct.rs
@@ -1,5 +1,6 @@
 use super::extract_docs;
 use quote::quote;
+use syn::Field;
 
 pub fn tuple_type<'a>(
 	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
@@ -87,10 +88,6 @@
 	&field.ty
 }
 
-pub fn map_field_to_doc(field: &syn::Field) -> syn::Result<Vec<proc_macro2::TokenStream>> {
-	extract_docs(&field.attrs, true)
-}
-
 pub fn impl_can_be_placed_in_vec(ident: &syn::Ident) -> proc_macro2::TokenStream {
 	quote! {
 		impl ::evm_coder::sealed::CanBePlacedInVec for #ident {}
@@ -147,27 +144,44 @@
 
 pub fn impl_struct_solidity_type<'a>(
 	name: &syn::Ident,
-	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
-	params_count: usize,
+	docs: Vec<String>,
+	fields: impl Iterator<Item = &'a Field> + Clone,
 ) -> proc_macro2::TokenStream {
-	let len = proc_macro2::Literal::usize_suffixed(params_count);
+	let solidity_name = name.to_string();
+	let solidity_fields = fields.enumerate().map(|(i, f)| {
+		let name = f
+			.ident
+			.as_ref()
+			.map(|i| i.to_string())
+			.unwrap_or_else(|| format!("field_{i}"));
+		let ty = &f.ty;
+		let docs = extract_docs(&f.attrs).expect("TODO: handle bad docs");
+		quote! {
+			SolidityStructField::<#ty> {
+				docs: &[#(#docs),*],
+				name: #name,
+				ty: ::core::marker::PhantomData,
+			}
+		}
+	});
 	quote! {
 		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityType for #name {
-			fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec<String> {
-				let mut collected =
-					Vec::with_capacity(<Self as ::evm_coder::solidity::SolidityType>::len());
-				#({
-					let mut out = String::new();
-					<#field_types as ::evm_coder::solidity::SolidityTypeName>::solidity_name(&mut out, tc)
-						.expect("no fmt error");
-					collected.push(out);
-				})*
-				collected
-			}
-
-			fn len() -> usize {
-				#len
+		impl ::evm_coder::solidity::SolidityStructTy for #name {
+			/// Generate solidity definitions for methods described in this struct
+			fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector) -> String {
+				use evm_coder::solidity::*;
+				use core::fmt::Write;
+				let interface = SolidityStruct {
+					docs: &[#(#docs),*],
+					name: #solidity_name,
+					fields: (#(
+						#solidity_fields,
+					)*),
+				};
+				let mut out = String::new();
+				let _ = interface.format(&mut out, tc);
+				tc.collect(out);
+				#solidity_name.to_string()
 			}
 		}
 	}
@@ -214,47 +228,4 @@
 			}
 		}
 	}
-}
-
-pub 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,
-	field_docs: impl Iterator<Item = syn::Result<Vec<proc_macro2::TokenStream>>> + Clone,
-	docs: &[proc_macro2::TokenStream],
-) -> syn::Result<proc_macro2::TokenStream> {
-	let string_name = name.to_string();
-	let name_type = field_names
-		.into_iter()
-		.zip(field_types)
-		.zip(field_docs)
-		.map(|((name, ty), doc)| {
-			let field_docs = doc.expect("Doc parse error");
-			let name = format!("{}", name);
-			quote!(
-				#(#field_docs)*
-				write!(str, "\t{} ", <#ty as ::evm_coder::solidity::StructCollect>::name()).unwrap();
-				writeln!(str, "{};", #name).unwrap();
-			)
-		});
-
-	Ok(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, "struct {} {{", Self::name()).unwrap();
-				#(#name_type)*
-				writeln!(str, "}}").unwrap();
-				str
-			}
-		}
-	})
 }
modifiedcrates/evm-coder/procedural/src/abi_derive/mod.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/mod.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/mod.rs
@@ -19,20 +19,18 @@
 	ast: &syn::DeriveInput,
 ) -> syn::Result<proc_macro2::TokenStream> {
 	let name = &ast.ident;
-	let docs = extract_docs(&ast.attrs, false)?;
-	let (is_named_fields, field_names, field_types, field_docs, params_count) = match ds.fields {
+	let docs = extract_docs(&ast.attrs)?;
+	let (is_named_fields, field_names, field_types, params_count) = match ds.fields {
 		syn::Fields::Named(ref fields) => Ok((
 			true,
 			fields.named.iter().enumerate().map(map_field_to_name),
 			fields.named.iter().map(map_field_to_type),
-			fields.named.iter().map(map_field_to_doc),
 			fields.named.len(),
 		)),
 		syn::Fields::Unnamed(ref fields) => Ok((
 			false,
 			fields.unnamed.iter().enumerate().map(map_field_to_name),
 			fields.unnamed.iter().map(map_field_to_type),
-			fields.unnamed.iter().map(map_field_to_doc),
 			fields.unnamed.len(),
 		)),
 		syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),
@@ -52,11 +50,9 @@
 	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 = impl_struct_solidity_type(name, docs, ds.fields.iter());
 	let solidity_type_name =
 		impl_struct_solidity_type_name(name, field_types.clone(), params_count);
-	let solidity_struct_collect =
-		impl_struct_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;
 
 	Ok(quote! {
 		#can_be_plcaed_in_vec
@@ -65,7 +61,6 @@
 		#abi_write
 		#solidity_type
 		#solidity_type_name
-		#solidity_struct_collect
 	})
 }
 
@@ -75,26 +70,16 @@
 ) -> syn::Result<proc_macro2::TokenStream> {
 	let name = &ast.ident;
 	check_repr_u8(name, &ast.attrs)?;
-	let docs = extract_docs(&ast.attrs, false)?;
-	let option_count = check_and_count_options(de)?;
-	let enum_options = de.variants.iter().map(|v| &v.ident);
-	let enum_options_docs = de.variants.iter().map(|v| extract_docs(&v.attrs, true));
+	let docs = extract_docs(&ast.attrs)?;
+	let enum_options = de.variants.iter();
 
 	let from = impl_enum_from_u8(name, enum_options.clone());
-	let solidity_option = impl_solidity_option(name, enum_options.clone());
+	let solidity_option = impl_solidity_option(docs, 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 = impl_enum_solidity_type(name);
 	let solidity_type_name = impl_enum_solidity_type_name(name);
-	let solidity_struct_collect = impl_enum_solidity_struct_collect(
-		name,
-		enum_options,
-		option_count,
-		enum_options_docs,
-		&docs,
-	);
 
 	Ok(quote! {
 		#from
@@ -103,16 +88,11 @@
 		#abi_type
 		#abi_read
 		#abi_write
-		#solidity_type
 		#solidity_type_name
-		#solidity_struct_collect
 	})
 }
 
-fn extract_docs(
-	attrs: &[syn::Attribute],
-	is_field_doc: bool,
-) -> syn::Result<Vec<proc_macro2::TokenStream>> {
+fn extract_docs(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {
 	attrs
 		.iter()
 		.filter_map(|attr| {
@@ -132,16 +112,6 @@
 				}
 			}
 			None
-		})
-		.enumerate()
-		.map(|(i, doc)| {
-			let doc = doc?;
-			let doc = doc.trim();
-			let dev = if i == 0 { " @dev" } else { "" };
-			let tab = if is_field_doc { "\t" } else { "" };
-			Ok(quote! {
-				writeln!(str, "{}///{} {}", #tab, #dev, #doc).unwrap();
-			})
 		})
 		.collect()
 }
modifiedcrates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/impls.rs
+++ b/crates/evm-coder/src/solidity/impls.rs
@@ -1,4 +1,4 @@
-use super::{TypeCollector, SolidityTypeName, SolidityType, StructCollect};
+use super::{TypeCollector, SolidityTypeName, SolidityTupleTy};
 use crate::{sealed, types::*};
 use core::fmt;
 use primitive_types::{U256, H160};
@@ -17,16 +17,6 @@
 					write!(writer, $default)
 				}
             }
-
-			impl StructCollect for $ty {
-				fn name() -> String {
-					$name.to_string()
-				}
-
-				fn declaration() -> String {
-					String::default()
-				}
-			}
         )*
     };
 }
@@ -71,17 +61,7 @@
 		write!(writer, "new ")?;
 		T::solidity_name(writer, tc)?;
 		write!(writer, "[](0)")
-	}
-}
-
-impl<T: StructCollect + sealed::CanBePlacedInVec> StructCollect for Vec<T> {
-	fn name() -> String {
-		<T as StructCollect>::name() + "[]"
 	}
-
-	fn declaration() -> String {
-		unimplemented!("Vectors have not declarations.")
-	}
 }
 
 macro_rules! count {
@@ -91,8 +71,8 @@
 
 macro_rules! impl_tuples {
 	($($ident:ident)+) => {
-		impl<$($ident: SolidityTypeName + 'static),+> SolidityType for ($($ident,)+) {
-			fn names(tc: &TypeCollector) -> Vec<string> {
+		impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleTy for ($($ident,)+) {
+			fn fields(tc: &TypeCollector) -> Vec<string> {
 				let mut collected = Vec::with_capacity(Self::len());
 				$({
 					let mut out = string::new();
modifiedcrates/evm-coder/src/solidity/mod.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/mod.rs
+++ b/crates/evm-coder/src/solidity/mod.rs
@@ -44,6 +44,7 @@
 	/// id ordering is required to perform topo-sort on the resulting data
 	structs: RefCell<BTreeMap<string, usize>>,
 	anonymous: RefCell<BTreeMap<Vec<string>, usize>>,
+	// generic: RefCell<BTreeMap<string, usize>>,
 	id: Cell<usize>,
 }
 impl TypeCollector {
@@ -59,8 +60,9 @@
 		self.id.set(v + 1);
 		v
 	}
-	pub fn collect_tuple<T: SolidityType>(&self) -> String {
-		let names = T::names(self);
+	/// Collect typle, deduplicating it by type, and returning generated name
+	pub fn collect_tuple<T: SolidityTupleTy>(&self) -> String {
+		let names = T::fields(self);
 		if let Some(id) = self.anonymous.borrow().get(&names).cloned() {
 			return format!("Tuple{}", id);
 		}
@@ -76,11 +78,12 @@
 		self.anonymous.borrow_mut().insert(names, id);
 		format!("Tuple{}", id)
 	}
-	pub fn collect_struct<T: StructCollect + SolidityType>(&self) -> String {
-		let _names = T::names(self);
-		self.collect(<T as StructCollect>::declaration());
-		<T as StructCollect>::name()
+	pub fn collect_struct<T: SolidityStructTy>(&self) -> String {
+		T::generate_solidity_interface(self)
 	}
+	pub fn collect_enum<T: SolidityEnumTy>(&self) -> String {
+		T::generate_solidity_interface(self)
+	}
 	pub fn finish(self) -> Vec<string> {
 		let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();
 		data.sort_by_key(|(_, id)| Reverse(*id));
@@ -420,3 +423,93 @@
 		writeln!(writer, ");")
 	}
 }
+
+#[impl_for_tuples(0, 48)]
+impl SolidityItems for Tuple {
+	for_tuples!( where #( Tuple: SolidityItems ),* );
+
+	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+		for_tuples!( #(
+            Tuple.solidity_name(writer, tc)?;
+        )* );
+		Ok(())
+	}
+}
+
+pub struct SolidityStructField<T> {
+	pub docs: &'static [&'static str],
+	pub name: &'static str,
+	pub ty: PhantomData<*const T>,
+}
+
+impl<T> SolidityItems for SolidityStructField<T>
+where
+	T: SolidityTypeName,
+{
+	fn solidity_name(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+		for doc in self.docs {
+			writeln!(out, "///{}", doc)?;
+		}
+		write!(out, "\t")?;
+		T::solidity_name(out, tc)?;
+		writeln!(out, " {};", self.name)?;
+		Ok(())
+	}
+}
+pub struct SolidityStruct<F> {
+	pub docs: &'static [&'static str],
+	// pub generics:
+	pub name: &'static str,
+	pub fields: F,
+}
+impl<F> SolidityStruct<F>
+where
+	F: SolidityItems,
+{
+	pub fn format(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+		for doc in self.docs {
+			writeln!(out, "///{}", doc)?;
+		}
+		writeln!(out, "struct {} {{", self.name)?;
+		self.fields.solidity_name(out, tc)?;
+		writeln!(out, "}}")?;
+		Ok(())
+	}
+}
+
+pub struct SolidityEnumVariant {
+	pub docs: &'static [&'static str],
+	pub name: &'static str,
+}
+impl SolidityItems for SolidityEnumVariant {
+	fn solidity_name(&self, out: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
+		for doc in self.docs {
+			writeln!(out, "///{}", doc)?;
+		}
+		write!(out, "\t{}", self.name)?;
+		Ok(())
+	}
+}
+pub struct SolidityEnum {
+	pub docs: &'static [&'static str],
+	pub name: &'static str,
+	pub fields: &'static [SolidityEnumVariant],
+}
+impl SolidityEnum {
+	pub fn format(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+		for doc in self.docs {
+			writeln!(out, "///{}", doc)?;
+		}
+		write!(out, "enum {} {{", self.name)?;
+		for (i, field) in self.fields.iter().enumerate() {
+			if i != 0 {
+				write!(out, ",")?;
+			}
+			writeln!(out)?;
+			field.solidity_name(out, tc)?;
+		}
+		writeln!(out)?;
+		writeln!(out, "}}")?;
+		Ok(())
+	}
+}
modifiedcrates/evm-coder/src/solidity/traits.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/traits.rs
+++ b/crates/evm-coder/src/solidity/traits.rs
@@ -1,17 +1,6 @@
 use super::TypeCollector;
 use core::fmt;
 
-pub trait StructCollect: 'static {
-	/// Structure name.
-	fn name() -> String;
-	/// Structure declaration.
-	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
@@ -23,10 +12,17 @@
 	}
 }
 
-pub trait SolidityType {
-	fn names(tc: &TypeCollector) -> Vec<String>;
+pub trait SolidityTupleTy: 'static {
+	fn fields(tc: &TypeCollector) -> Vec<String>;
 	fn len() -> usize;
 }
+pub trait SolidityStructTy: 'static {
+	fn generate_solidity_interface(tc: &TypeCollector) -> String;
+}
+pub trait SolidityEnumTy: 'static {
+	fn generate_solidity_interface(tc: &TypeCollector) -> String;
+	fn solidity_option(&self) -> &str;
+}
 
 pub trait SolidityArguments {
 	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
@@ -46,3 +42,9 @@
 		tc: &TypeCollector,
 	) -> fmt::Result;
 }
+
+pub trait SolidityItems {
+	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
+	// For PhantomData fields
+	// fn is_void()
+}
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_type_struct3_derived_mixed_param() {79		assert_eq!(80			<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),81			"TypeStruct3DerivedMixedParam"82		);83		similar_asserts::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	#[cfg(feature = "stubgen")]104	fn struct_collect_vec() {105		assert_eq!(106			<Vec<u8> as ::evm_coder::solidity::StructCollect>::name(),107			"uint8[]"108		);109	}110111	#[test]112	fn impl_abi_type_signature() {113		assert_eq!(114			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE115				.as_str()116				.unwrap(),117			"(uint8)"118		);119		assert_eq!(120			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE121				.as_str()122				.unwrap(),123			"(string)"124		);125		assert_eq!(126			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE127				.as_str()128				.unwrap(),129			"(uint8,uint32)"130		);131		assert_eq!(132			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE133				.as_str()134				.unwrap(),135			"(string,bytes)"136		);137		assert_eq!(138			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE139				.as_str()140				.unwrap(),141			"(uint8,bytes)"142		);143		assert_eq!(144			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE145				.as_str()146				.unwrap(),147			"((uint8))"148		);149		assert_eq!(150			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE151				.as_str()152				.unwrap(),153			"((uint8),(uint8,uint32))"154		);155		assert_eq!(156			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE157				.as_str()158				.unwrap(),159			"((string))"160		);161		assert_eq!(162			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE163				.as_str()164				.unwrap(),165			"((string),(string,bytes))"166		);167		assert_eq!(168			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE169				.as_str()170				.unwrap(),171			"((uint8),(string,bytes),(uint8,bytes))"172		);173	}174175	#[test]176	fn impl_abi_type_is_dynamic() {177		assert_eq!(178			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),179			false180		);181		assert_eq!(182			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),183			true184		);185		assert_eq!(186			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),187			false188		);189		assert_eq!(190			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),191			true192		);193		assert_eq!(194			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),195			true196		);197		assert_eq!(198			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),199			false200		);201		assert_eq!(202			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),203			false204		);205		assert_eq!(206			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),207			true208		);209		assert_eq!(210			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),211			true212		);213		assert_eq!(214			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),215			true216		);217	}218219	#[test]220	fn impl_abi_type_size() {221		const ABI_ALIGNMENT: usize = 32;222		assert_eq!(223			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),224			ABI_ALIGNMENT225		);226		assert_eq!(227			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),228			ABI_ALIGNMENT229		);230		assert_eq!(231			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),232			ABI_ALIGNMENT * 2233		);234		assert_eq!(235			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),236			ABI_ALIGNMENT * 2237		);238		assert_eq!(239			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),240			ABI_ALIGNMENT * 2241		);242		assert_eq!(243			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),244			ABI_ALIGNMENT245		);246		assert_eq!(247			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),248			ABI_ALIGNMENT * 3249		);250		assert_eq!(251			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),252			ABI_ALIGNMENT253		);254		assert_eq!(255			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),256			ABI_ALIGNMENT * 3257		);258		assert_eq!(259			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),260			ABI_ALIGNMENT * 5261		);262	}263264	#[derive(AbiCoder, PartialEq, Debug)]265	struct TupleStruct1SimpleParam(u8);266267	#[derive(AbiCoder, PartialEq, Debug)]268	struct TupleStruct1DynamicParam(String);269270	#[derive(AbiCoder, PartialEq, Debug)]271	struct TupleStruct2SimpleParam(u8, u32);272273	#[derive(AbiCoder, PartialEq, Debug)]274	struct TupleStruct2DynamicParam(String, bytes);275276	#[derive(AbiCoder, PartialEq, Debug)]277	struct TupleStruct2MixedParam(u8, bytes);278279	#[derive(AbiCoder, PartialEq, Debug)]280	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);281282	#[derive(AbiCoder, PartialEq, Debug)]283	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);284285	#[derive(AbiCoder, PartialEq, Debug)]286	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);287288	#[derive(AbiCoder, PartialEq, Debug)]289	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);290291	/// Some docs292	/// At multi293	/// line294	#[derive(AbiCoder, PartialEq, Debug)]295	struct TupleStruct3DerivedMixedParam(296		/// Docs for A297		/// multi298		/// line299		TupleStruct1SimpleParam,300		TupleStruct2DynamicParam,301		/// Docs for C302		TupleStruct2MixedParam,303	);304305	#[test]306	#[cfg(feature = "stubgen")]307	fn struct_collect_tuple_struct3_derived_mixed_param() {308		assert_eq!(309			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),310			"TupleStruct3DerivedMixedParam"311		);312		similar_asserts::assert_eq!(313			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),314			r#"/// @dev Some docs315/// At multi316/// line317struct TupleStruct3DerivedMixedParam {318	/// @dev Docs for A319	/// multi320	/// line321	TupleStruct1SimpleParam field0;322	TupleStruct2DynamicParam field1;323	/// @dev Docs for C324	TupleStruct2MixedParam field2;325}326"#327		);328	}329330	#[test]331	fn impl_abi_type_signature_same_for_structs() {332		assert_eq!(333			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE334				.as_str()335				.unwrap(),336			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE337				.as_str()338				.unwrap()339		);340		assert_eq!(341			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE342				.as_str()343				.unwrap(),344			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE345				.as_str()346				.unwrap()347		);348		assert_eq!(349			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE350				.as_str()351				.unwrap(),352			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE353				.as_str()354				.unwrap()355		);356		assert_eq!(357			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE358				.as_str()359				.unwrap(),360			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE361				.as_str()362				.unwrap()363		);364		assert_eq!(365			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE366				.as_str()367				.unwrap(),368			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE369				.as_str()370				.unwrap(),371		);372		assert_eq!(373			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE374				.as_str()375				.unwrap(),376			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE377				.as_str()378				.unwrap(),379		);380		assert_eq!(381			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE382				.as_str()383				.unwrap(),384			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE385				.as_str()386				.unwrap(),387		);388		assert_eq!(389			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE390				.as_str()391				.unwrap(),392			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE393				.as_str()394				.unwrap(),395		);396		assert_eq!(397			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE398				.as_str()399				.unwrap(),400			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE401				.as_str()402				.unwrap(),403		);404		assert_eq!(405			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE406				.as_str()407				.unwrap(),408			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE409				.as_str()410				.unwrap(),411		);412	}413414	#[test]415	fn impl_abi_type_is_dynamic_same_for_structs() {416		assert_eq!(417			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),418			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()419		);420		assert_eq!(421			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),422			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()423		);424		assert_eq!(425			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),426			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()427		);428		assert_eq!(429			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),430			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()431		);432		assert_eq!(433			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),434			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()435		);436		assert_eq!(437			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),438			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()439		);440		assert_eq!(441			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),442			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()443		);444		assert_eq!(445			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),446			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()447		);448		assert_eq!(449			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),450			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()451		);452		assert_eq!(453			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),454			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()455		);456	}457458	#[test]459	fn impl_abi_type_size_same_for_structs() {460		assert_eq!(461			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),462			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()463		);464		assert_eq!(465			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),466			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()467		);468		assert_eq!(469			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),470			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()471		);472		assert_eq!(473			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),474			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()475		);476		assert_eq!(477			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),478			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()479		);480		assert_eq!(481			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),482			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()483		);484		assert_eq!(485			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),486			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()487		);488		assert_eq!(489			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),490			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()491		);492		assert_eq!(493			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),494			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()495		);496		assert_eq!(497			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),498			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()499		);500	}501502	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;503504	fn test_impl<Tuple, TupleStruct, TypeStruct>(505		tuple_data: Tuple,506		tuple_struct_data: TupleStruct,507		type_struct_data: TypeStruct,508	) where509		TypeStruct: evm_coder::abi::AbiWrite510			+ evm_coder::abi::AbiRead511			+ std::cmp::PartialEq512			+ std::fmt::Debug,513		TupleStruct: evm_coder::abi::AbiWrite514			+ evm_coder::abi::AbiRead515			+ std::cmp::PartialEq516			+ std::fmt::Debug,517		Tuple: evm_coder::abi::AbiWrite518			+ evm_coder::abi::AbiRead519			+ std::cmp::PartialEq520			+ std::fmt::Debug,521	{522		let encoded_type_struct = test_abi_write_impl(&type_struct_data);523		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);524		let encoded_tuple = test_abi_write_impl(&tuple_data);525526		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);527		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);528529		{530			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();531			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();532			assert_eq!(restored_struct_data, type_struct_data);533		}534		{535			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();536			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();537			assert_eq!(restored_struct_data, tuple_struct_data);538		}539540		{541			let (_, mut decoder) =542				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();543			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();544			assert_eq!(restored_tuple_data, tuple_data);545		}546		{547			let (_, mut decoder) =548				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();549			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();550			assert_eq!(restored_tuple_data, tuple_data);551		}552	}553554	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>555	where556		A: evm_coder::abi::AbiWrite557			+ evm_coder::abi::AbiRead558			+ std::cmp::PartialEq559			+ std::fmt::Debug,560	{561		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);562		data.abi_write(&mut writer);563		let encoded_tuple = writer.finish();564		encoded_tuple565	}566567	#[test]568	fn codec_struct_1_simple() {569		let _a = 0xff;570		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(571			(_a,),572			TupleStruct1SimpleParam(_a),573			TypeStruct1SimpleParam { _a },574		);575	}576577	#[test]578	fn codec_struct_1_dynamic() {579		let _a: String = "some string".into();580		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(581			(_a.clone(),),582			TupleStruct1DynamicParam(_a.clone()),583			TypeStruct1DynamicParam { _a },584		);585	}586587	#[test]588	fn codec_struct_1_derived_simple() {589		let _a: u8 = 0xff;590		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(591			((_a,),),592			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),593			TypeStruct1DerivedSimpleParam {594				_a: TypeStruct1SimpleParam { _a },595			},596		);597	}598599	#[test]600	fn codec_struct_1_derived_dynamic() {601		let _a: String = "some string".into();602		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(603			((_a.clone(),),),604			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),605			TypeStruct1DerivedDynamicParam {606				_a: TypeStruct1DynamicParam { _a },607			},608		);609	}610611	#[test]612	fn codec_struct_2_simple() {613		let _a = 0xff;614		let _b = 0xbeefbaba;615		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(616			(_a, _b),617			TupleStruct2SimpleParam(_a, _b),618			TypeStruct2SimpleParam { _a, _b },619		);620	}621622	#[test]623	fn codec_struct_2_dynamic() {624		let _a: String = "some string".into();625		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);626		test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(627			(_a.clone(), _b.clone()),628			TupleStruct2DynamicParam(_a.clone(), _b.clone()),629			TypeStruct2DynamicParam { _a, _b },630		);631	}632633	#[test]634	fn codec_struct_2_mixed() {635		let _a: u8 = 0xff;636		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);637		test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(638			(_a.clone(), _b.clone()),639			TupleStruct2MixedParam(_a.clone(), _b.clone()),640			TypeStruct2MixedParam { _a, _b },641		);642	}643644	#[test]645	fn codec_struct_2_derived_simple() {646		let _a = 0xff;647		let _b = 0xbeefbaba;648		test_impl::<649			((u8,), (u8, u32)),650			TupleStruct2DerivedSimpleParam,651			TypeStruct2DerivedSimpleParam,652		>(653			((_a,), (_a, _b)),654			TupleStruct2DerivedSimpleParam(655				TupleStruct1SimpleParam(_a),656				TupleStruct2SimpleParam(_a, _b),657			),658			TypeStruct2DerivedSimpleParam {659				_a: TypeStruct1SimpleParam { _a },660				_b: TypeStruct2SimpleParam { _a, _b },661			},662		);663	}664665	#[test]666	fn codec_struct_2_derived_dynamic() {667		let _a = "some string".to_string();668		let _b = bytes(vec![0x11, 0x22, 0x33]);669		test_impl::<670			((String,), (String, bytes)),671			TupleStruct2DerivedDynamicParam,672			TypeStruct2DerivedDynamicParam,673		>(674			((_a.clone(),), (_a.clone(), _b.clone())),675			TupleStruct2DerivedDynamicParam(676				TupleStruct1DynamicParam(_a.clone()),677				TupleStruct2DynamicParam(_a.clone(), _b.clone()),678			),679			TypeStruct2DerivedDynamicParam {680				_a: TypeStruct1DynamicParam { _a: _a.clone() },681				_b: TypeStruct2DynamicParam { _a, _b },682			},683		);684	}685686	#[test]687	fn codec_struct_3_derived_mixed() {688		let int = 0xff;689		let by = bytes(vec![0x11, 0x22, 0x33]);690		let string = "some string".to_string();691		test_impl::<692			((u8,), (String, bytes), (u8, bytes)),693			TupleStruct3DerivedMixedParam,694			TypeStruct3DerivedMixedParam,695		>(696			((int,), (string.clone(), by.clone()), (int, by.clone())),697			TupleStruct3DerivedMixedParam(698				TupleStruct1SimpleParam(int),699				TupleStruct2DynamicParam(string.clone(), by.clone()),700				TupleStruct2MixedParam(int, by.clone()),701			),702			TypeStruct3DerivedMixedParam {703				_a: TypeStruct1SimpleParam { _a: int },704				_b: TypeStruct2DynamicParam {705					_a: string.clone(),706					_b: by.clone(),707				},708				_c: TypeStruct2MixedParam { _a: int, _b: by },709			},710		);711	}712713	#[derive(AbiCoder, PartialEq, Debug)]714	struct TypeStruct2SimpleStruct1Simple {715		_a: TypeStruct2SimpleParam,716		_b: TypeStruct2SimpleParam,717		_c: u8,718	}719	#[derive(AbiCoder, PartialEq, Debug)]720	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);721722	#[test]723	fn codec_struct_2_struct_simple_1_simple() {724		let _a = 0xff;725		let _b = 0xbeefbaba;726		test_impl::<727			((u8, u32), (u8, u32), u8),728			TupleStruct2SimpleStruct1Simple,729			TypeStruct2SimpleStruct1Simple,730		>(731			((_a, _b), (_a, _b), _a),732			TupleStruct2SimpleStruct1Simple(733				TupleStruct2SimpleParam(_a, _b),734				TupleStruct2SimpleParam(_a, _b),735				_a,736			),737			TypeStruct2SimpleStruct1Simple {738				_a: TypeStruct2SimpleParam { _a, _b },739				_b: TypeStruct2SimpleParam { _a, _b },740				_c: _a,741			},742		);743	}744}745746mod test_enum {747	use evm_coder::AbiCoder;748749	/// Some docs750	/// At multi751	/// line752	#[derive(AbiCoder, Debug, PartialEq, Default, Clone, Copy)]753	#[repr(u8)]754	enum Color {755		/// Docs for Red756		/// multi757		/// line758		Red,759		Green,760		/// Docs for Blue761		#[default]762		Blue,763	}764765	#[test]766	fn empty() {}767768	#[test]769	fn bad_enums() {770		let t = trybuild::TestCases::new();771		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");772	}773774	#[test]775	fn impl_abi_type_signature_same_for_structs() {776		assert_eq!(777			<Color as evm_coder::abi::AbiType>::SIGNATURE778				.as_str()779				.unwrap(),780			<u8 as evm_coder::abi::AbiType>::SIGNATURE.as_str().unwrap()781		);782	}783784	#[test]785	fn impl_abi_type_is_dynamic_same_for_structs() {786		assert_eq!(787			<Color as evm_coder::abi::AbiType>::is_dynamic(),788			<u8 as evm_coder::abi::AbiType>::is_dynamic()789		);790	}791792	#[test]793	fn impl_abi_type_size_same_for_structs() {794		assert_eq!(795			<Color as evm_coder::abi::AbiType>::size(),796			<u8 as evm_coder::abi::AbiType>::size()797		);798	}799800	#[test]801	fn test_coder() {802		const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;803804		let encoded_enum = {805			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);806			<Color as evm_coder::abi::AbiWrite>::abi_write(&Color::Green, &mut writer);807			writer.finish()808		};809810		let encoded_u8 = {811			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);812			<u8 as evm_coder::abi::AbiWrite>::abi_write(&(Color::Green as u8), &mut writer);813			writer.finish()814		};815816		similar_asserts::assert_eq!(encoded_enum, encoded_u8);817818		{819			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_enum).unwrap();820			let restored_enum_data =821				<Color as evm_coder::abi::AbiRead>::abi_read(&mut decoder).unwrap();822			assert_eq!(restored_enum_data, Color::Green);823		}824	}825826	#[test]827	#[cfg(feature = "stubgen")]828	fn struct_collect_enum() {829		assert_eq!(830			<Color as ::evm_coder::solidity::StructCollect>::name(),831			"Color"832		);833		similar_asserts::assert_eq!(834			<Color as ::evm_coder::solidity::StructCollect>::declaration(),835			r#"/// @dev Some docs836/// At multi837/// line838enum Color {839	/// @dev Docs for Red840	/// multi841	/// line842	Red,843	Green,844	/// @dev Docs for Blue845	Blue846}847"#848		);849	}850}
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	fn impl_abi_type_signature() {78		assert_eq!(79			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE80				.as_str()81				.unwrap(),82			"(uint8)"83		);84		assert_eq!(85			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE86				.as_str()87				.unwrap(),88			"(string)"89		);90		assert_eq!(91			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE92				.as_str()93				.unwrap(),94			"(uint8,uint32)"95		);96		assert_eq!(97			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE98				.as_str()99				.unwrap(),100			"(string,bytes)"101		);102		assert_eq!(103			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE104				.as_str()105				.unwrap(),106			"(uint8,bytes)"107		);108		assert_eq!(109			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE110				.as_str()111				.unwrap(),112			"((uint8))"113		);114		assert_eq!(115			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE116				.as_str()117				.unwrap(),118			"((uint8),(uint8,uint32))"119		);120		assert_eq!(121			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE122				.as_str()123				.unwrap(),124			"((string))"125		);126		assert_eq!(127			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE128				.as_str()129				.unwrap(),130			"((string),(string,bytes))"131		);132		assert_eq!(133			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE134				.as_str()135				.unwrap(),136			"((uint8),(string,bytes),(uint8,bytes))"137		);138	}139140	#[test]141	fn impl_abi_type_is_dynamic() {142		assert_eq!(143			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),144			false145		);146		assert_eq!(147			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),148			true149		);150		assert_eq!(151			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),152			false153		);154		assert_eq!(155			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),156			true157		);158		assert_eq!(159			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),160			true161		);162		assert_eq!(163			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),164			false165		);166		assert_eq!(167			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),168			false169		);170		assert_eq!(171			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),172			true173		);174		assert_eq!(175			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),176			true177		);178		assert_eq!(179			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),180			true181		);182	}183184	#[test]185	fn impl_abi_type_size() {186		const ABI_ALIGNMENT: usize = 32;187		assert_eq!(188			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),189			ABI_ALIGNMENT190		);191		assert_eq!(192			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),193			ABI_ALIGNMENT194		);195		assert_eq!(196			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),197			ABI_ALIGNMENT * 2198		);199		assert_eq!(200			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),201			ABI_ALIGNMENT * 2202		);203		assert_eq!(204			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),205			ABI_ALIGNMENT * 2206		);207		assert_eq!(208			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),209			ABI_ALIGNMENT210		);211		assert_eq!(212			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),213			ABI_ALIGNMENT * 3214		);215		assert_eq!(216			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),217			ABI_ALIGNMENT218		);219		assert_eq!(220			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),221			ABI_ALIGNMENT * 3222		);223		assert_eq!(224			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),225			ABI_ALIGNMENT * 5226		);227	}228229	#[derive(AbiCoder, PartialEq, Debug)]230	struct TupleStruct1SimpleParam(u8);231232	#[derive(AbiCoder, PartialEq, Debug)]233	struct TupleStruct1DynamicParam(String);234235	#[derive(AbiCoder, PartialEq, Debug)]236	struct TupleStruct2SimpleParam(u8, u32);237238	#[derive(AbiCoder, PartialEq, Debug)]239	struct TupleStruct2DynamicParam(String, bytes);240241	#[derive(AbiCoder, PartialEq, Debug)]242	struct TupleStruct2MixedParam(u8, bytes);243244	#[derive(AbiCoder, PartialEq, Debug)]245	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);246247	#[derive(AbiCoder, PartialEq, Debug)]248	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);249250	#[derive(AbiCoder, PartialEq, Debug)]251	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);252253	#[derive(AbiCoder, PartialEq, Debug)]254	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);255256	/// Some docs257	/// At multi258	/// line259	#[derive(AbiCoder, PartialEq, Debug)]260	struct TupleStruct3DerivedMixedParam(261		/// Docs for A262		/// multi263		/// line264		TupleStruct1SimpleParam,265		TupleStruct2DynamicParam,266		/// Docs for C267		TupleStruct2MixedParam,268	);269270	#[test]271	fn impl_abi_type_signature_same_for_structs() {272		assert_eq!(273			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE274				.as_str()275				.unwrap(),276			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE277				.as_str()278				.unwrap()279		);280		assert_eq!(281			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE282				.as_str()283				.unwrap(),284			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE285				.as_str()286				.unwrap()287		);288		assert_eq!(289			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE290				.as_str()291				.unwrap(),292			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE293				.as_str()294				.unwrap()295		);296		assert_eq!(297			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE298				.as_str()299				.unwrap(),300			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE301				.as_str()302				.unwrap()303		);304		assert_eq!(305			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE306				.as_str()307				.unwrap(),308			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE309				.as_str()310				.unwrap(),311		);312		assert_eq!(313			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE314				.as_str()315				.unwrap(),316			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE317				.as_str()318				.unwrap(),319		);320		assert_eq!(321			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE322				.as_str()323				.unwrap(),324			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE325				.as_str()326				.unwrap(),327		);328		assert_eq!(329			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE330				.as_str()331				.unwrap(),332			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE333				.as_str()334				.unwrap(),335		);336		assert_eq!(337			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE338				.as_str()339				.unwrap(),340			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE341				.as_str()342				.unwrap(),343		);344		assert_eq!(345			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE346				.as_str()347				.unwrap(),348			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE349				.as_str()350				.unwrap(),351		);352	}353354	#[test]355	fn impl_abi_type_is_dynamic_same_for_structs() {356		assert_eq!(357			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),358			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()359		);360		assert_eq!(361			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),362			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()363		);364		assert_eq!(365			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),366			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()367		);368		assert_eq!(369			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),370			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()371		);372		assert_eq!(373			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),374			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()375		);376		assert_eq!(377			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),378			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()379		);380		assert_eq!(381			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),382			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()383		);384		assert_eq!(385			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),386			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()387		);388		assert_eq!(389			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),390			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()391		);392		assert_eq!(393			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),394			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()395		);396	}397398	#[test]399	fn impl_abi_type_size_same_for_structs() {400		assert_eq!(401			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),402			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()403		);404		assert_eq!(405			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),406			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()407		);408		assert_eq!(409			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),410			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()411		);412		assert_eq!(413			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),414			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()415		);416		assert_eq!(417			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),418			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()419		);420		assert_eq!(421			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),422			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()423		);424		assert_eq!(425			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),426			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()427		);428		assert_eq!(429			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),430			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()431		);432		assert_eq!(433			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),434			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()435		);436		assert_eq!(437			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),438			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()439		);440	}441442	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;443444	fn test_impl<Tuple, TupleStruct, TypeStruct>(445		tuple_data: Tuple,446		tuple_struct_data: TupleStruct,447		type_struct_data: TypeStruct,448	) where449		TypeStruct: evm_coder::abi::AbiWrite450			+ evm_coder::abi::AbiRead451			+ std::cmp::PartialEq452			+ std::fmt::Debug,453		TupleStruct: evm_coder::abi::AbiWrite454			+ evm_coder::abi::AbiRead455			+ std::cmp::PartialEq456			+ std::fmt::Debug,457		Tuple: evm_coder::abi::AbiWrite458			+ evm_coder::abi::AbiRead459			+ std::cmp::PartialEq460			+ std::fmt::Debug,461	{462		let encoded_type_struct = test_abi_write_impl(&type_struct_data);463		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);464		let encoded_tuple = test_abi_write_impl(&tuple_data);465466		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);467		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);468469		{470			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();471			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();472			assert_eq!(restored_struct_data, type_struct_data);473		}474		{475			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();476			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();477			assert_eq!(restored_struct_data, tuple_struct_data);478		}479480		{481			let (_, mut decoder) =482				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();483			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();484			assert_eq!(restored_tuple_data, tuple_data);485		}486		{487			let (_, mut decoder) =488				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();489			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();490			assert_eq!(restored_tuple_data, tuple_data);491		}492	}493494	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>495	where496		A: evm_coder::abi::AbiWrite497			+ evm_coder::abi::AbiRead498			+ std::cmp::PartialEq499			+ std::fmt::Debug,500	{501		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);502		data.abi_write(&mut writer);503		let encoded_tuple = writer.finish();504		encoded_tuple505	}506507	#[test]508	fn codec_struct_1_simple() {509		let _a = 0xff;510		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(511			(_a,),512			TupleStruct1SimpleParam(_a),513			TypeStruct1SimpleParam { _a },514		);515	}516517	#[test]518	fn codec_struct_1_dynamic() {519		let _a: String = "some string".into();520		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(521			(_a.clone(),),522			TupleStruct1DynamicParam(_a.clone()),523			TypeStruct1DynamicParam { _a },524		);525	}526527	#[test]528	fn codec_struct_1_derived_simple() {529		let _a: u8 = 0xff;530		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(531			((_a,),),532			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),533			TypeStruct1DerivedSimpleParam {534				_a: TypeStruct1SimpleParam { _a },535			},536		);537	}538539	#[test]540	fn codec_struct_1_derived_dynamic() {541		let _a: String = "some string".into();542		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(543			((_a.clone(),),),544			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),545			TypeStruct1DerivedDynamicParam {546				_a: TypeStruct1DynamicParam { _a },547			},548		);549	}550551	#[test]552	fn codec_struct_2_simple() {553		let _a = 0xff;554		let _b = 0xbeefbaba;555		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(556			(_a, _b),557			TupleStruct2SimpleParam(_a, _b),558			TypeStruct2SimpleParam { _a, _b },559		);560	}561562	#[test]563	fn codec_struct_2_dynamic() {564		let _a: String = "some string".into();565		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);566		test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(567			(_a.clone(), _b.clone()),568			TupleStruct2DynamicParam(_a.clone(), _b.clone()),569			TypeStruct2DynamicParam { _a, _b },570		);571	}572573	#[test]574	fn codec_struct_2_mixed() {575		let _a: u8 = 0xff;576		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);577		test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(578			(_a.clone(), _b.clone()),579			TupleStruct2MixedParam(_a.clone(), _b.clone()),580			TypeStruct2MixedParam { _a, _b },581		);582	}583584	#[test]585	fn codec_struct_2_derived_simple() {586		let _a = 0xff;587		let _b = 0xbeefbaba;588		test_impl::<589			((u8,), (u8, u32)),590			TupleStruct2DerivedSimpleParam,591			TypeStruct2DerivedSimpleParam,592		>(593			((_a,), (_a, _b)),594			TupleStruct2DerivedSimpleParam(595				TupleStruct1SimpleParam(_a),596				TupleStruct2SimpleParam(_a, _b),597			),598			TypeStruct2DerivedSimpleParam {599				_a: TypeStruct1SimpleParam { _a },600				_b: TypeStruct2SimpleParam { _a, _b },601			},602		);603	}604605	#[test]606	fn codec_struct_2_derived_dynamic() {607		let _a = "some string".to_string();608		let _b = bytes(vec![0x11, 0x22, 0x33]);609		test_impl::<610			((String,), (String, bytes)),611			TupleStruct2DerivedDynamicParam,612			TypeStruct2DerivedDynamicParam,613		>(614			((_a.clone(),), (_a.clone(), _b.clone())),615			TupleStruct2DerivedDynamicParam(616				TupleStruct1DynamicParam(_a.clone()),617				TupleStruct2DynamicParam(_a.clone(), _b.clone()),618			),619			TypeStruct2DerivedDynamicParam {620				_a: TypeStruct1DynamicParam { _a: _a.clone() },621				_b: TypeStruct2DynamicParam { _a, _b },622			},623		);624	}625626	#[test]627	fn codec_struct_3_derived_mixed() {628		let int = 0xff;629		let by = bytes(vec![0x11, 0x22, 0x33]);630		let string = "some string".to_string();631		test_impl::<632			((u8,), (String, bytes), (u8, bytes)),633			TupleStruct3DerivedMixedParam,634			TypeStruct3DerivedMixedParam,635		>(636			((int,), (string.clone(), by.clone()), (int, by.clone())),637			TupleStruct3DerivedMixedParam(638				TupleStruct1SimpleParam(int),639				TupleStruct2DynamicParam(string.clone(), by.clone()),640				TupleStruct2MixedParam(int, by.clone()),641			),642			TypeStruct3DerivedMixedParam {643				_a: TypeStruct1SimpleParam { _a: int },644				_b: TypeStruct2DynamicParam {645					_a: string.clone(),646					_b: by.clone(),647				},648				_c: TypeStruct2MixedParam { _a: int, _b: by },649			},650		);651	}652653	#[derive(AbiCoder, PartialEq, Debug)]654	struct TypeStruct2SimpleStruct1Simple {655		_a: TypeStruct2SimpleParam,656		_b: TypeStruct2SimpleParam,657		_c: u8,658	}659	#[derive(AbiCoder, PartialEq, Debug)]660	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);661662	#[test]663	fn codec_struct_2_struct_simple_1_simple() {664		let _a = 0xff;665		let _b = 0xbeefbaba;666		test_impl::<667			((u8, u32), (u8, u32), u8),668			TupleStruct2SimpleStruct1Simple,669			TypeStruct2SimpleStruct1Simple,670		>(671			((_a, _b), (_a, _b), _a),672			TupleStruct2SimpleStruct1Simple(673				TupleStruct2SimpleParam(_a, _b),674				TupleStruct2SimpleParam(_a, _b),675				_a,676			),677			TypeStruct2SimpleStruct1Simple {678				_a: TypeStruct2SimpleParam { _a, _b },679				_b: TypeStruct2SimpleParam { _a, _b },680				_c: _a,681			},682		);683	}684}685686mod test_enum {687	use evm_coder::AbiCoder;688689	/// Some docs690	/// At multi691	/// line692	#[derive(AbiCoder, Debug, PartialEq, Default, Clone, Copy)]693	#[repr(u8)]694	enum Color {695		/// Docs for Red696		/// multi697		/// line698		Red,699		Green,700		/// Docs for Blue701		#[default]702		Blue,703	}704705	#[test]706	fn empty() {}707708	#[test]709	fn bad_enums() {710		let t = trybuild::TestCases::new();711		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");712	}713714	#[test]715	fn impl_abi_type_signature_same_for_structs() {716		assert_eq!(717			<Color as evm_coder::abi::AbiType>::SIGNATURE718				.as_str()719				.unwrap(),720			<u8 as evm_coder::abi::AbiType>::SIGNATURE.as_str().unwrap()721		);722	}723724	#[test]725	fn impl_abi_type_is_dynamic_same_for_structs() {726		assert_eq!(727			<Color as evm_coder::abi::AbiType>::is_dynamic(),728			<u8 as evm_coder::abi::AbiType>::is_dynamic()729		);730	}731732	#[test]733	fn impl_abi_type_size_same_for_structs() {734		assert_eq!(735			<Color as evm_coder::abi::AbiType>::size(),736			<u8 as evm_coder::abi::AbiType>::size()737		);738	}739740	#[test]741	fn test_coder() {742		const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;743744		let encoded_enum = {745			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);746			<Color as evm_coder::abi::AbiWrite>::abi_write(&Color::Green, &mut writer);747			writer.finish()748		};749750		let encoded_u8 = {751			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);752			<u8 as evm_coder::abi::AbiWrite>::abi_write(&(Color::Green as u8), &mut writer);753			writer.finish()754		};755756		similar_asserts::assert_eq!(encoded_enum, encoded_u8);757758		{759			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_enum).unwrap();760			let restored_enum_data =761				<Color as evm_coder::abi::AbiRead>::abi_read(&mut decoder).unwrap();762			assert_eq!(restored_enum_data, Color::Green);763		}764	}765}
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -265,13 +265,13 @@
 	}
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of Optional value with CrossAddress.
+/// Ethereum representation of Optional value with CrossAddress.
 struct OptionCrossAddress {
 	bool status;
 	CrossAddress value;
modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -437,67 +437,67 @@
 	}
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
 struct CollectionNestingPermission {
 	CollectionPermissionField field;
 	bool value;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissionField {
-	/// @dev Owner of token can nest tokens under it.
+	/// Owner of token can nest tokens under it.
 	TokenOwner,
-	/// @dev Admin of token collection can nest tokens under token.
+	/// Admin of token collection can nest tokens under token.
 	CollectionAdmin
 }
 
-/// @dev Nested collections.
+/// Nested collections.
 struct CollectionNesting {
 	bool token_owner;
 	uint256[] ids;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
 struct CollectionLimit {
 	CollectionLimitField field;
 	OptionUint value;
 }
 
-/// @dev Ethereum representation of Optional value with uint256.
+/// Ethereum representation of Optional value with uint256.
 struct OptionUint {
 	bool status;
 	uint256 value;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
 enum CollectionLimitField {
-	/// @dev How many tokens can a user have on one account.
+	/// How many tokens can a user have on one account.
 	AccountTokenOwnership,
-	/// @dev How many bytes of data are available for sponsorship.
+	/// How many bytes of data are available for sponsorship.
 	SponsoredDataSize,
-	/// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
 	SponsoredDataRateLimit,
-	/// @dev How many tokens can be mined into this collection.
+	/// How many tokens can be mined into this collection.
 	TokenLimit,
-	/// @dev Timeouts for transfer sponsoring.
+	/// Timeouts for transfer sponsoring.
 	SponsorTransferTimeout,
-	/// @dev Timeout for sponsoring an approval in passed blocks.
+	/// Timeout for sponsoring an approval in passed blocks.
 	SponsorApproveTimeout,
-	/// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+	/// Whether the collection owner of the collection can send tokens (which belong to other users).
 	OwnerCanTransfer,
-	/// @dev Can the collection owner burn other people's tokens.
+	/// Can the collection owner burn other people's tokens.
 	OwnerCanDestroy,
-	/// @dev Is it possible to send tokens from this collection between users.
+	/// Is it possible to send tokens from this collection between users.
 	TransferEnabled
 }
 
-/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
+/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
 	string key;
 	bytes value;
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -127,35 +127,35 @@
 	}
 }
 
-/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
+/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
 	string key;
 	bytes value;
 }
 
-/// @dev Ethereum representation of Token Property Permissions.
+/// Ethereum representation of Token Property Permissions.
 struct TokenPropertyPermission {
-	/// @dev Token property key.
+	/// Token property key.
 	string key;
-	/// @dev Token property permissions.
+	/// Token property permissions.
 	PropertyPermission[] permissions;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
 struct PropertyPermission {
-	/// @dev TokenPermission field.
+	/// TokenPermission field.
 	TokenPermissionField code;
-	/// @dev TokenPermission value.
+	/// TokenPermission value.
 	bool value;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum TokenPermissionField {
-	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
+	/// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
 	Mutable,
-	/// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
+	/// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
 	TokenOwner,
-	/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
+	/// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin
 }
 
@@ -579,63 +579,63 @@
 	}
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
 struct CollectionNestingPermission {
 	CollectionPermissionField field;
 	bool value;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissionField {
-	/// @dev Owner of token can nest tokens under it.
+	/// Owner of token can nest tokens under it.
 	TokenOwner,
-	/// @dev Admin of token collection can nest tokens under token.
+	/// Admin of token collection can nest tokens under token.
 	CollectionAdmin
 }
 
-/// @dev Nested collections.
+/// Nested collections.
 struct CollectionNesting {
 	bool token_owner;
 	uint256[] ids;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
 struct CollectionLimit {
 	CollectionLimitField field;
 	OptionUint value;
 }
 
-/// @dev Ethereum representation of Optional value with uint256.
+/// Ethereum representation of Optional value with uint256.
 struct OptionUint {
 	bool status;
 	uint256 value;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
 enum CollectionLimitField {
-	/// @dev How many tokens can a user have on one account.
+	/// How many tokens can a user have on one account.
 	AccountTokenOwnership,
-	/// @dev How many bytes of data are available for sponsorship.
+	/// How many bytes of data are available for sponsorship.
 	SponsoredDataSize,
-	/// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
 	SponsoredDataRateLimit,
-	/// @dev How many tokens can be mined into this collection.
+	/// How many tokens can be mined into this collection.
 	TokenLimit,
-	/// @dev Timeouts for transfer sponsoring.
+	/// Timeouts for transfer sponsoring.
 	SponsorTransferTimeout,
-	/// @dev Timeout for sponsoring an approval in passed blocks.
+	/// Timeout for sponsoring an approval in passed blocks.
 	SponsorApproveTimeout,
-	/// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+	/// Whether the collection owner of the collection can send tokens (which belong to other users).
 	OwnerCanTransfer,
-	/// @dev Can the collection owner burn other people's tokens.
+	/// Can the collection owner burn other people's tokens.
 	OwnerCanDestroy,
-	/// @dev Is it possible to send tokens from this collection between users.
+	/// Is it possible to send tokens from this collection between users.
 	TransferEnabled
 }
 
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -127,35 +127,35 @@
 	}
 }
 
-/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
+/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
 	string key;
 	bytes value;
 }
 
-/// @dev Ethereum representation of Token Property Permissions.
+/// Ethereum representation of Token Property Permissions.
 struct TokenPropertyPermission {
-	/// @dev Token property key.
+	/// Token property key.
 	string key;
-	/// @dev Token property permissions.
+	/// Token property permissions.
 	PropertyPermission[] permissions;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
 struct PropertyPermission {
-	/// @dev TokenPermission field.
+	/// TokenPermission field.
 	TokenPermissionField code;
-	/// @dev TokenPermission value.
+	/// TokenPermission value.
 	bool value;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum TokenPermissionField {
-	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
+	/// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
 	Mutable,
-	/// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
+	/// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
 	TokenOwner,
-	/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
+	/// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin
 }
 
@@ -579,63 +579,63 @@
 	}
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
 struct CollectionNestingPermission {
 	CollectionPermissionField field;
 	bool value;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissionField {
-	/// @dev Owner of token can nest tokens under it.
+	/// Owner of token can nest tokens under it.
 	TokenOwner,
-	/// @dev Admin of token collection can nest tokens under token.
+	/// Admin of token collection can nest tokens under token.
 	CollectionAdmin
 }
 
-/// @dev Nested collections.
+/// Nested collections.
 struct CollectionNesting {
 	bool token_owner;
 	uint256[] ids;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
 struct CollectionLimit {
 	CollectionLimitField field;
 	OptionUint value;
 }
 
-/// @dev Ethereum representation of Optional value with uint256.
+/// Ethereum representation of Optional value with uint256.
 struct OptionUint {
 	bool status;
 	uint256 value;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
 enum CollectionLimitField {
-	/// @dev How many tokens can a user have on one account.
+	/// How many tokens can a user have on one account.
 	AccountTokenOwnership,
-	/// @dev How many bytes of data are available for sponsorship.
+	/// How many bytes of data are available for sponsorship.
 	SponsoredDataSize,
-	/// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
 	SponsoredDataRateLimit,
-	/// @dev How many tokens can be mined into this collection.
+	/// How many tokens can be mined into this collection.
 	TokenLimit,
-	/// @dev Timeouts for transfer sponsoring.
+	/// Timeouts for transfer sponsoring.
 	SponsorTransferTimeout,
-	/// @dev Timeout for sponsoring an approval in passed blocks.
+	/// Timeout for sponsoring an approval in passed blocks.
 	SponsorApproveTimeout,
-	/// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+	/// Whether the collection owner of the collection can send tokens (which belong to other users).
 	OwnerCanTransfer,
-	/// @dev Can the collection owner burn other people's tokens.
+	/// Can the collection owner burn other people's tokens.
 	OwnerCanDestroy,
-	/// @dev Is it possible to send tokens from this collection between users.
+	/// Is it possible to send tokens from this collection between users.
 	TransferEnabled
 }
 
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
@@ -128,7 +128,7 @@
 	}
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
modifiedtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth
--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -171,13 +171,13 @@
 	function toggleAllowlist(address contractAddress, bool enabled) external;
 }
 
-/// @dev Ethereum representation of Optional value with CrossAddress.
+/// Ethereum representation of Optional value with CrossAddress.
 struct OptionCrossAddress {
 	bool status;
 	CrossAddress value;
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -279,67 +279,67 @@
 	function changeCollectionOwnerCross(CrossAddress memory newOwner) external;
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
 struct CollectionNestingPermission {
 	CollectionPermissionField field;
 	bool value;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissionField {
-	/// @dev Owner of token can nest tokens under it.
+	/// Owner of token can nest tokens under it.
 	TokenOwner,
-	/// @dev Admin of token collection can nest tokens under token.
+	/// Admin of token collection can nest tokens under token.
 	CollectionAdmin
 }
 
-/// @dev Nested collections.
+/// Nested collections.
 struct CollectionNesting {
 	bool token_owner;
 	uint256[] ids;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
 struct CollectionLimit {
 	CollectionLimitField field;
 	OptionUint value;
 }
 
-/// @dev Ethereum representation of Optional value with uint256.
+/// Ethereum representation of Optional value with uint256.
 struct OptionUint {
 	bool status;
 	uint256 value;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
 enum CollectionLimitField {
-	/// @dev How many tokens can a user have on one account.
+	/// How many tokens can a user have on one account.
 	AccountTokenOwnership,
-	/// @dev How many bytes of data are available for sponsorship.
+	/// How many bytes of data are available for sponsorship.
 	SponsoredDataSize,
-	/// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
 	SponsoredDataRateLimit,
-	/// @dev How many tokens can be mined into this collection.
+	/// How many tokens can be mined into this collection.
 	TokenLimit,
-	/// @dev Timeouts for transfer sponsoring.
+	/// Timeouts for transfer sponsoring.
 	SponsorTransferTimeout,
-	/// @dev Timeout for sponsoring an approval in passed blocks.
+	/// Timeout for sponsoring an approval in passed blocks.
 	SponsorApproveTimeout,
-	/// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+	/// Whether the collection owner of the collection can send tokens (which belong to other users).
 	OwnerCanTransfer,
-	/// @dev Can the collection owner burn other people's tokens.
+	/// Can the collection owner burn other people's tokens.
 	OwnerCanDestroy,
-	/// @dev Is it possible to send tokens from this collection between users.
+	/// Is it possible to send tokens from this collection between users.
 	TransferEnabled
 }
 
-/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
+/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
 	string key;
 	bytes value;
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -80,35 +80,35 @@
 	function property(uint256 tokenId, string memory key) external view returns (bytes memory);
 }
 
-/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
+/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
 	string key;
 	bytes value;
 }
 
-/// @dev Ethereum representation of Token Property Permissions.
+/// Ethereum representation of Token Property Permissions.
 struct TokenPropertyPermission {
-	/// @dev Token property key.
+	/// Token property key.
 	string key;
-	/// @dev Token property permissions.
+	/// Token property permissions.
 	PropertyPermission[] permissions;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
 struct PropertyPermission {
-	/// @dev TokenPermission field.
+	/// TokenPermission field.
 	TokenPermissionField code;
-	/// @dev TokenPermission value.
+	/// TokenPermission value.
 	bool value;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum TokenPermissionField {
-	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
+	/// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
 	Mutable,
-	/// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
+	/// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
 	TokenOwner,
-	/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
+	/// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin
 }
 
@@ -379,63 +379,63 @@
 	function changeCollectionOwnerCross(CrossAddress memory newOwner) external;
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
 struct CollectionNestingPermission {
 	CollectionPermissionField field;
 	bool value;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissionField {
-	/// @dev Owner of token can nest tokens under it.
+	/// Owner of token can nest tokens under it.
 	TokenOwner,
-	/// @dev Admin of token collection can nest tokens under token.
+	/// Admin of token collection can nest tokens under token.
 	CollectionAdmin
 }
 
-/// @dev Nested collections.
+/// Nested collections.
 struct CollectionNesting {
 	bool token_owner;
 	uint256[] ids;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
 struct CollectionLimit {
 	CollectionLimitField field;
 	OptionUint value;
 }
 
-/// @dev Ethereum representation of Optional value with uint256.
+/// Ethereum representation of Optional value with uint256.
 struct OptionUint {
 	bool status;
 	uint256 value;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
 enum CollectionLimitField {
-	/// @dev How many tokens can a user have on one account.
+	/// How many tokens can a user have on one account.
 	AccountTokenOwnership,
-	/// @dev How many bytes of data are available for sponsorship.
+	/// How many bytes of data are available for sponsorship.
 	SponsoredDataSize,
-	/// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
 	SponsoredDataRateLimit,
-	/// @dev How many tokens can be mined into this collection.
+	/// How many tokens can be mined into this collection.
 	TokenLimit,
-	/// @dev Timeouts for transfer sponsoring.
+	/// Timeouts for transfer sponsoring.
 	SponsorTransferTimeout,
-	/// @dev Timeout for sponsoring an approval in passed blocks.
+	/// Timeout for sponsoring an approval in passed blocks.
 	SponsorApproveTimeout,
-	/// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+	/// Whether the collection owner of the collection can send tokens (which belong to other users).
 	OwnerCanTransfer,
-	/// @dev Can the collection owner burn other people's tokens.
+	/// Can the collection owner burn other people's tokens.
 	OwnerCanDestroy,
-	/// @dev Is it possible to send tokens from this collection between users.
+	/// Is it possible to send tokens from this collection between users.
 	TransferEnabled
 }
 
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -80,35 +80,35 @@
 	function property(uint256 tokenId, string memory key) external view returns (bytes memory);
 }
 
-/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
+/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
 	string key;
 	bytes value;
 }
 
-/// @dev Ethereum representation of Token Property Permissions.
+/// Ethereum representation of Token Property Permissions.
 struct TokenPropertyPermission {
-	/// @dev Token property key.
+	/// Token property key.
 	string key;
-	/// @dev Token property permissions.
+	/// Token property permissions.
 	PropertyPermission[] permissions;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
 struct PropertyPermission {
-	/// @dev TokenPermission field.
+	/// TokenPermission field.
 	TokenPermissionField code;
-	/// @dev TokenPermission value.
+	/// TokenPermission value.
 	bool value;
 }
 
-/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum TokenPermissionField {
-	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
+	/// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
 	Mutable,
-	/// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
+	/// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
 	TokenOwner,
-	/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
+	/// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin
 }
 
@@ -379,63 +379,63 @@
 	function changeCollectionOwnerCross(CrossAddress memory newOwner) external;
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
 struct CollectionNestingPermission {
 	CollectionPermissionField field;
 	bool value;
 }
 
-/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
+/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissionField {
-	/// @dev Owner of token can nest tokens under it.
+	/// Owner of token can nest tokens under it.
 	TokenOwner,
-	/// @dev Admin of token collection can nest tokens under token.
+	/// Admin of token collection can nest tokens under token.
 	CollectionAdmin
 }
 
-/// @dev Nested collections.
+/// Nested collections.
 struct CollectionNesting {
 	bool token_owner;
 	uint256[] ids;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.
 struct CollectionLimit {
 	CollectionLimitField field;
 	OptionUint value;
 }
 
-/// @dev Ethereum representation of Optional value with uint256.
+/// Ethereum representation of Optional value with uint256.
 struct OptionUint {
 	bool status;
 	uint256 value;
 }
 
-/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.
 enum CollectionLimitField {
-	/// @dev How many tokens can a user have on one account.
+	/// How many tokens can a user have on one account.
 	AccountTokenOwnership,
-	/// @dev How many bytes of data are available for sponsorship.
+	/// How many bytes of data are available for sponsorship.
 	SponsoredDataSize,
-	/// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
 	SponsoredDataRateLimit,
-	/// @dev How many tokens can be mined into this collection.
+	/// How many tokens can be mined into this collection.
 	TokenLimit,
-	/// @dev Timeouts for transfer sponsoring.
+	/// Timeouts for transfer sponsoring.
 	SponsorTransferTimeout,
-	/// @dev Timeout for sponsoring an approval in passed blocks.
+	/// Timeout for sponsoring an approval in passed blocks.
 	SponsorApproveTimeout,
-	/// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+	/// Whether the collection owner of the collection can send tokens (which belong to other users).
 	OwnerCanTransfer,
-	/// @dev Can the collection owner burn other people's tokens.
+	/// Can the collection owner burn other people's tokens.
 	OwnerCanDestroy,
-	/// @dev Is it possible to send tokens from this collection between users.
+	/// Is it possible to send tokens from this collection between users.
 	TransferEnabled
 }
 
modifiedtests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungibleToken.sol
+++ b/tests/src/eth/api/UniqueRefungibleToken.sol
@@ -79,7 +79,7 @@
 	) external returns (bool);
 }
 
-/// @dev Cross account struct
+/// Cross account struct
 struct CrossAddress {
 	address eth;
 	uint256 sub;