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
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;