git.delta.rocks / unique-network / refs/commits / 8298cf829479

difftreelog

feat Rewrite tuple to named structures for TokenPropertyPermission. fix: AbiCoder derive macro

Trubnikov Sergey2022-12-19parent: #ab6e845.patch.diff
in: master

23 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
@@ -86,6 +86,21 @@
 	)
 }
 
+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 {
 	quote!(
 		#[cfg(feature = "stubgen")]
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
@@ -86,6 +86,7 @@
 	let abi_type = impl_enum_abi_type(name, option_count);
 	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,
@@ -102,6 +103,7 @@
 		#abi_type
 		#abi_read
 		#abi_write
+		#solidity_type
 		#solidity_type_name
 		#solidity_struct_collect
 	})
modifiedcrates/evm-coder/src/abi/impls.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi/impls.rs
+++ b/crates/evm-coder/src/abi/impls.rs
@@ -184,6 +184,11 @@
 	}
 }
 
+macro_rules! count {
+    () => (0usize);
+    ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
+}
+
 macro_rules! impl_tuples {
 	($($ident:ident)+) => {
 		impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)
@@ -198,7 +203,7 @@
                 shift_left(1)
                 fixed(")")
             );
-			const FIELDS_COUNT: usize = 0 $(+ {let _ = <$ident as AbiType>::FIELDS_COUNT; 1})+;
+			const FIELDS_COUNT: usize = count!($($ident)*);
 
 			fn is_dynamic() -> bool {
 				false
modifiedcrates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/impls.rs
+++ b/crates/evm-coder/src/solidity/impls.rs
@@ -74,6 +74,16 @@
 	}
 }
 
+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 {
     () => (0usize);
     ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
@@ -131,60 +141,3 @@
 impl_tuples! {A B C D E F G H}
 impl_tuples! {A B C D E F G H I}
 impl_tuples! {A B C D E F G H I J}
-
-impl StructCollect for Property {
-	fn name() -> String {
-		"Property".into()
-	}
-
-	fn declaration() -> String {
-		use std::fmt::Write;
-
-		let mut str = String::new();
-		writeln!(str, "/// @dev Property struct").unwrap();
-		writeln!(str, "struct {} {{", Self::name()).unwrap();
-		writeln!(str, "\tstring key;").unwrap();
-		writeln!(str, "\tbytes value;").unwrap();
-		writeln!(str, "}}").unwrap();
-		str
-	}
-}
-
-impl SolidityTypeName for Property {
-	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "{}", tc.collect_struct::<Self>())
-	}
-
-	fn is_simple() -> bool {
-		false
-	}
-
-	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "{}(", tc.collect_struct::<Self>())?;
-		address::solidity_default(writer, tc)?;
-		write!(writer, ",")?;
-		uint256::solidity_default(writer, tc)?;
-		write!(writer, ")")
-	}
-}
-
-impl SolidityType for Property {
-	fn names(tc: &TypeCollector) -> Vec<string> {
-		let mut collected = Vec::with_capacity(Self::len());
-		{
-			let mut out = string::new();
-			string::solidity_name(&mut out, tc).expect("no fmt error");
-			collected.push(out);
-		}
-		{
-			let mut out = string::new();
-			bytes::solidity_name(&mut out, tc).expect("no fmt error");
-			collected.push(out);
-		}
-		collected
-	}
-
-	fn len() -> usize {
-		2
-	}
-}
modifiedcrates/evm-coder/src/solidity/mod.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/mod.rs
+++ b/crates/evm-coder/src/solidity/mod.rs
@@ -76,7 +76,8 @@
 		self.anonymous.borrow_mut().insert(names, id);
 		format!("Tuple{}", id)
 	}
-	pub fn collect_struct<T: StructCollect>(&self) -> String {
+	pub fn collect_struct<T: StructCollect + SolidityType>(&self) -> String {
+		let _names = T::names(self);
 		self.collect(<T as StructCollect>::declaration());
 		<T as StructCollect>::name()
 	}
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	fn impl_abi_type_signature() {104		assert_eq!(105			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE106				.as_str()107				.unwrap(),108			"(uint8)"109		);110		assert_eq!(111			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE112				.as_str()113				.unwrap(),114			"(string)"115		);116		assert_eq!(117			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE118				.as_str()119				.unwrap(),120			"(uint8,uint32)"121		);122		assert_eq!(123			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE124				.as_str()125				.unwrap(),126			"(string,bytes)"127		);128		assert_eq!(129			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE130				.as_str()131				.unwrap(),132			"(uint8,bytes)"133		);134		assert_eq!(135			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE136				.as_str()137				.unwrap(),138			"((uint8))"139		);140		assert_eq!(141			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE142				.as_str()143				.unwrap(),144			"((uint8),(uint8,uint32))"145		);146		assert_eq!(147			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE148				.as_str()149				.unwrap(),150			"((string))"151		);152		assert_eq!(153			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE154				.as_str()155				.unwrap(),156			"((string),(string,bytes))"157		);158		assert_eq!(159			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE160				.as_str()161				.unwrap(),162			"((uint8),(string,bytes),(uint8,bytes))"163		);164	}165166	#[test]167	fn impl_abi_type_fields_count() {168		assert_eq!(169			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,170			1171		);172		assert_eq!(173			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,174			1175		);176		assert_eq!(177			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,178			2179		);180		assert_eq!(181			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,182			2183		);184		assert_eq!(185			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::FIELDS_COUNT,186			2187		);188		assert_eq!(189			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,190			1191		);192		assert_eq!(193			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,194			2195		);196		assert_eq!(197			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,198			2199		);200		assert_eq!(201			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,202			2203		);204		assert_eq!(205			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::FIELDS_COUNT,206			3207		);208	}209210	#[test]211	fn impl_abi_type_is_dynamic() {212		assert_eq!(213			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),214			false215		);216		assert_eq!(217			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),218			true219		);220		assert_eq!(221			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),222			false223		);224		assert_eq!(225			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),226			true227		);228		assert_eq!(229			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),230			true231		);232		assert_eq!(233			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),234			false235		);236		assert_eq!(237			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),238			false239		);240		assert_eq!(241			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),242			true243		);244		assert_eq!(245			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),246			true247		);248		assert_eq!(249			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),250			true251		);252	}253254	#[test]255	fn impl_abi_type_size() {256		const ABI_ALIGNMENT: usize = 32;257		assert_eq!(258			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),259			ABI_ALIGNMENT260		);261		assert_eq!(262			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),263			ABI_ALIGNMENT264		);265		assert_eq!(266			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),267			ABI_ALIGNMENT * 2268		);269		assert_eq!(270			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),271			ABI_ALIGNMENT * 2272		);273		assert_eq!(274			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),275			ABI_ALIGNMENT * 2276		);277		assert_eq!(278			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),279			ABI_ALIGNMENT280		);281		assert_eq!(282			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),283			ABI_ALIGNMENT * 3284		);285		assert_eq!(286			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),287			ABI_ALIGNMENT288		);289		assert_eq!(290			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),291			ABI_ALIGNMENT * 3292		);293		assert_eq!(294			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),295			ABI_ALIGNMENT * 5296		);297	}298299	#[derive(AbiCoder, PartialEq, Debug)]300	struct TupleStruct1SimpleParam(u8);301302	#[derive(AbiCoder, PartialEq, Debug)]303	struct TupleStruct1DynamicParam(String);304305	#[derive(AbiCoder, PartialEq, Debug)]306	struct TupleStruct2SimpleParam(u8, u32);307308	#[derive(AbiCoder, PartialEq, Debug)]309	struct TupleStruct2DynamicParam(String, bytes);310311	#[derive(AbiCoder, PartialEq, Debug)]312	struct TupleStruct2MixedParam(u8, bytes);313314	#[derive(AbiCoder, PartialEq, Debug)]315	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);316317	#[derive(AbiCoder, PartialEq, Debug)]318	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);319320	#[derive(AbiCoder, PartialEq, Debug)]321	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);322323	#[derive(AbiCoder, PartialEq, Debug)]324	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);325326	/// Some docs327	/// At multi328	/// line329	#[derive(AbiCoder, PartialEq, Debug)]330	struct TupleStruct3DerivedMixedParam(331		/// Docs for A332		/// multi333		/// line334		TupleStruct1SimpleParam,335		TupleStruct2DynamicParam,336		/// Docs for C337		TupleStruct2MixedParam,338	);339340	#[test]341	#[cfg(feature = "stubgen")]342	fn struct_collect_tuple_struct3_derived_mixed_param() {343		assert_eq!(344			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),345			"TupleStruct3DerivedMixedParam"346		);347		similar_asserts::assert_eq!(348			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),349			r#"/// @dev Some docs350/// At multi351/// line352struct TupleStruct3DerivedMixedParam {353	/// @dev Docs for A354	/// multi355	/// line356	TupleStruct1SimpleParam field0;357	TupleStruct2DynamicParam field1;358	/// @dev Docs for C359	TupleStruct2MixedParam field2;360}361"#362		);363	}364365	#[test]366	fn impl_abi_type_signature_same_for_structs() {367		assert_eq!(368			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE369				.as_str()370				.unwrap(),371			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE372				.as_str()373				.unwrap()374		);375		assert_eq!(376			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE377				.as_str()378				.unwrap(),379			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE380				.as_str()381				.unwrap()382		);383		assert_eq!(384			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE385				.as_str()386				.unwrap(),387			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE388				.as_str()389				.unwrap()390		);391		assert_eq!(392			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE393				.as_str()394				.unwrap(),395			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE396				.as_str()397				.unwrap()398		);399		assert_eq!(400			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE401				.as_str()402				.unwrap(),403			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE404				.as_str()405				.unwrap(),406		);407		assert_eq!(408			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE409				.as_str()410				.unwrap(),411			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE412				.as_str()413				.unwrap(),414		);415		assert_eq!(416			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE417				.as_str()418				.unwrap(),419			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE420				.as_str()421				.unwrap(),422		);423		assert_eq!(424			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE425				.as_str()426				.unwrap(),427			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE428				.as_str()429				.unwrap(),430		);431		assert_eq!(432			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE433				.as_str()434				.unwrap(),435			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE436				.as_str()437				.unwrap(),438		);439		assert_eq!(440			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE441				.as_str()442				.unwrap(),443			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE444				.as_str()445				.unwrap(),446		);447	}448449	#[test]450	fn impl_abi_type_is_dynamic_same_for_structs() {451		assert_eq!(452			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),453			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()454		);455		assert_eq!(456			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),457			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()458		);459		assert_eq!(460			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),461			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()462		);463		assert_eq!(464			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),465			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()466		);467		assert_eq!(468			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),469			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()470		);471		assert_eq!(472			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),473			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()474		);475		assert_eq!(476			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),477			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()478		);479		assert_eq!(480			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),481			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()482		);483		assert_eq!(484			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),485			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()486		);487		assert_eq!(488			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),489			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()490		);491	}492493	#[test]494	fn impl_abi_type_size_same_for_structs() {495		assert_eq!(496			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),497			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()498		);499		assert_eq!(500			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),501			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()502		);503		assert_eq!(504			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),505			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()506		);507		assert_eq!(508			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),509			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()510		);511		assert_eq!(512			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),513			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()514		);515		assert_eq!(516			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),517			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()518		);519		assert_eq!(520			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),521			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()522		);523		assert_eq!(524			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),525			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()526		);527		assert_eq!(528			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),529			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()530		);531		assert_eq!(532			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),533			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()534		);535	}536537	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;538539	fn test_impl<Tuple, TupleStruct, TypeStruct>(540		tuple_data: Tuple,541		tuple_struct_data: TupleStruct,542		type_struct_data: TypeStruct,543	) where544		TypeStruct: evm_coder::abi::AbiWrite545			+ evm_coder::abi::AbiRead546			+ std::cmp::PartialEq547			+ std::fmt::Debug,548		TupleStruct: evm_coder::abi::AbiWrite549			+ evm_coder::abi::AbiRead550			+ std::cmp::PartialEq551			+ std::fmt::Debug,552		Tuple: evm_coder::abi::AbiWrite553			+ evm_coder::abi::AbiRead554			+ std::cmp::PartialEq555			+ std::fmt::Debug,556	{557		let encoded_type_struct = test_abi_write_impl(&type_struct_data);558		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);559		let encoded_tuple = test_abi_write_impl(&tuple_data);560561		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);562		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);563564		{565			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();566			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();567			assert_eq!(restored_struct_data, type_struct_data);568		}569		{570			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();571			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();572			assert_eq!(restored_struct_data, tuple_struct_data);573		}574575		{576			let (_, mut decoder) =577				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();578			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();579			assert_eq!(restored_tuple_data, tuple_data);580		}581		{582			let (_, mut decoder) =583				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();584			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();585			assert_eq!(restored_tuple_data, tuple_data);586		}587	}588589	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>590	where591		A: evm_coder::abi::AbiWrite592			+ evm_coder::abi::AbiRead593			+ std::cmp::PartialEq594			+ std::fmt::Debug,595	{596		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);597		data.abi_write(&mut writer);598		let encoded_tuple = writer.finish();599		encoded_tuple600	}601602	#[test]603	fn codec_struct_1_simple() {604		let _a = 0xff;605		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(606			(_a,),607			TupleStruct1SimpleParam(_a),608			TypeStruct1SimpleParam { _a },609		);610	}611612	#[test]613	fn codec_struct_1_dynamic() {614		let _a: String = "some string".into();615		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(616			(_a.clone(),),617			TupleStruct1DynamicParam(_a.clone()),618			TypeStruct1DynamicParam { _a },619		);620	}621622	#[test]623	fn codec_struct_1_derived_simple() {624		let _a: u8 = 0xff;625		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(626			((_a,),),627			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),628			TypeStruct1DerivedSimpleParam {629				_a: TypeStruct1SimpleParam { _a },630			},631		);632	}633634	#[test]635	fn codec_struct_1_derived_dynamic() {636		let _a: String = "some string".into();637		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(638			((_a.clone(),),),639			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),640			TypeStruct1DerivedDynamicParam {641				_a: TypeStruct1DynamicParam { _a },642			},643		);644	}645646	#[test]647	fn codec_struct_2_simple() {648		let _a = 0xff;649		let _b = 0xbeefbaba;650		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(651			(_a, _b),652			TupleStruct2SimpleParam(_a, _b),653			TypeStruct2SimpleParam { _a, _b },654		);655	}656657	#[test]658	fn codec_struct_2_dynamic() {659		let _a: String = "some string".into();660		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);661		test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(662			(_a.clone(), _b.clone()),663			TupleStruct2DynamicParam(_a.clone(), _b.clone()),664			TypeStruct2DynamicParam { _a, _b },665		);666	}667668	#[test]669	fn codec_struct_2_mixed() {670		let _a: u8 = 0xff;671		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);672		test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(673			(_a.clone(), _b.clone()),674			TupleStruct2MixedParam(_a.clone(), _b.clone()),675			TypeStruct2MixedParam { _a, _b },676		);677	}678679	#[test]680	fn codec_struct_2_derived_simple() {681		let _a = 0xff;682		let _b = 0xbeefbaba;683		test_impl::<684			((u8,), (u8, u32)),685			TupleStruct2DerivedSimpleParam,686			TypeStruct2DerivedSimpleParam,687		>(688			((_a,), (_a, _b)),689			TupleStruct2DerivedSimpleParam(690				TupleStruct1SimpleParam(_a),691				TupleStruct2SimpleParam(_a, _b),692			),693			TypeStruct2DerivedSimpleParam {694				_a: TypeStruct1SimpleParam { _a },695				_b: TypeStruct2SimpleParam { _a, _b },696			},697		);698	}699700	#[test]701	fn codec_struct_2_derived_dynamic() {702		let _a = "some string".to_string();703		let _b = bytes(vec![0x11, 0x22, 0x33]);704		test_impl::<705			((String,), (String, bytes)),706			TupleStruct2DerivedDynamicParam,707			TypeStruct2DerivedDynamicParam,708		>(709			((_a.clone(),), (_a.clone(), _b.clone())),710			TupleStruct2DerivedDynamicParam(711				TupleStruct1DynamicParam(_a.clone()),712				TupleStruct2DynamicParam(_a.clone(), _b.clone()),713			),714			TypeStruct2DerivedDynamicParam {715				_a: TypeStruct1DynamicParam { _a: _a.clone() },716				_b: TypeStruct2DynamicParam { _a, _b },717			},718		);719	}720721	#[test]722	fn codec_struct_3_derived_mixed() {723		let int = 0xff;724		let by = bytes(vec![0x11, 0x22, 0x33]);725		let string = "some string".to_string();726		test_impl::<727			((u8,), (String, bytes), (u8, bytes)),728			TupleStruct3DerivedMixedParam,729			TypeStruct3DerivedMixedParam,730		>(731			((int,), (string.clone(), by.clone()), (int, by.clone())),732			TupleStruct3DerivedMixedParam(733				TupleStruct1SimpleParam(int),734				TupleStruct2DynamicParam(string.clone(), by.clone()),735				TupleStruct2MixedParam(int, by.clone()),736			),737			TypeStruct3DerivedMixedParam {738				_a: TypeStruct1SimpleParam { _a: int },739				_b: TypeStruct2DynamicParam {740					_a: string.clone(),741					_b: by.clone(),742				},743				_c: TypeStruct2MixedParam { _a: int, _b: by },744			},745		);746	}747748	#[derive(AbiCoder, PartialEq, Debug)]749	struct TypeStruct2SimpleStruct1Simple {750		_a: TypeStruct2SimpleParam,751		_b: TypeStruct2SimpleParam,752		_c: u8,753	}754	#[derive(AbiCoder, PartialEq, Debug)]755	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);756757	#[test]758	fn codec_struct_2_struct_simple_1_simple() {759		let _a = 0xff;760		let _b = 0xbeefbaba;761		test_impl::<762			((u8, u32), (u8, u32), u8),763			TupleStruct2SimpleStruct1Simple,764			TypeStruct2SimpleStruct1Simple,765		>(766			((_a, _b), (_a, _b), _a),767			TupleStruct2SimpleStruct1Simple(768				TupleStruct2SimpleParam(_a, _b),769				TupleStruct2SimpleParam(_a, _b),770				_a,771			),772			TypeStruct2SimpleStruct1Simple {773				_a: TypeStruct2SimpleParam { _a, _b },774				_b: TypeStruct2SimpleParam { _a, _b },775				_c: _a,776			},777		);778	}779}780781mod test_enum {782	use evm_coder::AbiCoder;783784	/// Some docs785	/// At multi786	/// line787	#[derive(AbiCoder, Debug, PartialEq, Default, Clone, Copy)]788	#[repr(u8)]789	enum Color {790		/// Docs for Red791		/// multi792		/// line793		Red,794		Green,795		/// Docs for Blue796		#[default]797		Blue,798	}799800	#[test]801	fn empty() {}802803	#[test]804	fn bad_enums() {805		let t = trybuild::TestCases::new();806		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");807	}808809	#[test]810	fn impl_abi_type_signature_same_for_structs() {811		assert_eq!(812			<Color as evm_coder::abi::AbiType>::SIGNATURE813				.as_str()814				.unwrap(),815			<u8 as evm_coder::abi::AbiType>::SIGNATURE.as_str().unwrap()816		);817	}818819	#[test]820	fn impl_abi_type_is_dynamic_same_for_structs() {821		assert_eq!(822			<Color as evm_coder::abi::AbiType>::is_dynamic(),823			<u8 as evm_coder::abi::AbiType>::is_dynamic()824		);825	}826827	#[test]828	fn impl_abi_type_size_same_for_structs() {829		assert_eq!(830			<Color as evm_coder::abi::AbiType>::size(),831			<u8 as evm_coder::abi::AbiType>::size()832		);833	}834835	#[test]836	fn test_coder() {837		const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;838839		let encoded_enum = {840			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);841			<Color as evm_coder::abi::AbiWrite>::abi_write(&Color::Green, &mut writer);842			writer.finish()843		};844845		let encoded_u8 = {846			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);847			<u8 as evm_coder::abi::AbiWrite>::abi_write(&(Color::Green as u8), &mut writer);848			writer.finish()849		};850851		similar_asserts::assert_eq!(encoded_enum, encoded_u8);852853		{854			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_enum).unwrap();855			let restored_enum_data =856				<Color as evm_coder::abi::AbiRead>::abi_read(&mut decoder).unwrap();857			assert_eq!(restored_enum_data, Color::Green);858		}859	}860861	#[test]862	#[cfg(feature = "stubgen")]863	fn struct_collect_enum() {864		assert_eq!(865			<Color as ::evm_coder::solidity::StructCollect>::name(),866			"Color"867		);868		similar_asserts::assert_eq!(869			<Color as ::evm_coder::solidity::StructCollect>::declaration(),870			r#"/// @dev Some docs871/// At multi872/// line873enum Color {874	/// @dev Docs for Red875	/// multi876	/// line877	Red,878	Green,879	/// @dev Docs for Blue880	Blue881}882"#883		);884	}885}
after · crates/evm-coder/tests/abi_derive_generation.rs
1mod test_struct {2	use evm_coder_procedural::AbiCoder;3	use evm_coder::types::bytes;45	#[test]6	fn empty_struct() {7		let t = trybuild::TestCases::new();8		t.compile_fail("tests/build_failed/abi_derive_struct_generation.rs");9	}1011	#[derive(AbiCoder, PartialEq, Debug)]12	struct TypeStruct1SimpleParam {13		_a: u8,14	}1516	#[derive(AbiCoder, PartialEq, Debug)]17	struct TypeStruct1DynamicParam {18		_a: String,19	}2021	#[derive(AbiCoder, PartialEq, Debug)]22	struct TypeStruct2SimpleParam {23		_a: u8,24		_b: u32,25	}2627	#[derive(AbiCoder, PartialEq, Debug)]28	struct TypeStruct2DynamicParam {29		_a: String,30		_b: bytes,31	}3233	#[derive(AbiCoder, PartialEq, Debug)]34	struct TypeStruct2MixedParam {35		_a: u8,36		_b: bytes,37	}3839	#[derive(AbiCoder, PartialEq, Debug)]40	struct TypeStruct1DerivedSimpleParam {41		_a: TypeStruct1SimpleParam,42	}4344	#[derive(AbiCoder, PartialEq, Debug)]45	struct TypeStruct2DerivedSimpleParam {46		_a: TypeStruct1SimpleParam,47		_b: TypeStruct2SimpleParam,48	}4950	#[derive(AbiCoder, PartialEq, Debug)]51	struct TypeStruct1DerivedDynamicParam {52		_a: TypeStruct1DynamicParam,53	}5455	#[derive(AbiCoder, PartialEq, Debug)]56	struct TypeStruct2DerivedDynamicParam {57		_a: TypeStruct1DynamicParam,58		_b: TypeStruct2DynamicParam,59	}6061	/// Some docs62	/// At multi63	/// line64	#[derive(AbiCoder, PartialEq, Debug)]65	struct TypeStruct3DerivedMixedParam {66		/// Docs for A67		/// multi68		/// line69		_a: TypeStruct1SimpleParam,70		/// Docs for B71		_b: TypeStruct2DynamicParam,72		/// Docs for C73		_c: TypeStruct2MixedParam,74	}7576	#[test]77	#[cfg(feature = "stubgen")]78	fn struct_collect_type_struct3_derived_mixed_param() {79		assert_eq!(80			<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),81			"TypeStruct3DerivedMixedParam"82		);83		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_fields_count() {177		assert_eq!(178			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,179			1180		);181		assert_eq!(182			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,183			1184		);185		assert_eq!(186			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,187			2188		);189		assert_eq!(190			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,191			2192		);193		assert_eq!(194			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::FIELDS_COUNT,195			2196		);197		assert_eq!(198			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,199			1200		);201		assert_eq!(202			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::FIELDS_COUNT,203			2204		);205		assert_eq!(206			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,207			2208		);209		assert_eq!(210			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::FIELDS_COUNT,211			2212		);213		assert_eq!(214			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::FIELDS_COUNT,215			3216		);217	}218219	#[test]220	fn impl_abi_type_is_dynamic() {221		assert_eq!(222			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),223			false224		);225		assert_eq!(226			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),227			true228		);229		assert_eq!(230			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),231			false232		);233		assert_eq!(234			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),235			true236		);237		assert_eq!(238			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),239			true240		);241		assert_eq!(242			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),243			false244		);245		assert_eq!(246			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),247			false248		);249		assert_eq!(250			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),251			true252		);253		assert_eq!(254			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),255			true256		);257		assert_eq!(258			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),259			true260		);261	}262263	#[test]264	fn impl_abi_type_size() {265		const ABI_ALIGNMENT: usize = 32;266		assert_eq!(267			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),268			ABI_ALIGNMENT269		);270		assert_eq!(271			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),272			ABI_ALIGNMENT273		);274		assert_eq!(275			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),276			ABI_ALIGNMENT * 2277		);278		assert_eq!(279			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),280			ABI_ALIGNMENT * 2281		);282		assert_eq!(283			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),284			ABI_ALIGNMENT * 2285		);286		assert_eq!(287			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),288			ABI_ALIGNMENT289		);290		assert_eq!(291			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),292			ABI_ALIGNMENT * 3293		);294		assert_eq!(295			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),296			ABI_ALIGNMENT297		);298		assert_eq!(299			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),300			ABI_ALIGNMENT * 3301		);302		assert_eq!(303			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),304			ABI_ALIGNMENT * 5305		);306	}307308	#[derive(AbiCoder, PartialEq, Debug)]309	struct TupleStruct1SimpleParam(u8);310311	#[derive(AbiCoder, PartialEq, Debug)]312	struct TupleStruct1DynamicParam(String);313314	#[derive(AbiCoder, PartialEq, Debug)]315	struct TupleStruct2SimpleParam(u8, u32);316317	#[derive(AbiCoder, PartialEq, Debug)]318	struct TupleStruct2DynamicParam(String, bytes);319320	#[derive(AbiCoder, PartialEq, Debug)]321	struct TupleStruct2MixedParam(u8, bytes);322323	#[derive(AbiCoder, PartialEq, Debug)]324	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);325326	#[derive(AbiCoder, PartialEq, Debug)]327	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);328329	#[derive(AbiCoder, PartialEq, Debug)]330	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);331332	#[derive(AbiCoder, PartialEq, Debug)]333	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);334335	/// Some docs336	/// At multi337	/// line338	#[derive(AbiCoder, PartialEq, Debug)]339	struct TupleStruct3DerivedMixedParam(340		/// Docs for A341		/// multi342		/// line343		TupleStruct1SimpleParam,344		TupleStruct2DynamicParam,345		/// Docs for C346		TupleStruct2MixedParam,347	);348349	#[test]350	#[cfg(feature = "stubgen")]351	fn struct_collect_tuple_struct3_derived_mixed_param() {352		assert_eq!(353			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),354			"TupleStruct3DerivedMixedParam"355		);356		similar_asserts::assert_eq!(357			<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),358			r#"/// @dev Some docs359/// At multi360/// line361struct TupleStruct3DerivedMixedParam {362	/// @dev Docs for A363	/// multi364	/// line365	TupleStruct1SimpleParam field0;366	TupleStruct2DynamicParam field1;367	/// @dev Docs for C368	TupleStruct2MixedParam field2;369}370"#371		);372	}373374	#[test]375	fn impl_abi_type_signature_same_for_structs() {376		assert_eq!(377			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE378				.as_str()379				.unwrap(),380			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE381				.as_str()382				.unwrap()383		);384		assert_eq!(385			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE386				.as_str()387				.unwrap(),388			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE389				.as_str()390				.unwrap()391		);392		assert_eq!(393			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE394				.as_str()395				.unwrap(),396			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE397				.as_str()398				.unwrap()399		);400		assert_eq!(401			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE402				.as_str()403				.unwrap(),404			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE405				.as_str()406				.unwrap()407		);408		assert_eq!(409			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE410				.as_str()411				.unwrap(),412			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE413				.as_str()414				.unwrap(),415		);416		assert_eq!(417			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE418				.as_str()419				.unwrap(),420			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE421				.as_str()422				.unwrap(),423		);424		assert_eq!(425			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE426				.as_str()427				.unwrap(),428			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE429				.as_str()430				.unwrap(),431		);432		assert_eq!(433			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE434				.as_str()435				.unwrap(),436			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE437				.as_str()438				.unwrap(),439		);440		assert_eq!(441			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE442				.as_str()443				.unwrap(),444			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE445				.as_str()446				.unwrap(),447		);448		assert_eq!(449			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE450				.as_str()451				.unwrap(),452			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE453				.as_str()454				.unwrap(),455		);456	}457458	#[test]459	fn impl_abi_type_is_dynamic_same_for_structs() {460		assert_eq!(461			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),462			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()463		);464		assert_eq!(465			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),466			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()467		);468		assert_eq!(469			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),470			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()471		);472		assert_eq!(473			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),474			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()475		);476		assert_eq!(477			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),478			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()479		);480		assert_eq!(481			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),482			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()483		);484		assert_eq!(485			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),486			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()487		);488		assert_eq!(489			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),490			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()491		);492		assert_eq!(493			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),494			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()495		);496		assert_eq!(497			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),498			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()499		);500	}501502	#[test]503	fn impl_abi_type_size_same_for_structs() {504		assert_eq!(505			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),506			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()507		);508		assert_eq!(509			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),510			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()511		);512		assert_eq!(513			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),514			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()515		);516		assert_eq!(517			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),518			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()519		);520		assert_eq!(521			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),522			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()523		);524		assert_eq!(525			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),526			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()527		);528		assert_eq!(529			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),530			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()531		);532		assert_eq!(533			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),534			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()535		);536		assert_eq!(537			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),538			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()539		);540		assert_eq!(541			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),542			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()543		);544	}545546	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;547548	fn test_impl<Tuple, TupleStruct, TypeStruct>(549		tuple_data: Tuple,550		tuple_struct_data: TupleStruct,551		type_struct_data: TypeStruct,552	) where553		TypeStruct: evm_coder::abi::AbiWrite554			+ evm_coder::abi::AbiRead555			+ std::cmp::PartialEq556			+ std::fmt::Debug,557		TupleStruct: evm_coder::abi::AbiWrite558			+ evm_coder::abi::AbiRead559			+ std::cmp::PartialEq560			+ std::fmt::Debug,561		Tuple: evm_coder::abi::AbiWrite562			+ evm_coder::abi::AbiRead563			+ std::cmp::PartialEq564			+ std::fmt::Debug,565	{566		let encoded_type_struct = test_abi_write_impl(&type_struct_data);567		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);568		let encoded_tuple = test_abi_write_impl(&tuple_data);569570		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);571		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);572573		{574			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();575			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();576			assert_eq!(restored_struct_data, type_struct_data);577		}578		{579			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();580			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();581			assert_eq!(restored_struct_data, tuple_struct_data);582		}583584		{585			let (_, mut decoder) =586				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();587			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();588			assert_eq!(restored_tuple_data, tuple_data);589		}590		{591			let (_, mut decoder) =592				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();593			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();594			assert_eq!(restored_tuple_data, tuple_data);595		}596	}597598	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>599	where600		A: evm_coder::abi::AbiWrite601			+ evm_coder::abi::AbiRead602			+ std::cmp::PartialEq603			+ std::fmt::Debug,604	{605		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);606		data.abi_write(&mut writer);607		let encoded_tuple = writer.finish();608		encoded_tuple609	}610611	#[test]612	fn codec_struct_1_simple() {613		let _a = 0xff;614		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(615			(_a,),616			TupleStruct1SimpleParam(_a),617			TypeStruct1SimpleParam { _a },618		);619	}620621	#[test]622	fn codec_struct_1_dynamic() {623		let _a: String = "some string".into();624		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(625			(_a.clone(),),626			TupleStruct1DynamicParam(_a.clone()),627			TypeStruct1DynamicParam { _a },628		);629	}630631	#[test]632	fn codec_struct_1_derived_simple() {633		let _a: u8 = 0xff;634		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(635			((_a,),),636			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),637			TypeStruct1DerivedSimpleParam {638				_a: TypeStruct1SimpleParam { _a },639			},640		);641	}642643	#[test]644	fn codec_struct_1_derived_dynamic() {645		let _a: String = "some string".into();646		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(647			((_a.clone(),),),648			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),649			TypeStruct1DerivedDynamicParam {650				_a: TypeStruct1DynamicParam { _a },651			},652		);653	}654655	#[test]656	fn codec_struct_2_simple() {657		let _a = 0xff;658		let _b = 0xbeefbaba;659		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(660			(_a, _b),661			TupleStruct2SimpleParam(_a, _b),662			TypeStruct2SimpleParam { _a, _b },663		);664	}665666	#[test]667	fn codec_struct_2_dynamic() {668		let _a: String = "some string".into();669		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);670		test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(671			(_a.clone(), _b.clone()),672			TupleStruct2DynamicParam(_a.clone(), _b.clone()),673			TypeStruct2DynamicParam { _a, _b },674		);675	}676677	#[test]678	fn codec_struct_2_mixed() {679		let _a: u8 = 0xff;680		let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);681		test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(682			(_a.clone(), _b.clone()),683			TupleStruct2MixedParam(_a.clone(), _b.clone()),684			TypeStruct2MixedParam { _a, _b },685		);686	}687688	#[test]689	fn codec_struct_2_derived_simple() {690		let _a = 0xff;691		let _b = 0xbeefbaba;692		test_impl::<693			((u8,), (u8, u32)),694			TupleStruct2DerivedSimpleParam,695			TypeStruct2DerivedSimpleParam,696		>(697			((_a,), (_a, _b)),698			TupleStruct2DerivedSimpleParam(699				TupleStruct1SimpleParam(_a),700				TupleStruct2SimpleParam(_a, _b),701			),702			TypeStruct2DerivedSimpleParam {703				_a: TypeStruct1SimpleParam { _a },704				_b: TypeStruct2SimpleParam { _a, _b },705			},706		);707	}708709	#[test]710	fn codec_struct_2_derived_dynamic() {711		let _a = "some string".to_string();712		let _b = bytes(vec![0x11, 0x22, 0x33]);713		test_impl::<714			((String,), (String, bytes)),715			TupleStruct2DerivedDynamicParam,716			TypeStruct2DerivedDynamicParam,717		>(718			((_a.clone(),), (_a.clone(), _b.clone())),719			TupleStruct2DerivedDynamicParam(720				TupleStruct1DynamicParam(_a.clone()),721				TupleStruct2DynamicParam(_a.clone(), _b.clone()),722			),723			TypeStruct2DerivedDynamicParam {724				_a: TypeStruct1DynamicParam { _a: _a.clone() },725				_b: TypeStruct2DynamicParam { _a, _b },726			},727		);728	}729730	#[test]731	fn codec_struct_3_derived_mixed() {732		let int = 0xff;733		let by = bytes(vec![0x11, 0x22, 0x33]);734		let string = "some string".to_string();735		test_impl::<736			((u8,), (String, bytes), (u8, bytes)),737			TupleStruct3DerivedMixedParam,738			TypeStruct3DerivedMixedParam,739		>(740			((int,), (string.clone(), by.clone()), (int, by.clone())),741			TupleStruct3DerivedMixedParam(742				TupleStruct1SimpleParam(int),743				TupleStruct2DynamicParam(string.clone(), by.clone()),744				TupleStruct2MixedParam(int, by.clone()),745			),746			TypeStruct3DerivedMixedParam {747				_a: TypeStruct1SimpleParam { _a: int },748				_b: TypeStruct2DynamicParam {749					_a: string.clone(),750					_b: by.clone(),751				},752				_c: TypeStruct2MixedParam { _a: int, _b: by },753			},754		);755	}756757	#[derive(AbiCoder, PartialEq, Debug)]758	struct TypeStruct2SimpleStruct1Simple {759		_a: TypeStruct2SimpleParam,760		_b: TypeStruct2SimpleParam,761		_c: u8,762	}763	#[derive(AbiCoder, PartialEq, Debug)]764	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);765766	#[test]767	fn codec_struct_2_struct_simple_1_simple() {768		let _a = 0xff;769		let _b = 0xbeefbaba;770		test_impl::<771			((u8, u32), (u8, u32), u8),772			TupleStruct2SimpleStruct1Simple,773			TypeStruct2SimpleStruct1Simple,774		>(775			((_a, _b), (_a, _b), _a),776			TupleStruct2SimpleStruct1Simple(777				TupleStruct2SimpleParam(_a, _b),778				TupleStruct2SimpleParam(_a, _b),779				_a,780			),781			TypeStruct2SimpleStruct1Simple {782				_a: TypeStruct2SimpleParam { _a, _b },783				_b: TypeStruct2SimpleParam { _a, _b },784				_c: _a,785			},786		);787	}788}789790mod test_enum {791	use evm_coder::AbiCoder;792793	/// Some docs794	/// At multi795	/// line796	#[derive(AbiCoder, Debug, PartialEq, Default, Clone, Copy)]797	#[repr(u8)]798	enum Color {799		/// Docs for Red800		/// multi801		/// line802		Red,803		Green,804		/// Docs for Blue805		#[default]806		Blue,807	}808809	#[test]810	fn empty() {}811812	#[test]813	fn bad_enums() {814		let t = trybuild::TestCases::new();815		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");816	}817818	#[test]819	fn impl_abi_type_signature_same_for_structs() {820		assert_eq!(821			<Color as evm_coder::abi::AbiType>::SIGNATURE822				.as_str()823				.unwrap(),824			<u8 as evm_coder::abi::AbiType>::SIGNATURE.as_str().unwrap()825		);826	}827828	#[test]829	fn impl_abi_type_is_dynamic_same_for_structs() {830		assert_eq!(831			<Color as evm_coder::abi::AbiType>::is_dynamic(),832			<u8 as evm_coder::abi::AbiType>::is_dynamic()833		);834	}835836	#[test]837	fn impl_abi_type_size_same_for_structs() {838		assert_eq!(839			<Color as evm_coder::abi::AbiType>::size(),840			<u8 as evm_coder::abi::AbiType>::size()841		);842	}843844	#[test]845	fn test_coder() {846		const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;847848		let encoded_enum = {849			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);850			<Color as evm_coder::abi::AbiWrite>::abi_write(&Color::Green, &mut writer);851			writer.finish()852		};853854		let encoded_u8 = {855			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);856			<u8 as evm_coder::abi::AbiWrite>::abi_write(&(Color::Green as u8), &mut writer);857			writer.finish()858		};859860		similar_asserts::assert_eq!(encoded_enum, encoded_u8);861862		{863			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_enum).unwrap();864			let restored_enum_data =865				<Color as evm_coder::abi::AbiRead>::abi_read(&mut decoder).unwrap();866			assert_eq!(restored_enum_data, Color::Green);867		}868	}869870	#[test]871	#[cfg(feature = "stubgen")]872	fn struct_collect_enum() {873		assert_eq!(874			<Color as ::evm_coder::solidity::StructCollect>::name(),875			"Color"876		);877		similar_asserts::assert_eq!(878			<Color as ::evm_coder::solidity::StructCollect>::declaration(),879			r#"/// @dev Some docs880/// At multi881/// line882enum Color {883	/// @dev Docs for Red884	/// multi885	/// line886	Red,887	Green,888	/// @dev Docs for Blue889	Blue890}891"#892		);893	}894}
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -16,6 +16,7 @@
 
 //! The module contains a number of functions for converting and checking ethereum identifiers.
 
+use sp_std::{vec, vec::Vec};
 use evm_coder::{
 	AbiCoder,
 	types::{uint256, address},
@@ -183,3 +184,102 @@
 	/// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin,
 }
+
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+#[derive(Debug, Default, AbiCoder)]
+pub struct PropertyPermission {
+	/// TokenPermission field.
+	code: EthTokenPermissions,
+	/// TokenPermission value.
+	value: bool,
+}
+
+impl PropertyPermission {
+	pub fn into_vec(pp: up_data_structs::PropertyPermission) -> Vec<Self> {
+		vec![
+			PropertyPermission {
+				code: EthTokenPermissions::Mutable,
+				value: pp.mutable,
+			},
+			PropertyPermission {
+				code: EthTokenPermissions::TokenOwner,
+				value: pp.token_owner,
+			},
+			PropertyPermission {
+				code: EthTokenPermissions::CollectionAdmin,
+				value: pp.collection_admin,
+			},
+		]
+	}
+
+	pub fn from_vec(permission: Vec<Self>) -> up_data_structs::PropertyPermission {
+		let mut token_permission = up_data_structs::PropertyPermission::default();
+
+		for PropertyPermission { code, value } in permission {
+			match code {
+				EthTokenPermissions::Mutable => token_permission.mutable = value,
+				EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
+				EthTokenPermissions::CollectionAdmin => token_permission.collection_admin = value,
+			}
+		}
+		token_permission
+	}
+}
+
+/// Ethereum representation of Token Property Permissions.
+#[derive(Debug, Default, AbiCoder)]
+pub struct TokenPropertyPermission {
+	/// Token property key.
+	key: evm_coder::types::string,
+	/// Token property permissions.
+	permissions: Vec<PropertyPermission>,
+}
+
+impl
+	From<(
+		up_data_structs::PropertyKey,
+		up_data_structs::PropertyPermission,
+	)> for TokenPropertyPermission
+{
+	fn from(
+		value: (
+			up_data_structs::PropertyKey,
+			up_data_structs::PropertyPermission,
+		),
+	) -> Self {
+		let (key, permission) = value;
+		let key = evm_coder::types::string::from_utf8(key.into_inner())
+			.expect("Stored key must be valid");
+		let permissions = PropertyPermission::into_vec(permission);
+		Self { key, permissions }
+	}
+}
+
+impl TokenPropertyPermission {
+	pub fn into_property_key_permissions(
+		permissions: Vec<TokenPropertyPermission>,
+	) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {
+		let mut perms = Vec::new();
+
+		for TokenPropertyPermission { key, permissions } in permissions {
+			if permissions.len() > <EthTokenPermissions as evm_coder::abi::AbiType>::FIELDS_COUNT {
+				return Err(alloc::format!(
+					"Actual number of fields {} for {}, which exceeds the maximum value of {}",
+					permissions.len(),
+					stringify!(EthTokenPermissions),
+					<EthTokenPermissions as evm_coder::abi::AbiType>::FIELDS_COUNT
+				)
+				.as_str()
+				.into());
+			}
+
+			let token_permission = PropertyPermission::from_vec(permissions);
+
+			perms.push(up_data_structs::PropertyKeyPermission {
+				key: key.into_bytes().try_into().map_err(|_| "too long key")?,
+				permission: token_permission,
+			});
+		}
+		Ok(perms)
+	}
+}
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

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
@@ -470,9 +470,12 @@
 	uint256 sub;
 }
 
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissions {
-	CollectionAdmin,
-	TokenOwner
+	/// @dev Owner of token can nest tokens under it.
+	TokenOwner,
+	/// @dev Admin of token collection can nest tokens under token.
+	CollectionAdmin
 }
 
 /// @dev anonymous struct
@@ -516,9 +519,11 @@
 	uint256 field_2;
 }
 
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
+	/// @dev Property key.
 	string key;
+	/// @dev Property value.
 	bytes value;
 }
 
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -38,7 +38,7 @@
 use pallet_common::{
 	CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
 	erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
-	eth::{Property as PropertyStruct, EthCrossAccount, EthTokenPermissions},
+	eth::{Property as PropertyStruct, EthCrossAccount},
 };
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
 use pallet_evm_coder_substrate::call;
@@ -94,40 +94,12 @@
 	fn set_token_property_permissions(
 		&mut self,
 		caller: caller,
-		permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
+		permissions: Vec<pallet_common::eth::TokenPropertyPermission>,
 	) -> Result<()> {
 		let caller = T::CrossAccountId::from_eth(caller);
-		let mut perms = Vec::new();
-
-		for (key, pp) in permissions {
-			if pp.len() > EthTokenPermissions::FIELDS_COUNT {
-				return Err(alloc::format!(
-					"Actual number of fields {} for {}, which exceeds the maximum value of {}",
-					pp.len(),
-					stringify!(EthTokenPermissions),
-					EthTokenPermissions::FIELDS_COUNT
-				)
-				.as_str()
-				.into());
-			}
-
-			let mut token_permission = PropertyPermission::default();
-
-			for (perm, value) in pp {
-				match perm {
-					EthTokenPermissions::Mutable => token_permission.mutable = value,
-					EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
-					EthTokenPermissions::CollectionAdmin => {
-						token_permission.collection_admin = value
-					}
-				}
-			}
-
-			perms.push(PropertyKeyPermission {
-				key: key.into_bytes().try_into().map_err(|_| "too long key")?,
-				permission: token_permission,
-			});
-		}
+		let perms = pallet_common::eth::TokenPropertyPermission::into_property_key_permissions(
+			permissions,
+		)?;
 
 		<Pallet<T>>::set_token_property_permissions(self, &caller, perms)
 			.map_err(dispatch_to_evm::<T>)
@@ -136,19 +108,11 @@
 	/// @notice Get permissions for token properties.
 	fn token_property_permissions(
 		&self,
-	) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
+	) -> Result<Vec<pallet_common::eth::TokenPropertyPermission>> {
 		let perms = <Pallet<T>>::token_property_permission(self.id);
 		Ok(perms
 			.into_iter()
-			.map(|(key, pp)| {
-				let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
-				let pp = vec![
-					(EthTokenPermissions::Mutable, pp.mutable),
-					(EthTokenPermissions::TokenOwner, pp.token_owner),
-					(EthTokenPermissions::CollectionAdmin, pp.collection_admin),
-				];
-				(key, pp)
-			})
+			.map(pallet_common::eth::TokenPropertyPermission::from)
 			.collect())
 	}
 
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
@@ -42,7 +42,7 @@
 	/// @param permissions Permissions for keys.
 	/// @dev EVM selector for this function is: 0xbd92983a,
 	///  or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
-	function setTokenPropertyPermissions(Tuple61[] memory permissions) public {
+	function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) public {
 		require(false, stub_error);
 		permissions;
 		dummy = 0;
@@ -51,10 +51,10 @@
 	/// @notice Get permissions for token properties.
 	/// @dev EVM selector for this function is: 0xf23d7790,
 	///  or in textual repr: tokenPropertyPermissions()
-	function tokenPropertyPermissions() public view returns (Tuple61[] memory) {
+	function tokenPropertyPermissions() public view returns (TokenPropertyPermission[] memory) {
 		require(false, stub_error);
 		dummy;
-		return new Tuple61[](0);
+		return new TokenPropertyPermission[](0);
 	}
 
 	// /// @notice Set token property value.
@@ -127,12 +127,30 @@
 	}
 }
 
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
+	/// @dev Property key.
 	string key;
+	/// @dev Property value.
 	bytes value;
 }
 
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+	/// @dev Token property key.
+	string key;
+	/// @dev Token property permissions.
+	PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+	/// @dev TokenPermission field.
+	EthTokenPermissions code;
+	/// @dev TokenPermission value.
+	bool value;
+}
+
 /// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum EthTokenPermissions {
 	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -141,18 +159,6 @@
 	TokenOwner,
 	/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin
-}
-
-/// @dev anonymous struct
-struct Tuple61 {
-	string field_0;
-	Tuple59[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple59 {
-	EthTokenPermissions field_0;
-	bool field_1;
 }
 
 /// @title A contract that allows you to work with collections.
@@ -608,9 +614,12 @@
 	uint256 sub;
 }
 
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissions {
-	CollectionAdmin,
-	TokenOwner
+	/// @dev Owner of token can nest tokens under it.
+	TokenOwner,
+	/// @dev Admin of token collection can nest tokens under token.
+	CollectionAdmin
 }
 
 /// @dev anonymous struct
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -33,7 +33,7 @@
 use pallet_common::{
 	CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
 	erc::{CommonEvmHandler, CollectionCall, static_property::key},
-	eth::{Property as PropertyStruct, EthCrossAccount, EthTokenPermissions},
+	eth::{Property as PropertyStruct, EthCrossAccount},
 	Error as CommonError,
 };
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
@@ -97,47 +97,13 @@
 	fn set_token_property_permissions(
 		&mut self,
 		caller: caller,
-		permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
+		permissions: Vec<pallet_common::eth::TokenPropertyPermission>,
 	) -> Result<()> {
 		let caller = T::CrossAccountId::from_eth(caller);
-		const PERMISSIONS_FIELDS_COUNT: usize = 3;
-
-		let mut perms = Vec::new();
-
-		for (key, pp) in permissions {
-			if pp.len() > PERMISSIONS_FIELDS_COUNT {
-				return Err(alloc::format!(
-					"Actual number of fields {} for {}, which exceeds the maximum value of {}",
-					pp.len(),
-					stringify!(EthTokenPermissions),
-					PERMISSIONS_FIELDS_COUNT
-				)
-				.as_str()
-				.into());
-			}
-
-			let mut token_permission = PropertyPermission {
-				mutable: false,
-				collection_admin: false,
-				token_owner: false,
-			};
+		let perms = pallet_common::eth::TokenPropertyPermission::into_property_key_permissions(
+			permissions,
+		)?;
 
-			for (perm, value) in pp {
-				match perm {
-					EthTokenPermissions::Mutable => token_permission.mutable = value,
-					EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
-					EthTokenPermissions::CollectionAdmin => {
-						token_permission.collection_admin = value
-					}
-				}
-			}
-
-			perms.push(PropertyKeyPermission {
-				key: key.into_bytes().try_into().map_err(|_| "too long key")?,
-				permission: token_permission,
-			});
-		}
-
 		<Pallet<T>>::set_token_property_permissions(self, &caller, perms)
 			.map_err(dispatch_to_evm::<T>)
 	}
@@ -145,19 +111,11 @@
 	/// @notice Get permissions for token properties.
 	fn token_property_permissions(
 		&self,
-	) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
+	) -> Result<Vec<pallet_common::eth::TokenPropertyPermission>> {
 		let perms = <Pallet<T>>::token_property_permission(self.id);
 		Ok(perms
 			.into_iter()
-			.map(|(key, pp)| {
-				let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
-				let pp = vec![
-					(EthTokenPermissions::Mutable, pp.mutable),
-					(EthTokenPermissions::TokenOwner, pp.token_owner),
-					(EthTokenPermissions::CollectionAdmin, pp.collection_admin),
-				];
-				(key, pp)
-			})
+			.map(pallet_common::eth::TokenPropertyPermission::from)
 			.collect())
 	}
 
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
@@ -42,7 +42,7 @@
 	/// @param permissions Permissions for keys.
 	/// @dev EVM selector for this function is: 0xbd92983a,
 	///  or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
-	function setTokenPropertyPermissions(Tuple60[] memory permissions) public {
+	function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) public {
 		require(false, stub_error);
 		permissions;
 		dummy = 0;
@@ -51,10 +51,10 @@
 	/// @notice Get permissions for token properties.
 	/// @dev EVM selector for this function is: 0xf23d7790,
 	///  or in textual repr: tokenPropertyPermissions()
-	function tokenPropertyPermissions() public view returns (Tuple60[] memory) {
+	function tokenPropertyPermissions() public view returns (TokenPropertyPermission[] memory) {
 		require(false, stub_error);
 		dummy;
-		return new Tuple60[](0);
+		return new TokenPropertyPermission[](0);
 	}
 
 	// /// @notice Set token property value.
@@ -127,12 +127,30 @@
 	}
 }
 
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
+	/// @dev Property key.
 	string key;
+	/// @dev Property value.
 	bytes value;
 }
 
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+	/// @dev Token property key.
+	string key;
+	/// @dev Token property permissions.
+	PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+	/// @dev TokenPermission field.
+	EthTokenPermissions code;
+	/// @dev TokenPermission value.
+	bool value;
+}
+
 /// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum EthTokenPermissions {
 	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -141,18 +159,6 @@
 	TokenOwner,
 	/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
 	CollectionAdmin
-}
-
-/// @dev anonymous struct
-struct Tuple60 {
-	string field_0;
-	Tuple58[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple58 {
-	EthTokenPermissions field_0;
-	bool field_1;
 }
 
 /// @title A contract that allows you to work with collections.
@@ -608,9 +614,12 @@
 	uint256 sub;
 }
 
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissions {
-	CollectionAdmin,
-	TokenOwner
+	/// @dev Owner of token can nest tokens under it.
+	TokenOwner,
+	/// @dev Admin of token collection can nest tokens under token.
+	CollectionAdmin
 }
 
 /// @dev anonymous struct
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -752,22 +752,22 @@
     "inputs": [
       {
         "components": [
-          { "internalType": "string", "name": "field_0", "type": "string" },
+          { "internalType": "string", "name": "key", "type": "string" },
           {
             "components": [
               {
                 "internalType": "enum EthTokenPermissions",
-                "name": "field_0",
+                "name": "code",
                 "type": "uint8"
               },
-              { "internalType": "bool", "name": "field_1", "type": "bool" }
+              { "internalType": "bool", "name": "value", "type": "bool" }
             ],
-            "internalType": "struct Tuple59[]",
-            "name": "field_1",
+            "internalType": "struct PropertyPermission[]",
+            "name": "permissions",
             "type": "tuple[]"
           }
         ],
-        "internalType": "struct Tuple61[]",
+        "internalType": "struct TokenPropertyPermission[]",
         "name": "permissions",
         "type": "tuple[]"
       }
@@ -818,22 +818,22 @@
     "outputs": [
       {
         "components": [
-          { "internalType": "string", "name": "field_0", "type": "string" },
+          { "internalType": "string", "name": "key", "type": "string" },
           {
             "components": [
               {
                 "internalType": "enum EthTokenPermissions",
-                "name": "field_0",
+                "name": "code",
                 "type": "uint8"
               },
-              { "internalType": "bool", "name": "field_1", "type": "bool" }
+              { "internalType": "bool", "name": "value", "type": "bool" }
             ],
-            "internalType": "struct Tuple59[]",
-            "name": "field_1",
+            "internalType": "struct PropertyPermission[]",
+            "name": "permissions",
             "type": "tuple[]"
           }
         ],
-        "internalType": "struct Tuple61[]",
+        "internalType": "struct TokenPropertyPermission[]",
         "name": "",
         "type": "tuple[]"
       }
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -734,22 +734,22 @@
     "inputs": [
       {
         "components": [
-          { "internalType": "string", "name": "field_0", "type": "string" },
+          { "internalType": "string", "name": "key", "type": "string" },
           {
             "components": [
               {
                 "internalType": "enum EthTokenPermissions",
-                "name": "field_0",
+                "name": "code",
                 "type": "uint8"
               },
-              { "internalType": "bool", "name": "field_1", "type": "bool" }
+              { "internalType": "bool", "name": "value", "type": "bool" }
             ],
-            "internalType": "struct Tuple58[]",
-            "name": "field_1",
+            "internalType": "struct PropertyPermission[]",
+            "name": "permissions",
             "type": "tuple[]"
           }
         ],
-        "internalType": "struct Tuple60[]",
+        "internalType": "struct TokenPropertyPermission[]",
         "name": "permissions",
         "type": "tuple[]"
       }
@@ -809,22 +809,22 @@
     "outputs": [
       {
         "components": [
-          { "internalType": "string", "name": "field_0", "type": "string" },
+          { "internalType": "string", "name": "key", "type": "string" },
           {
             "components": [
               {
                 "internalType": "enum EthTokenPermissions",
-                "name": "field_0",
+                "name": "code",
                 "type": "uint8"
               },
-              { "internalType": "bool", "name": "field_1", "type": "bool" }
+              { "internalType": "bool", "name": "value", "type": "bool" }
             ],
-            "internalType": "struct Tuple58[]",
-            "name": "field_1",
+            "internalType": "struct PropertyPermission[]",
+            "name": "permissions",
             "type": "tuple[]"
           }
         ],
-        "internalType": "struct Tuple60[]",
+        "internalType": "struct TokenPropertyPermission[]",
         "name": "",
         "type": "tuple[]"
       }
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -316,9 +316,12 @@
 	bool field_1;
 }
 
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissions {
-	CollectionAdmin,
-	TokenOwner
+	/// @dev Owner of token can nest tokens under it.
+	TokenOwner,
+	/// @dev Admin of token collection can nest tokens under token.
+	CollectionAdmin
 }
 
 /// @dev anonymous struct
@@ -356,9 +359,11 @@
 	uint256 field_2;
 }
 
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
+	/// @dev Property key.
 	string key;
+	/// @dev Property value.
 	bytes value;
 }
 
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -30,12 +30,12 @@
 	/// @param permissions Permissions for keys.
 	/// @dev EVM selector for this function is: 0xbd92983a,
 	///  or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
-	function setTokenPropertyPermissions(Tuple53[] memory permissions) external;
+	function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) external;
 
 	/// @notice Get permissions for token properties.
 	/// @dev EVM selector for this function is: 0xf23d7790,
 	///  or in textual repr: tokenPropertyPermissions()
-	function tokenPropertyPermissions() external view returns (Tuple53[] memory);
+	function tokenPropertyPermissions() external view returns (TokenPropertyPermission[] memory);
 
 	// /// @notice Set token property value.
 	// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -80,12 +80,30 @@
 	function property(uint256 tokenId, string memory key) external view returns (bytes memory);
 }
 
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
+	/// @dev Property key.
 	string key;
+	/// @dev Property value.
 	bytes value;
 }
 
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+	/// @dev Token property key.
+	string key;
+	/// @dev Token property permissions.
+	PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+	/// @dev TokenPermission field.
+	EthTokenPermissions code;
+	/// @dev TokenPermission value.
+	bool value;
+}
+
 /// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum EthTokenPermissions {
 	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -96,18 +114,6 @@
 	CollectionAdmin
 }
 
-/// @dev anonymous struct
-struct Tuple53 {
-	string field_0;
-	Tuple51[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple51 {
-	EthTokenPermissions field_0;
-	bool field_1;
-}
-
 /// @title A contract that allows you to work with collections.
 /// @dev the ERC-165 identifier for this interface is 0x81172a75
 interface Collection is Dummy, ERC165 {
@@ -412,9 +418,12 @@
 	bool field_1;
 }
 
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissions {
-	CollectionAdmin,
-	TokenOwner
+	/// @dev Owner of token can nest tokens under it.
+	TokenOwner,
+	/// @dev Admin of token collection can nest tokens under token.
+	CollectionAdmin
 }
 
 /// @dev anonymous struct
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -30,12 +30,12 @@
 	/// @param permissions Permissions for keys.
 	/// @dev EVM selector for this function is: 0xbd92983a,
 	///  or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
-	function setTokenPropertyPermissions(Tuple52[] memory permissions) external;
+	function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) external;
 
 	/// @notice Get permissions for token properties.
 	/// @dev EVM selector for this function is: 0xf23d7790,
 	///  or in textual repr: tokenPropertyPermissions()
-	function tokenPropertyPermissions() external view returns (Tuple52[] memory);
+	function tokenPropertyPermissions() external view returns (TokenPropertyPermission[] memory);
 
 	// /// @notice Set token property value.
 	// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -80,12 +80,30 @@
 	function property(uint256 tokenId, string memory key) external view returns (bytes memory);
 }
 
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
 struct Property {
+	/// @dev Property key.
 	string key;
+	/// @dev Property value.
 	bytes value;
 }
 
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+	/// @dev Token property key.
+	string key;
+	/// @dev Token property permissions.
+	PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+	/// @dev TokenPermission field.
+	EthTokenPermissions code;
+	/// @dev TokenPermission value.
+	bool value;
+}
+
 /// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
 enum EthTokenPermissions {
 	/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -96,18 +114,6 @@
 	CollectionAdmin
 }
 
-/// @dev anonymous struct
-struct Tuple52 {
-	string field_0;
-	Tuple50[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple50 {
-	EthTokenPermissions field_0;
-	bool field_1;
-}
-
 /// @title A contract that allows you to work with collections.
 /// @dev the ERC-165 identifier for this interface is 0x81172a75
 interface Collection is Dummy, ERC165 {
@@ -412,9 +418,12 @@
 	bool field_1;
 }
 
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
 enum CollectionPermissions {
-	CollectionAdmin,
-	TokenOwner
+	/// @dev Owner of token can nest tokens under it.
+	TokenOwner,
+	/// @dev Admin of token collection can nest tokens under token.
+	CollectionAdmin
 }
 
 /// @dev anonymous struct