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

difftreelog

refactor custom_signature.rs

Trubnikov Sergey2022-10-24parent: #15e4512.patch.diff
in: master

13 files changed

modifiedcrates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth
before · crates/evm-coder/procedural/src/solidity_interface.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![allow(dead_code)]1819// NOTE: In order to understand this Rust macro better, first read this chapter20// about Procedural Macros in Rust book:21// https://doc.rust-lang.org/reference/procedural-macros.html2223use proc_macro2::{TokenStream, Group};24use quote::{quote, ToTokens, format_ident};25use inflector::cases;26use std::fmt::Write;27use syn::{28	Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,29	MetaNameValue, PatType, PathArguments, ReturnType, Type,30	spanned::Spanned,31	parse::{Parse, ParseStream},32	parenthesized, Token, LitInt, LitStr,33};3435use crate::{36	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,37	parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,38	snake_ident_to_screaming,39};4041struct Is {42	name: Ident,43	pascal_call_name: Ident,44	snake_call_name: Ident,45	via: Option<(Type, Ident)>,46	condition: Option<Expr>,47}48impl Is {49	fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {50		let name = &self.name;51		let pascal_call_name = &self.pascal_call_name;52		quote! {53			#name(#pascal_call_name #gen_ref)54		}55	}5657	fn expand_interface_id(&self) -> proc_macro2::TokenStream {58		let pascal_call_name = &self.pascal_call_name;59		quote! {60			interface_id ^= u32::from_be_bytes(#pascal_call_name::interface_id());61		}62	}6364	fn expand_supports_interface(65		&self,66		generics: &proc_macro2::TokenStream,67	) -> proc_macro2::TokenStream {68		let pascal_call_name = &self.pascal_call_name;69		let condition = self.condition.as_ref().map(|condition| {70			quote! {71				(#condition) &&72			}73		});74		quote! {75			#condition <#pascal_call_name #generics>::supports_interface(this, interface_id)76		}77	}7879	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {80		let name = &self.name;81		quote! {82			Self::#name(call) => call.weight()83		}84	}8586	fn expand_variant_call(87		&self,88		call_name: &proc_macro2::Ident,89		generics: &proc_macro2::TokenStream,90	) -> proc_macro2::TokenStream {91		let name = &self.name;92		let pascal_call_name = &self.pascal_call_name;93		let via_typ = self94			.via95			.as_ref()96			.map(|(t, _)| quote! {#t})97			.unwrap_or_else(|| quote! {Self});98		let via_map = self99			.via100			.as_ref()101			.map(|(_, i)| quote! {.#i()})102			.unwrap_or_default();103		let condition = self.condition.as_ref().map(|condition| {104			quote! {105				if ({let this = &self; (#condition)})106			}107		});108		quote! {109			#call_name::#name(call) #condition => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {110				call,111				caller: c.caller,112				value: c.value,113			})114		}115	}116117	fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {118		let name = &self.name;119		let pascal_call_name = &self.pascal_call_name;120		quote! {121			if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {122				return Ok(Some(Self::#name(parsed_call)))123			}124		}125	}126127	fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {128		let pascal_call_name = &self.pascal_call_name;129		quote! {130			<#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);131		}132	}133134	fn expand_event_generator(&self) -> proc_macro2::TokenStream {135		let name = &self.name;136		quote! {137			#name::generate_solidity_interface(tc, is_impl);138		}139	}140}141142#[derive(Default)]143struct IsList(Vec<Is>);144impl Parse for IsList {145	fn parse(input: ParseStream) -> syn::Result<Self> {146		let mut out = vec![];147		loop {148			if input.is_empty() {149				break;150			}151			let name = input.parse::<Ident>()?;152			let lookahead = input.lookahead1();153154			let mut condition: Option<Expr> = None;155			let mut via: Option<(Type, Ident)> = None;156157			if lookahead.peek(syn::token::Paren) {158				let contents;159				parenthesized!(contents in input);160				let input = contents;161162				while !input.is_empty() {163					let lookahead = input.lookahead1();164					if lookahead.peek(Token![if]) {165						input.parse::<Token![if]>()?;166						let contents;167						parenthesized!(contents in input);168						let contents = contents.parse::<Expr>()?;169170						if condition.replace(contents).is_some() {171							return Err(syn::Error::new(input.span(), "condition is already set"));172						}173					} else if lookahead.peek(kw::via) {174						input.parse::<kw::via>()?;175						let contents;176						parenthesized!(contents in input);177178						let method = contents.parse::<Ident>()?;179						contents.parse::<kw::returns>()?;180						let ty = contents.parse::<Type>()?;181182						if via.replace((ty, method)).is_some() {183							return Err(syn::Error::new(input.span(), "via is already set"));184						}185					} else {186						return Err(lookahead.error());187					}188189					if input.peek(Token![,]) {190						input.parse::<Token![,]>()?;191					} else if !input.is_empty() {192						return Err(syn::Error::new(input.span(), "expected end"));193					}194				}195			} else if lookahead.peek(Token![,]) || input.is_empty() {196				// Pass197			} else {198				return Err(lookahead.error());199			};200			out.push(Is {201				pascal_call_name: pascal_ident_to_call(&name),202				snake_call_name: pascal_ident_to_snake_call(&name),203				name,204				via,205				condition,206			});207			if input.peek(Token![,]) {208				input.parse::<Token![,]>()?;209				continue;210			} else {211				break;212			}213		}214		Ok(Self(out))215	}216}217218pub struct InterfaceInfo {219	name: Ident,220	is: IsList,221	inline_is: IsList,222	events: IsList,223	expect_selector: Option<u32>,224}225impl Parse for InterfaceInfo {226	fn parse(input: ParseStream) -> syn::Result<Self> {227		let mut name = None;228		let mut is = None;229		let mut inline_is = None;230		let mut events = None;231		let mut expect_selector = None;232		// TODO: create proc-macro to optimize proc-macro boilerplate? :D233		loop {234			let lookahead = input.lookahead1();235			if lookahead.peek(kw::name) {236				let k = input.parse::<kw::name>()?;237				input.parse::<Token![=]>()?;238				if name.replace(input.parse::<Ident>()?).is_some() {239					return Err(syn::Error::new(k.span(), "name is already set"));240				}241			} else if lookahead.peek(kw::is) {242				let k = input.parse::<kw::is>()?;243				let contents;244				parenthesized!(contents in input);245				if is.replace(contents.parse::<IsList>()?).is_some() {246					return Err(syn::Error::new(k.span(), "is is already set"));247				}248			} else if lookahead.peek(kw::inline_is) {249				let k = input.parse::<kw::inline_is>()?;250				let contents;251				parenthesized!(contents in input);252				if inline_is.replace(contents.parse::<IsList>()?).is_some() {253					return Err(syn::Error::new(k.span(), "inline_is is already set"));254				}255			} else if lookahead.peek(kw::events) {256				let k = input.parse::<kw::events>()?;257				let contents;258				parenthesized!(contents in input);259				if events.replace(contents.parse::<IsList>()?).is_some() {260					return Err(syn::Error::new(k.span(), "events is already set"));261				}262			} else if lookahead.peek(kw::expect_selector) {263				let k = input.parse::<kw::expect_selector>()?;264				input.parse::<Token![=]>()?;265				let value = input.parse::<LitInt>()?;266				if expect_selector267					.replace(value.base10_parse::<u32>()?)268					.is_some()269				{270					return Err(syn::Error::new(k.span(), "expect_selector is already set"));271				}272			} else if input.is_empty() {273				break;274			} else {275				return Err(lookahead.error());276			}277			if input.peek(Token![,]) {278				input.parse::<Token![,]>()?;279			} else {280				break;281			}282		}283		Ok(Self {284			name: name.ok_or_else(|| syn::Error::new(input.span(), "missing name"))?,285			is: is.unwrap_or_default(),286			inline_is: inline_is.unwrap_or_default(),287			events: events.unwrap_or_default(),288			expect_selector,289		})290	}291}292293struct MethodInfo {294	rename_selector: Option<String>,295	hide: bool,296}297impl Parse for MethodInfo {298	fn parse(input: ParseStream) -> syn::Result<Self> {299		let mut rename_selector = None;300		let mut hide = false;301		while !input.is_empty() {302			let lookahead = input.lookahead1();303			if lookahead.peek(kw::rename_selector) {304				let k = input.parse::<kw::rename_selector>()?;305				input.parse::<Token![=]>()?;306				if rename_selector307					.replace(input.parse::<LitStr>()?.value())308					.is_some()309				{310					return Err(syn::Error::new(k.span(), "rename_selector is already set"));311				}312			} else if lookahead.peek(kw::hide) {313				input.parse::<kw::hide>()?;314				hide = true;315			} else {316				return Err(lookahead.error());317			}318319			if input.peek(Token![,]) {320				input.parse::<Token![,]>()?;321			} else if !input.is_empty() {322				return Err(syn::Error::new(input.span(), "expected end"));323			}324		}325		Ok(Self {326			rename_selector,327			hide,328		})329	}330}331332#[derive(Debug)]333enum AbiType {334	// type335	Plain(Ident),336	// (type1,type2)337	Tuple(Vec<AbiType>),338	// type[]339	Vec(Box<AbiType>),340	// type[20]341	Array(Box<AbiType>, usize),342}343impl AbiType {344	fn try_from(value: &Type) -> syn::Result<Self> {345		let value = Self::try_maybe_special_from(value)?;346		if value.is_special() {347			return Err(syn::Error::new(value.span(), "unexpected special type"));348		}349		Ok(value)350	}351	fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {352		match value {353			Type::Array(arr) => {354				let wrapped = AbiType::try_from(&arr.elem)?;355				match &arr.len {356					Expr::Lit(l) => match &l.lit {357						Lit::Int(i) => {358							let num = i.base10_parse::<usize>()?;359							Ok(AbiType::Array(Box::new(wrapped), num as usize))360						}361						_ => Err(syn::Error::new(arr.len.span(), "should be int literal")),362					},363					_ => Err(syn::Error::new(arr.len.span(), "should be literal")),364				}365			}366			Type::Path(_) => {367				let path = parse_path(value)?;368				let segment = parse_path_segment(path)?;369				if segment.ident == "Vec" {370					let args = match &segment.arguments {371						PathArguments::AngleBracketed(e) => e,372						_ => {373							return Err(syn::Error::new(374								segment.arguments.span(),375								"missing Vec generic",376							))377						}378					};379					let args = &args.args;380					if args.len() != 1 {381						return Err(syn::Error::new(382							args.span(),383							"expected only one generic for vec",384						));385					}386					let arg = args.first().expect("first arg");387388					let ty = match arg {389						GenericArgument::Type(ty) => ty,390						_ => {391							return Err(syn::Error::new(392								arg.span(),393								"expected first generic to be type",394							))395						}396					};397398					let wrapped = AbiType::try_from(ty)?;399					Ok(Self::Vec(Box::new(wrapped)))400				} else {401					if !segment.arguments.is_empty() {402						return Err(syn::Error::new(403							segment.arguments.span(),404							"unexpected generic arguments for non-vec type",405						));406					}407					Ok(Self::Plain(segment.ident.clone()))408				}409			}410			Type::Tuple(t) => {411				let mut out = Vec::with_capacity(t.elems.len());412				for el in t.elems.iter() {413					out.push(AbiType::try_from(el)?)414				}415				Ok(Self::Tuple(out))416			}417			_ => Err(syn::Error::new(418				value.span(),419				"unexpected type, only arrays, plain types and tuples are supported",420			)),421		}422	}423	fn is_value(&self) -> bool {424		matches!(self, Self::Plain(v) if v == "value")425	}426	fn is_caller(&self) -> bool {427		matches!(self, Self::Plain(v) if v == "caller")428	}429	fn is_special(&self) -> bool {430		self.is_caller() || self.is_value()431	}432	fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {433		match self {434			AbiType::Plain(t) => {435				write!(buf, "{}", t)436			}437			AbiType::Tuple(t) => {438				write!(buf, "(")?;439				for (i, t) in t.iter().enumerate() {440					if i != 0 {441						write!(buf, ",")?;442					}443					t.selector_ty_buf(buf)?;444				}445				write!(buf, ")")446			}447			AbiType::Vec(v) => {448				v.selector_ty_buf(buf)?;449				write!(buf, "[]")450			}451			AbiType::Array(v, len) => {452				v.selector_ty_buf(buf)?;453				write!(buf, "[{}]", len)454			}455		}456	}457	fn selector_ty(&self) -> String {458		let mut out = String::new();459		self.selector_ty_buf(&mut out).expect("no fmt error");460		out461	}462}463impl ToTokens for AbiType {464	fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {465		match self {466			AbiType::Plain(t) => tokens.extend(quote! {#t}),467			AbiType::Tuple(t) => {468				tokens.extend(quote! {(469					#(#t),*470				)});471			}472			AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),473			AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),474		}475	}476}477478#[derive(Debug)]479struct MethodArg {480	name: Ident,481	camel_name: String,482	ty: AbiType,483}484impl MethodArg {485	fn try_from(value: &PatType) -> syn::Result<Self> {486		let name = parse_ident_from_pat(&value.pat)?.clone();487		Ok(Self {488			camel_name: cases::camelcase::to_camel_case(&name.to_string()),489			name,490			ty: AbiType::try_maybe_special_from(&value.ty)?,491		})492	}493	fn is_value(&self) -> bool {494		self.ty.is_value()495	}496	fn is_caller(&self) -> bool {497		self.ty.is_caller()498	}499	fn is_special(&self) -> bool {500		self.ty.is_special()501	}502	fn selector_ty(&self) -> String {503		assert!(!self.is_special());504		self.ty.selector_ty()505	}506507	fn expand_call_def(&self) -> proc_macro2::TokenStream {508		assert!(!self.is_special());509		let name = &self.name;510		let ty = &self.ty;511512		quote! {513			#name: #ty514		}515	}516517	fn expand_parse(&self) -> proc_macro2::TokenStream {518		assert!(!self.is_special());519		let name = &self.name;520		quote! {521			#name: reader.abi_read()?522		}523	}524525	fn expand_call_arg(&self) -> proc_macro2::TokenStream {526		if self.is_value() {527			quote! {528				c.value.clone()529			}530		} else if self.is_caller() {531			quote! {532				c.caller.clone()533			}534		} else {535			let name = &self.name;536			quote! {537				#name538			}539		}540	}541542	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {543		let camel_name = &self.camel_name.to_string();544		let ty = &self.ty;545		quote! {546			<NamedArgument<#ty>>::new(#camel_name)547		}548	}549}550551#[derive(PartialEq)]552enum Mutability {553	Mutable,554	View,555	Pure,556}557558/// Group all keywords for this macro. Usage example:559/// #[solidity_interface(name = "B", inline_is(A))]560mod kw {561	syn::custom_keyword!(weight);562563	syn::custom_keyword!(via);564	syn::custom_keyword!(returns);565	syn::custom_keyword!(name);566	syn::custom_keyword!(is);567	syn::custom_keyword!(inline_is);568	syn::custom_keyword!(events);569	syn::custom_keyword!(expect_selector);570571	syn::custom_keyword!(rename_selector);572	syn::custom_keyword!(hide);573}574575/// Rust methods are parsed into this structure when Solidity code is generated576struct Method {577	name: Ident,578	camel_name: String,579	pascal_name: Ident,580	screaming_name: Ident,581	selector_str: String,582	selector: u32,583	hide: bool,584	args: Vec<MethodArg>,585	has_normal_args: bool,586	has_value_args: bool,587	mutability: Mutability,588	result: Type,589	weight: Option<Expr>,590	docs: Vec<String>,591}592impl Method {593	fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {594		let mut info = MethodInfo {595			rename_selector: None,596			hide: false,597		};598		let mut docs = Vec::new();599		let mut weight = None;600		for attr in &value.attrs {601			let ident = parse_ident_from_path(&attr.path, false)?;602			if ident == "solidity" {603				info = attr.parse_args::<MethodInfo>()?;604			} else if ident == "doc" {605				let args = attr.parse_meta().unwrap();606				let value = match args {607					Meta::NameValue(MetaNameValue {608						lit: Lit::Str(str), ..609					}) => str.value(),610					_ => unreachable!(),611				};612				docs.push(value);613			} else if ident == "weight" {614				weight = Some(attr.parse_args::<Expr>()?);615			}616		}617		let ident = &value.sig.ident;618		let ident_str = ident.to_string();619		if !cases::snakecase::is_snake_case(&ident_str) {620			return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));621		}622623		let mut mutability = Mutability::Pure;624625		if let Some(FnArg::Receiver(receiver)) = value626			.sig627			.inputs628			.iter()629			.find(|arg| matches!(arg, FnArg::Receiver(_)))630		{631			if receiver.reference.is_none() {632				return Err(syn::Error::new(633					receiver.span(),634					"receiver should be by ref",635				));636			}637			if receiver.mutability.is_some() {638				mutability = Mutability::Mutable;639			} else {640				mutability = Mutability::View;641			}642		}643		let mut args = Vec::new();644		for typ in value645			.sig646			.inputs647			.iter()648			.filter(|arg| matches!(arg, FnArg::Typed(_)))649		{650			let typ = match typ {651				FnArg::Typed(typ) => typ,652				_ => unreachable!(),653			};654			args.push(MethodArg::try_from(typ)?);655		}656657		if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {658			return Err(syn::Error::new(659				args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),660				"payable function should be mutable",661			));662		}663664		let result = match &value.sig.output {665			ReturnType::Type(_, ty) => ty,666			_ => return Err(syn::Error::new(value.sig.output.span(), "interface method should return Result<value>\nif there is no value to return - specify void (which is alias to unit)")),667		};668		let result = parse_result_ok(result)?;669670		let camel_name = info671			.rename_selector672			.unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));673		let mut selector_str = camel_name.clone();674		selector_str.push('(');675		let mut has_normal_args = false;676		for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {677			if i != 0 {678				selector_str.push(',');679			}680			write!(selector_str, "{}", arg.selector_ty()).unwrap();681			has_normal_args = true;682		}683		let has_value_args = args.iter().any(|a| a.is_value());684		selector_str.push(')');685		let selector = fn_selector_str(&selector_str);686687		Ok(Self {688			name: ident.clone(),689			camel_name,690			pascal_name: snake_ident_to_pascal(ident),691			screaming_name: snake_ident_to_screaming(ident),692			selector_str,693			selector,694			hide: info.hide,695			args,696			has_normal_args,697			has_value_args,698			mutability,699			result: result.clone(),700			weight,701			docs,702		})703	}704	fn expand_call_def(&self) -> proc_macro2::TokenStream {705		let defs = self706			.args707			.iter()708			.filter(|a| !a.is_special())709			.map(|a| a.expand_call_def());710		let pascal_name = &self.pascal_name;711		let docs = &self.docs;712713		if self.has_normal_args {714			quote! {715				#(#[doc = #docs])*716				#[allow(missing_docs)]717				#pascal_name {718					#(719						#defs,720					)*721				}722			}723		} else {724			quote! {#pascal_name}725		}726	}727728	fn expand_const(&self) -> proc_macro2::TokenStream {729		let screaming_name = &self.screaming_name;730		let screaming_name_signature = format_ident!("{}_SIGNATURE", &self.screaming_name);731		let selector_str = &self.selector_str;732		let custom_signature = self.expand_custom_signature();733		quote! {734			const #screaming_name_signature: ::evm_coder::custom_signature::FunctionSignature = #custom_signature;735			#[doc = #selector_str]736			const #screaming_name: ::evm_coder::types::bytes4 = {737				let a = ::evm_coder::sha3_const::Keccak256::new()738				.update_with_size(&Self::#screaming_name_signature.signature, Self::#screaming_name_signature.signature_len)739				.finalize();740				[a[0], a[1], a[2], a[3]]741			};742		}743	}744745	fn expand_interface_id(&self) -> proc_macro2::TokenStream {746		let screaming_name = &self.screaming_name;747		quote! {748			interface_id ^= u32::from_be_bytes(Self::#screaming_name);749		}750	}751752	fn expand_parse(&self) -> proc_macro2::TokenStream {753		let pascal_name = &self.pascal_name;754		let screaming_name = &self.screaming_name;755		if self.has_normal_args {756			let parsers = self757				.args758				.iter()759				.filter(|a| !a.is_special())760				.map(|a| a.expand_parse());761			quote! {762				Self::#screaming_name => return Ok(Some(Self::#pascal_name {763					#(764						#parsers,765					)*766				}))767			}768		} else {769			quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }770		}771	}772773	fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {774		let pascal_name = &self.pascal_name;775		let name = &self.name;776777		let matcher = if self.has_normal_args {778			let names = self779				.args780				.iter()781				.filter(|a| !a.is_special())782				.map(|a| &a.name);783784			quote! {{785				#(786					#names,787				)*788			}}789		} else {790			quote! {}791		};792793		let receiver = match self.mutability {794			Mutability::Mutable | Mutability::View => quote! {self.},795			Mutability::Pure => quote! {Self::},796		};797		let args = self.args.iter().map(|a| a.expand_call_arg());798799		quote! {800			#call_name::#pascal_name #matcher => {801				let result = #receiver #name(802					#(803						#args,804					)*805				)?;806				(&result).to_result()807			}808		}809	}810811	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {812		let pascal_name = &self.pascal_name;813		if let Some(weight) = &self.weight {814			let matcher = if self.has_normal_args {815				let names = self816					.args817					.iter()818					.filter(|a| !a.is_special())819					.map(|a| &a.name);820821				quote! {{822					#(823						#names,824					)*825				}}826			} else {827				quote! {}828			};829			quote! {830				Self::#pascal_name #matcher => (#weight).into()831			}832		} else {833			let matcher = if self.has_normal_args {834				quote! {{..}}835			} else {836				quote! {}837			};838			quote! {839				Self::#pascal_name #matcher => ().into()840			}841		}842	}843844	fn expand_custom_signature(&self) -> proc_macro2::TokenStream {845		let mut custom_signature = TokenStream::new();846847		self.args848			.iter()849			.filter_map(|a| {850				if a.is_special() {851					return None;852				};853854				match a.ty {855					AbiType::Plain(ref ident) => Some(ident),856					_ => None,857				}858			})859			.for_each(|ident| {860				custom_signature.extend(quote! {861					(<#ident>::SIGNATURE, <#ident>::SIGNATURE_LEN)862				});863			});864865		let func_name = self.camel_name.clone();866		let func_name = quote!(FunctionName::new(#func_name));867		custom_signature =868			quote!({ ::evm_coder::make_signature!(new fn(& #func_name),#custom_signature) });869870		// println!("!!!!! {}", custom_signature);871872		custom_signature873	}874875	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {876		let camel_name = &self.camel_name;877		let mutability = match self.mutability {878			Mutability::Mutable => quote! {SolidityMutability::Mutable},879			Mutability::View => quote! { SolidityMutability::View },880			Mutability::Pure => quote! {SolidityMutability::Pure},881		};882		let result = &self.result;883884		let args = self885			.args886			.iter()887			.filter(|a| !a.is_special())888			.map(MethodArg::expand_solidity_argument);889		let docs = &self.docs;890		let selector_str = &self.selector_str;891		let screaming_name = &self.screaming_name;892		let hide = self.hide;893		let custom_signature = self.expand_custom_signature();894		let custom_signature = quote!(895			{896				const cs: FunctionSignature = #custom_signature;897				cs898			}899		);900		// println!("!!!!! {}", custom_signature);901		let is_payable = self.has_value_args;902		let out = quote! {903			SolidityFunction {904				docs: &[#(#docs),*],905				selector_str: #selector_str,906				hide: #hide,907				selector: u32::from_be_bytes(Self::#screaming_name),908				custom_signature: #custom_signature,909				name: #camel_name,910				mutability: #mutability,911				is_payable: #is_payable,912				args: (913					#(914						#args,915					)*916				),917				result: <UnnamedArgument<#result>>::default(),918			}919		};920		// println!("@@@ {}", out);921		out922	}923}924925fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {926	if gen.params.is_empty() {927		return quote! {};928	}929	let params = gen.params.iter().map(|p| match p {930		syn::GenericParam::Type(id) => {931			let v = &id.ident;932			quote! {#v}933		}934		syn::GenericParam::Lifetime(lt) => {935			let v = &lt.lifetime;936			quote! {#v}937		}938		syn::GenericParam::Const(c) => {939			let i = &c.ident;940			quote! {#i}941		}942	});943	quote! { #(#params),* }944}945fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {946	if gen.params.is_empty() {947		return quote! {};948	}949	let list = generics_list(gen);950	quote! { <#list> }951}952fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {953	let list = generics_list(gen);954	if gen.params.len() == 1 {955		quote! {#list}956	} else {957		quote! { (#list) }958	}959}960961pub struct SolidityInterface {962	generics: Generics,963	name: Box<syn::Type>,964	info: InterfaceInfo,965	methods: Vec<Method>,966	docs: Vec<String>,967}968impl SolidityInterface {969	pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {970		let mut methods = Vec::new();971972		for item in &value.items {973			if let ImplItem::Method(method) = item {974				methods.push(Method::try_from(method)?)975			}976		}977		let mut docs = vec![];978		for attr in &value.attrs {979			let ident = parse_ident_from_path(&attr.path, false)?;980			if ident == "doc" {981				let args = attr.parse_meta().unwrap();982				let value = match args {983					Meta::NameValue(MetaNameValue {984						lit: Lit::Str(str), ..985					}) => str.value(),986					_ => unreachable!(),987				};988				docs.push(value);989			}990		}991		Ok(Self {992			generics: value.generics.clone(),993			name: value.self_ty.clone(),994			info,995			methods,996			docs,997		})998	}999	pub fn expand(self) -> proc_macro2::TokenStream {1000		let name = self.name;10011002		let solidity_name = self.info.name.to_string();1003		let call_name = pascal_ident_to_call(&self.info.name);1004		let generics = self.generics;1005		let gen_ref = generics_reference(&generics);1006		let gen_data = generics_data(&generics);1007		let gen_where = &generics.where_clause;10081009		let call_sub = self1010			.info1011			.inline_is1012			.01013			.iter()1014			.chain(self.info.is.0.iter())1015			.map(|c| Is::expand_call_def(c, &gen_ref));1016		let call_parse = self1017			.info1018			.inline_is1019			.01020			.iter()1021			.chain(self.info.is.0.iter())1022			.map(|is| Is::expand_parse(is, &gen_ref));1023		let call_variants = self1024			.info1025			.inline_is1026			.01027			.iter()1028			.chain(self.info.is.0.iter())1029			.map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));1030		let weight_variants = self1031			.info1032			.inline_is1033			.01034			.iter()1035			.chain(self.info.is.0.iter())1036			.map(Is::expand_variant_weight);10371038		let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);1039		let supports_interface = self1040			.info1041			.is1042			.01043			.iter()1044			.map(|is| Is::expand_supports_interface(is, &gen_ref));10451046		let calls = self.methods.iter().map(Method::expand_call_def);1047		let consts = self.methods.iter().map(Method::expand_const);1048		let interface_id = self.methods.iter().map(Method::expand_interface_id);1049		let parsers = self.methods.iter().map(Method::expand_parse);1050		let call_variants_this = self1051			.methods1052			.iter()1053			.map(|m| Method::expand_variant_call(m, &call_name));1054		let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);1055		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);10561057		// TODO: Inline inline_is1058		let solidity_is = self1059			.info1060			.is1061			.01062			.iter()1063			.chain(self.info.inline_is.0.iter())1064			.map(|is| is.name.to_string());1065		let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());1066		let solidity_generators = self1067			.info1068			.is1069			.01070			.iter()1071			.chain(self.info.inline_is.0.iter())1072			.map(|is| Is::expand_generator(is, &gen_ref));1073		let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);10741075		let docs = &self.docs;10761077		if let Some(expect_selector) = &self.info.expect_selector {1078			if !self.info.inline_is.0.is_empty() {1079				return syn::Error::new(1080					name.span(),1081					"expect_selector is not compatible with inline_is",1082				)1083				.to_compile_error();1084			}1085			let selector = self1086				.methods1087				.iter()1088				.map(|m| m.selector)1089				.fold(0, |a, b| a ^ b);10901091			if *expect_selector != selector {1092				let mut methods = String::new();1093				for meth in self.methods.iter() {1094					write!(methods, "\n- {}", meth.selector_str).expect("write to string");1095				}1096				return syn::Error::new(name.span(), format!("expected selector mismatch, expected {expect_selector:0>8x}, but implementation has {selector:0>8x}{methods}")).to_compile_error();1097			}1098		}1099		// let methods = self.methods.iter().map(Method::solidity_def);11001101		quote! {1102			#[derive(Debug)]1103			#(#[doc = #docs])*1104			pub enum #call_name #gen_ref {1105				/// Inherited method1106				ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),1107				#(1108					#calls,1109				)*1110				#(1111					#call_sub,1112				)*1113			}1114			impl #gen_ref #call_name #gen_ref {1115				#(1116					#consts1117				)*1118				/// Return this call ERC165 selector1119				pub fn interface_id() -> ::evm_coder::types::bytes4 {1120					let mut interface_id = 0;1121					#(#interface_id)*1122					#(#inline_interface_id)*1123					u32::to_be_bytes(interface_id)1124				}1125				/// Generate solidity definitions for methods described in this interface1126				pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {1127					use evm_coder::solidity::*;1128					use core::fmt::Write;1129					let interface = SolidityInterface {1130						docs: &[#(#docs),*],1131						name: #solidity_name,1132						selector: Self::interface_id(),1133						is: &["Dummy", "ERC165", #(1134							#solidity_is,1135						)* #(1136							#solidity_events_is,1137						)* ],1138						functions: (#(1139							#solidity_functions,1140						)*),1141					};11421143					let mut out = ::evm_coder::types::string::new();1144					if #solidity_name.starts_with("Inline") {1145						out.push_str("/// @dev inlined interface\n");1146					}1147					let _ = interface.format(is_impl, &mut out, tc);1148					tc.collect(out);1149					#(1150						#solidity_event_generators1151					)*1152					#(1153						#solidity_generators1154					)*1155					if is_impl {1156						tc.collect("/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into());1157					} else {1158						tc.collect("/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());1159					}1160				}1161			}1162			impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {1163				fn parse(method_id: ::evm_coder::types::bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {1164					use ::evm_coder::abi::AbiRead;1165					match method_id {1166						::evm_coder::ERC165Call::INTERFACE_ID => return Ok(1167							::evm_coder::ERC165Call::parse(method_id, reader)?1168							.map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))1169						),1170						#(1171							#parsers,1172						)*1173						_ => {},1174					}1175					#(1176						#call_parse1177					)else*1178					return Ok(None);1179				}1180			}1181			impl #generics #call_name #gen_ref1182			#gen_where1183			{1184				/// Is this contract implements specified ERC165 selector1185				pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::bytes4) -> bool {1186					interface_id != u32::to_be_bytes(0xffffff) && (1187						interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||1188						interface_id == Self::interface_id()1189						#(1190							|| #supports_interface1191						)*1192					)1193				}1194			}1195			impl #generics ::evm_coder::Weighted for #call_name #gen_ref1196			#gen_where1197			{1198				#[allow(unused_variables)]1199				fn weight(&self) -> ::evm_coder::execution::DispatchInfo {1200					match self {1201						#(1202							#weight_variants,1203						)*1204						// TODO: It should be very cheap, but not free1205						Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => ::frame_support::weights::Weight::from_ref_time(100).into(),1206						#(1207							#weight_variants_this,1208						)*1209					}1210				}1211			}1212			impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name1213			#gen_where1214			{1215				#[allow(unreachable_code)] // In case of no inner calls1216				fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {1217					use ::evm_coder::abi::AbiWrite;1218					match c.call {1219						#(1220							#call_variants,1221						)*1222						#call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {1223							let mut writer = ::evm_coder::abi::AbiWriter::default();1224							writer.bool(&<#call_name #gen_ref>::supports_interface(self, interface_id));1225							return Ok(writer.into());1226						}1227						_ => {},1228					}1229					let mut writer = ::evm_coder::abi::AbiWriter::default();1230					match c.call {1231						#(1232							#call_variants_this,1233						)*1234						_ => Err(::evm_coder::execution::Error::from("method is not available").into()),1235					}1236				}1237			}1238		}1239	}1240}
after · crates/evm-coder/procedural/src/solidity_interface.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![allow(dead_code)]1819// NOTE: In order to understand this Rust macro better, first read this chapter20// about Procedural Macros in Rust book:21// https://doc.rust-lang.org/reference/procedural-macros.html2223use proc_macro2::TokenStream;24use quote::{quote, ToTokens, format_ident};25use inflector::cases;26use std::fmt::Write;27use syn::{28	Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,29	MetaNameValue, PatType, PathArguments, ReturnType, Type,30	spanned::Spanned,31	parse::{Parse, ParseStream},32	parenthesized, Token, LitInt, LitStr,33};3435use crate::{36	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,37	parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,38	snake_ident_to_screaming,39};4041struct Is {42	name: Ident,43	pascal_call_name: Ident,44	snake_call_name: Ident,45	via: Option<(Type, Ident)>,46	condition: Option<Expr>,47}48impl Is {49	fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {50		let name = &self.name;51		let pascal_call_name = &self.pascal_call_name;52		quote! {53			#name(#pascal_call_name #gen_ref)54		}55	}5657	fn expand_interface_id(&self) -> proc_macro2::TokenStream {58		let pascal_call_name = &self.pascal_call_name;59		quote! {60			interface_id ^= u32::from_be_bytes(#pascal_call_name::interface_id());61		}62	}6364	fn expand_supports_interface(65		&self,66		generics: &proc_macro2::TokenStream,67	) -> proc_macro2::TokenStream {68		let pascal_call_name = &self.pascal_call_name;69		let condition = self.condition.as_ref().map(|condition| {70			quote! {71				(#condition) &&72			}73		});74		quote! {75			#condition <#pascal_call_name #generics>::supports_interface(this, interface_id)76		}77	}7879	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {80		let name = &self.name;81		quote! {82			Self::#name(call) => call.weight()83		}84	}8586	fn expand_variant_call(87		&self,88		call_name: &proc_macro2::Ident,89		generics: &proc_macro2::TokenStream,90	) -> proc_macro2::TokenStream {91		let name = &self.name;92		let pascal_call_name = &self.pascal_call_name;93		let via_typ = self94			.via95			.as_ref()96			.map(|(t, _)| quote! {#t})97			.unwrap_or_else(|| quote! {Self});98		let via_map = self99			.via100			.as_ref()101			.map(|(_, i)| quote! {.#i()})102			.unwrap_or_default();103		let condition = self.condition.as_ref().map(|condition| {104			quote! {105				if ({let this = &self; (#condition)})106			}107		});108		quote! {109			#call_name::#name(call) #condition => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {110				call,111				caller: c.caller,112				value: c.value,113			})114		}115	}116117	fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {118		let name = &self.name;119		let pascal_call_name = &self.pascal_call_name;120		quote! {121			if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {122				return Ok(Some(Self::#name(parsed_call)))123			}124		}125	}126127	fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {128		let pascal_call_name = &self.pascal_call_name;129		quote! {130			<#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);131		}132	}133134	fn expand_event_generator(&self) -> proc_macro2::TokenStream {135		let name = &self.name;136		quote! {137			#name::generate_solidity_interface(tc, is_impl);138		}139	}140}141142#[derive(Default)]143struct IsList(Vec<Is>);144impl Parse for IsList {145	fn parse(input: ParseStream) -> syn::Result<Self> {146		let mut out = vec![];147		loop {148			if input.is_empty() {149				break;150			}151			let name = input.parse::<Ident>()?;152			let lookahead = input.lookahead1();153154			let mut condition: Option<Expr> = None;155			let mut via: Option<(Type, Ident)> = None;156157			if lookahead.peek(syn::token::Paren) {158				let contents;159				parenthesized!(contents in input);160				let input = contents;161162				while !input.is_empty() {163					let lookahead = input.lookahead1();164					if lookahead.peek(Token![if]) {165						input.parse::<Token![if]>()?;166						let contents;167						parenthesized!(contents in input);168						let contents = contents.parse::<Expr>()?;169170						if condition.replace(contents).is_some() {171							return Err(syn::Error::new(input.span(), "condition is already set"));172						}173					} else if lookahead.peek(kw::via) {174						input.parse::<kw::via>()?;175						let contents;176						parenthesized!(contents in input);177178						let method = contents.parse::<Ident>()?;179						contents.parse::<kw::returns>()?;180						let ty = contents.parse::<Type>()?;181182						if via.replace((ty, method)).is_some() {183							return Err(syn::Error::new(input.span(), "via is already set"));184						}185					} else {186						return Err(lookahead.error());187					}188189					if input.peek(Token![,]) {190						input.parse::<Token![,]>()?;191					} else if !input.is_empty() {192						return Err(syn::Error::new(input.span(), "expected end"));193					}194				}195			} else if lookahead.peek(Token![,]) || input.is_empty() {196				// Pass197			} else {198				return Err(lookahead.error());199			};200			out.push(Is {201				pascal_call_name: pascal_ident_to_call(&name),202				snake_call_name: pascal_ident_to_snake_call(&name),203				name,204				via,205				condition,206			});207			if input.peek(Token![,]) {208				input.parse::<Token![,]>()?;209				continue;210			} else {211				break;212			}213		}214		Ok(Self(out))215	}216}217218pub struct InterfaceInfo {219	name: Ident,220	is: IsList,221	inline_is: IsList,222	events: IsList,223	expect_selector: Option<u32>,224}225impl Parse for InterfaceInfo {226	fn parse(input: ParseStream) -> syn::Result<Self> {227		let mut name = None;228		let mut is = None;229		let mut inline_is = None;230		let mut events = None;231		let mut expect_selector = None;232		// TODO: create proc-macro to optimize proc-macro boilerplate? :D233		loop {234			let lookahead = input.lookahead1();235			if lookahead.peek(kw::name) {236				let k = input.parse::<kw::name>()?;237				input.parse::<Token![=]>()?;238				if name.replace(input.parse::<Ident>()?).is_some() {239					return Err(syn::Error::new(k.span(), "name is already set"));240				}241			} else if lookahead.peek(kw::is) {242				let k = input.parse::<kw::is>()?;243				let contents;244				parenthesized!(contents in input);245				if is.replace(contents.parse::<IsList>()?).is_some() {246					return Err(syn::Error::new(k.span(), "is is already set"));247				}248			} else if lookahead.peek(kw::inline_is) {249				let k = input.parse::<kw::inline_is>()?;250				let contents;251				parenthesized!(contents in input);252				if inline_is.replace(contents.parse::<IsList>()?).is_some() {253					return Err(syn::Error::new(k.span(), "inline_is is already set"));254				}255			} else if lookahead.peek(kw::events) {256				let k = input.parse::<kw::events>()?;257				let contents;258				parenthesized!(contents in input);259				if events.replace(contents.parse::<IsList>()?).is_some() {260					return Err(syn::Error::new(k.span(), "events is already set"));261				}262			} else if lookahead.peek(kw::expect_selector) {263				let k = input.parse::<kw::expect_selector>()?;264				input.parse::<Token![=]>()?;265				let value = input.parse::<LitInt>()?;266				if expect_selector267					.replace(value.base10_parse::<u32>()?)268					.is_some()269				{270					return Err(syn::Error::new(k.span(), "expect_selector is already set"));271				}272			} else if input.is_empty() {273				break;274			} else {275				return Err(lookahead.error());276			}277			if input.peek(Token![,]) {278				input.parse::<Token![,]>()?;279			} else {280				break;281			}282		}283		Ok(Self {284			name: name.ok_or_else(|| syn::Error::new(input.span(), "missing name"))?,285			is: is.unwrap_or_default(),286			inline_is: inline_is.unwrap_or_default(),287			events: events.unwrap_or_default(),288			expect_selector,289		})290	}291}292293struct MethodInfo {294	rename_selector: Option<String>,295	hide: bool,296}297impl Parse for MethodInfo {298	fn parse(input: ParseStream) -> syn::Result<Self> {299		let mut rename_selector = None;300		let mut hide = false;301		while !input.is_empty() {302			let lookahead = input.lookahead1();303			if lookahead.peek(kw::rename_selector) {304				let k = input.parse::<kw::rename_selector>()?;305				input.parse::<Token![=]>()?;306				if rename_selector307					.replace(input.parse::<LitStr>()?.value())308					.is_some()309				{310					return Err(syn::Error::new(k.span(), "rename_selector is already set"));311				}312			} else if lookahead.peek(kw::hide) {313				input.parse::<kw::hide>()?;314				hide = true;315			} else {316				return Err(lookahead.error());317			}318319			if input.peek(Token![,]) {320				input.parse::<Token![,]>()?;321			} else if !input.is_empty() {322				return Err(syn::Error::new(input.span(), "expected end"));323			}324		}325		Ok(Self {326			rename_selector,327			hide,328		})329	}330}331332#[derive(Debug)]333enum AbiType {334	// type335	Plain(Ident),336	// (type1,type2)337	Tuple(Vec<AbiType>),338	// type[]339	Vec(Box<AbiType>),340	// type[20]341	Array(Box<AbiType>, usize),342}343impl AbiType {344	fn try_from(value: &Type) -> syn::Result<Self> {345		let value = Self::try_maybe_special_from(value)?;346		if value.is_special() {347			return Err(syn::Error::new(value.span(), "unexpected special type"));348		}349		Ok(value)350	}351	fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {352		match value {353			Type::Array(arr) => {354				let wrapped = AbiType::try_from(&arr.elem)?;355				match &arr.len {356					Expr::Lit(l) => match &l.lit {357						Lit::Int(i) => {358							let num = i.base10_parse::<usize>()?;359							Ok(AbiType::Array(Box::new(wrapped), num as usize))360						}361						_ => Err(syn::Error::new(arr.len.span(), "should be int literal")),362					},363					_ => Err(syn::Error::new(arr.len.span(), "should be literal")),364				}365			}366			Type::Path(_) => {367				let path = parse_path(value)?;368				let segment = parse_path_segment(path)?;369				if segment.ident == "Vec" {370					let args = match &segment.arguments {371						PathArguments::AngleBracketed(e) => e,372						_ => {373							return Err(syn::Error::new(374								segment.arguments.span(),375								"missing Vec generic",376							))377						}378					};379					let args = &args.args;380					if args.len() != 1 {381						return Err(syn::Error::new(382							args.span(),383							"expected only one generic for vec",384						));385					}386					let arg = args.first().expect("first arg");387388					let ty = match arg {389						GenericArgument::Type(ty) => ty,390						_ => {391							return Err(syn::Error::new(392								arg.span(),393								"expected first generic to be type",394							))395						}396					};397398					let wrapped = AbiType::try_from(ty)?;399					Ok(Self::Vec(Box::new(wrapped)))400				} else {401					if !segment.arguments.is_empty() {402						return Err(syn::Error::new(403							segment.arguments.span(),404							"unexpected generic arguments for non-vec type",405						));406					}407					Ok(Self::Plain(segment.ident.clone()))408				}409			}410			Type::Tuple(t) => {411				let mut out = Vec::with_capacity(t.elems.len());412				for el in t.elems.iter() {413					out.push(AbiType::try_from(el)?)414				}415				Ok(Self::Tuple(out))416			}417			_ => Err(syn::Error::new(418				value.span(),419				"unexpected type, only arrays, plain types and tuples are supported",420			)),421		}422	}423	fn is_value(&self) -> bool {424		matches!(self, Self::Plain(v) if v == "value")425	}426	fn is_caller(&self) -> bool {427		matches!(self, Self::Plain(v) if v == "caller")428	}429	fn is_special(&self) -> bool {430		self.is_caller() || self.is_value()431	}432	fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {433		match self {434			AbiType::Plain(t) => {435				write!(buf, "{}", t)436			}437			AbiType::Tuple(t) => {438				write!(buf, "(")?;439				for (i, t) in t.iter().enumerate() {440					if i != 0 {441						write!(buf, ",")?;442					}443					t.selector_ty_buf(buf)?;444				}445				write!(buf, ")")446			}447			AbiType::Vec(v) => {448				v.selector_ty_buf(buf)?;449				write!(buf, "[]")450			}451			AbiType::Array(v, len) => {452				v.selector_ty_buf(buf)?;453				write!(buf, "[{}]", len)454			}455		}456	}457	fn selector_ty(&self) -> String {458		let mut out = String::new();459		self.selector_ty_buf(&mut out).expect("no fmt error");460		out461	}462}463impl ToTokens for AbiType {464	fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {465		match self {466			AbiType::Plain(t) => tokens.extend(quote! {#t}),467			AbiType::Tuple(t) => {468				tokens.extend(quote! {(469					#(#t),*470				)});471			}472			AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),473			AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),474		}475	}476}477478#[derive(Debug)]479struct MethodArg {480	name: Ident,481	camel_name: String,482	ty: AbiType,483}484impl MethodArg {485	fn try_from(value: &PatType) -> syn::Result<Self> {486		let name = parse_ident_from_pat(&value.pat)?.clone();487		Ok(Self {488			camel_name: cases::camelcase::to_camel_case(&name.to_string()),489			name,490			ty: AbiType::try_maybe_special_from(&value.ty)?,491		})492	}493	fn is_value(&self) -> bool {494		self.ty.is_value()495	}496	fn is_caller(&self) -> bool {497		self.ty.is_caller()498	}499	fn is_special(&self) -> bool {500		self.ty.is_special()501	}502	fn selector_ty(&self) -> String {503		assert!(!self.is_special());504		self.ty.selector_ty()505	}506507	fn expand_call_def(&self) -> proc_macro2::TokenStream {508		assert!(!self.is_special());509		let name = &self.name;510		let ty = &self.ty;511512		quote! {513			#name: #ty514		}515	}516517	fn expand_parse(&self) -> proc_macro2::TokenStream {518		assert!(!self.is_special());519		let name = &self.name;520		quote! {521			#name: reader.abi_read()?522		}523	}524525	fn expand_call_arg(&self) -> proc_macro2::TokenStream {526		if self.is_value() {527			quote! {528				c.value.clone()529			}530		} else if self.is_caller() {531			quote! {532				c.caller.clone()533			}534		} else {535			let name = &self.name;536			quote! {537				#name538			}539		}540	}541542	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {543		let camel_name = &self.camel_name.to_string();544		let ty = &self.ty;545		quote! {546			<NamedArgument<#ty>>::new(#camel_name)547		}548	}549}550551#[derive(PartialEq)]552enum Mutability {553	Mutable,554	View,555	Pure,556}557558/// Group all keywords for this macro. Usage example:559/// #[solidity_interface(name = "B", inline_is(A))]560mod kw {561	syn::custom_keyword!(weight);562563	syn::custom_keyword!(via);564	syn::custom_keyword!(returns);565	syn::custom_keyword!(name);566	syn::custom_keyword!(is);567	syn::custom_keyword!(inline_is);568	syn::custom_keyword!(events);569	syn::custom_keyword!(expect_selector);570571	syn::custom_keyword!(rename_selector);572	syn::custom_keyword!(hide);573}574575/// Rust methods are parsed into this structure when Solidity code is generated576struct Method {577	name: Ident,578	camel_name: String,579	pascal_name: Ident,580	screaming_name: Ident,581	selector_str: String,582	selector: u32,583	hide: bool,584	args: Vec<MethodArg>,585	has_normal_args: bool,586	has_value_args: bool,587	mutability: Mutability,588	result: Type,589	weight: Option<Expr>,590	docs: Vec<String>,591}592impl Method {593	fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {594		let mut info = MethodInfo {595			rename_selector: None,596			hide: false,597		};598		let mut docs = Vec::new();599		let mut weight = None;600		for attr in &value.attrs {601			let ident = parse_ident_from_path(&attr.path, false)?;602			if ident == "solidity" {603				info = attr.parse_args::<MethodInfo>()?;604			} else if ident == "doc" {605				let args = attr.parse_meta().unwrap();606				let value = match args {607					Meta::NameValue(MetaNameValue {608						lit: Lit::Str(str), ..609					}) => str.value(),610					_ => unreachable!(),611				};612				docs.push(value);613			} else if ident == "weight" {614				weight = Some(attr.parse_args::<Expr>()?);615			}616		}617		let ident = &value.sig.ident;618		let ident_str = ident.to_string();619		if !cases::snakecase::is_snake_case(&ident_str) {620			return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));621		}622623		let mut mutability = Mutability::Pure;624625		if let Some(FnArg::Receiver(receiver)) = value626			.sig627			.inputs628			.iter()629			.find(|arg| matches!(arg, FnArg::Receiver(_)))630		{631			if receiver.reference.is_none() {632				return Err(syn::Error::new(633					receiver.span(),634					"receiver should be by ref",635				));636			}637			if receiver.mutability.is_some() {638				mutability = Mutability::Mutable;639			} else {640				mutability = Mutability::View;641			}642		}643		let mut args = Vec::new();644		for typ in value645			.sig646			.inputs647			.iter()648			.filter(|arg| matches!(arg, FnArg::Typed(_)))649		{650			let typ = match typ {651				FnArg::Typed(typ) => typ,652				_ => unreachable!(),653			};654			args.push(MethodArg::try_from(typ)?);655		}656657		if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {658			return Err(syn::Error::new(659				args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),660				"payable function should be mutable",661			));662		}663664		let result = match &value.sig.output {665			ReturnType::Type(_, ty) => ty,666			_ => return Err(syn::Error::new(value.sig.output.span(), "interface method should return Result<value>\nif there is no value to return - specify void (which is alias to unit)")),667		};668		let result = parse_result_ok(result)?;669670		let camel_name = info671			.rename_selector672			.unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));673		let mut selector_str = camel_name.clone();674		selector_str.push('(');675		let mut has_normal_args = false;676		for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {677			if i != 0 {678				selector_str.push(',');679			}680			write!(selector_str, "{}", arg.selector_ty()).unwrap();681			has_normal_args = true;682		}683		let has_value_args = args.iter().any(|a| a.is_value());684		selector_str.push(')');685		let selector = fn_selector_str(&selector_str);686687		Ok(Self {688			name: ident.clone(),689			camel_name,690			pascal_name: snake_ident_to_pascal(ident),691			screaming_name: snake_ident_to_screaming(ident),692			selector_str,693			selector,694			hide: info.hide,695			args,696			has_normal_args,697			has_value_args,698			mutability,699			result: result.clone(),700			weight,701			docs,702		})703	}704	fn expand_call_def(&self) -> proc_macro2::TokenStream {705		let defs = self706			.args707			.iter()708			.filter(|a| !a.is_special())709			.map(|a| a.expand_call_def());710		let pascal_name = &self.pascal_name;711		let docs = &self.docs;712713		if self.has_normal_args {714			quote! {715				#(#[doc = #docs])*716				#[allow(missing_docs)]717				#pascal_name {718					#(719						#defs,720					)*721				}722			}723		} else {724			quote! {#pascal_name}725		}726	}727728	fn expand_const(&self) -> proc_macro2::TokenStream {729		let screaming_name = &self.screaming_name;730		let screaming_name_signature = format_ident!("{}_SIGNATURE", &self.screaming_name);731		let selector_str = &self.selector_str;732		let custom_signature = self.expand_custom_signature();733		quote! {734			const #screaming_name_signature: ::evm_coder::custom_signature::FunctionSignature = #custom_signature;735			#[doc = #selector_str]736			const #screaming_name: ::evm_coder::types::bytes4 = {737				let a = ::evm_coder::sha3_const::Keccak256::new()738				.update_with_size(&Self::#screaming_name_signature.data, Self::#screaming_name_signature.len)739				.finalize();740				[a[0], a[1], a[2], a[3]]741			};742		}743	}744745	fn expand_interface_id(&self) -> proc_macro2::TokenStream {746		let screaming_name = &self.screaming_name;747		quote! {748			interface_id ^= u32::from_be_bytes(Self::#screaming_name);749		}750	}751752	fn expand_parse(&self) -> proc_macro2::TokenStream {753		let pascal_name = &self.pascal_name;754		let screaming_name = &self.screaming_name;755		if self.has_normal_args {756			let parsers = self757				.args758				.iter()759				.filter(|a| !a.is_special())760				.map(|a| a.expand_parse());761			quote! {762				Self::#screaming_name => return Ok(Some(Self::#pascal_name {763					#(764						#parsers,765					)*766				}))767			}768		} else {769			quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }770		}771	}772773	fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {774		let pascal_name = &self.pascal_name;775		let name = &self.name;776777		let matcher = if self.has_normal_args {778			let names = self779				.args780				.iter()781				.filter(|a| !a.is_special())782				.map(|a| &a.name);783784			quote! {{785				#(786					#names,787				)*788			}}789		} else {790			quote! {}791		};792793		let receiver = match self.mutability {794			Mutability::Mutable | Mutability::View => quote! {self.},795			Mutability::Pure => quote! {Self::},796		};797		let args = self.args.iter().map(|a| a.expand_call_arg());798799		quote! {800			#call_name::#pascal_name #matcher => {801				let result = #receiver #name(802					#(803						#args,804					)*805				)?;806				(&result).to_result()807			}808		}809	}810811	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {812		let pascal_name = &self.pascal_name;813		if let Some(weight) = &self.weight {814			let matcher = if self.has_normal_args {815				let names = self816					.args817					.iter()818					.filter(|a| !a.is_special())819					.map(|a| &a.name);820821				quote! {{822					#(823						#names,824					)*825				}}826			} else {827				quote! {}828			};829			quote! {830				Self::#pascal_name #matcher => (#weight).into()831			}832		} else {833			let matcher = if self.has_normal_args {834				quote! {{..}}835			} else {836				quote! {}837			};838			quote! {839				Self::#pascal_name #matcher => ().into()840			}841		}842	}843844	fn expand_type(ty: &AbiType, token_stream: &mut proc_macro2::TokenStream) {845		match ty {846			AbiType::Plain(ref ident) => {847				token_stream.extend(quote! {848					(<#ident>::SIGNATURE),849				});850			}851852			AbiType::Tuple(ref tuple_type) => {853				let mut tuple_types = proc_macro2::TokenStream::new();854				for ty in tuple_type {855					Self::expand_type(ty, &mut tuple_types);856				}857				let group =858					proc_macro2::Group::new(proc_macro2::Delimiter::Parenthesis, tuple_types);859				token_stream.extend(group.stream());860			}861862			AbiType::Vec(ref _vec_type) => {}863864			AbiType::Array(_, _) => todo!("Array eth signature"),865		};866	}867868	fn expand_custom_signature(&self) -> proc_macro2::TokenStream {869		let mut token_stream = TokenStream::new();870871		for arg in &self.args {872			if arg.is_special() {873				continue;874			}875876			Self::expand_type(&arg.ty, &mut token_stream);877		}878879		let func_name = self.camel_name.clone();880		let func_name = quote!(SignaturePreferences {881			open_name: Some(SignatureUnit::new(#func_name)),882			open_delimiter: Some(SignatureUnit::new("(")),883			param_delimiter: Some(SignatureUnit::new(",")),884			close_delimiter: Some(SignatureUnit::new(")")),885			close_name: None,886		});887		token_stream = quote!({ ::evm_coder::make_signature!(new fn(#func_name),#token_stream) });888889		// println!("!!!!! {}", custom_signature);890891		token_stream892	}893894	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {895		let camel_name = &self.camel_name;896		let mutability = match self.mutability {897			Mutability::Mutable => quote! {SolidityMutability::Mutable},898			Mutability::View => quote! { SolidityMutability::View },899			Mutability::Pure => quote! {SolidityMutability::Pure},900		};901		let result = &self.result;902903		let args = self904			.args905			.iter()906			.filter(|a| !a.is_special())907			.map(MethodArg::expand_solidity_argument);908		let docs = &self.docs;909		let selector_str = &self.selector_str;910		let screaming_name = &self.screaming_name;911		let hide = self.hide;912		let custom_signature = self.expand_custom_signature();913		let custom_signature = quote!(914			{915				const cs: FunctionSignature = #custom_signature;916				cs917			}918		);919		// println!("!!!!! {}", custom_signature);920		let is_payable = self.has_value_args;921		let out = quote! {922			SolidityFunction {923				docs: &[#(#docs),*],924				selector_str: #selector_str,925				hide: #hide,926				selector: u32::from_be_bytes(Self::#screaming_name),927				custom_signature: #custom_signature,928				name: #camel_name,929				mutability: #mutability,930				is_payable: #is_payable,931				args: (932					#(933						#args,934					)*935				),936				result: <UnnamedArgument<#result>>::default(),937			}938		};939		// println!("@@@ {}", out);940		out941	}942}943944fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {945	if gen.params.is_empty() {946		return quote! {};947	}948	let params = gen.params.iter().map(|p| match p {949		syn::GenericParam::Type(id) => {950			let v = &id.ident;951			quote! {#v}952		}953		syn::GenericParam::Lifetime(lt) => {954			let v = &lt.lifetime;955			quote! {#v}956		}957		syn::GenericParam::Const(c) => {958			let i = &c.ident;959			quote! {#i}960		}961	});962	quote! { #(#params),* }963}964fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {965	if gen.params.is_empty() {966		return quote! {};967	}968	let list = generics_list(gen);969	quote! { <#list> }970}971fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {972	let list = generics_list(gen);973	if gen.params.len() == 1 {974		quote! {#list}975	} else {976		quote! { (#list) }977	}978}979980pub struct SolidityInterface {981	generics: Generics,982	name: Box<syn::Type>,983	info: InterfaceInfo,984	methods: Vec<Method>,985	docs: Vec<String>,986}987impl SolidityInterface {988	pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {989		let mut methods = Vec::new();990991		for item in &value.items {992			if let ImplItem::Method(method) = item {993				methods.push(Method::try_from(method)?)994			}995		}996		let mut docs = vec![];997		for attr in &value.attrs {998			let ident = parse_ident_from_path(&attr.path, false)?;999			if ident == "doc" {1000				let args = attr.parse_meta().unwrap();1001				let value = match args {1002					Meta::NameValue(MetaNameValue {1003						lit: Lit::Str(str), ..1004					}) => str.value(),1005					_ => unreachable!(),1006				};1007				docs.push(value);1008			}1009		}1010		Ok(Self {1011			generics: value.generics.clone(),1012			name: value.self_ty.clone(),1013			info,1014			methods,1015			docs,1016		})1017	}1018	pub fn expand(self) -> proc_macro2::TokenStream {1019		let name = self.name;10201021		let solidity_name = self.info.name.to_string();1022		let call_name = pascal_ident_to_call(&self.info.name);1023		let generics = self.generics;1024		let gen_ref = generics_reference(&generics);1025		let gen_data = generics_data(&generics);1026		let gen_where = &generics.where_clause;10271028		let call_sub = self1029			.info1030			.inline_is1031			.01032			.iter()1033			.chain(self.info.is.0.iter())1034			.map(|c| Is::expand_call_def(c, &gen_ref));1035		let call_parse = self1036			.info1037			.inline_is1038			.01039			.iter()1040			.chain(self.info.is.0.iter())1041			.map(|is| Is::expand_parse(is, &gen_ref));1042		let call_variants = self1043			.info1044			.inline_is1045			.01046			.iter()1047			.chain(self.info.is.0.iter())1048			.map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));1049		let weight_variants = self1050			.info1051			.inline_is1052			.01053			.iter()1054			.chain(self.info.is.0.iter())1055			.map(Is::expand_variant_weight);10561057		let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);1058		let supports_interface = self1059			.info1060			.is1061			.01062			.iter()1063			.map(|is| Is::expand_supports_interface(is, &gen_ref));10641065		let calls = self.methods.iter().map(Method::expand_call_def);1066		let consts = self.methods.iter().map(Method::expand_const);1067		let interface_id = self.methods.iter().map(Method::expand_interface_id);1068		let parsers = self.methods.iter().map(Method::expand_parse);1069		let call_variants_this = self1070			.methods1071			.iter()1072			.map(|m| Method::expand_variant_call(m, &call_name));1073		let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);1074		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);10751076		// TODO: Inline inline_is1077		let solidity_is = self1078			.info1079			.is1080			.01081			.iter()1082			.chain(self.info.inline_is.0.iter())1083			.map(|is| is.name.to_string());1084		let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());1085		let solidity_generators = self1086			.info1087			.is1088			.01089			.iter()1090			.chain(self.info.inline_is.0.iter())1091			.map(|is| Is::expand_generator(is, &gen_ref));1092		let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);10931094		let docs = &self.docs;10951096		if let Some(expect_selector) = &self.info.expect_selector {1097			if !self.info.inline_is.0.is_empty() {1098				return syn::Error::new(1099					name.span(),1100					"expect_selector is not compatible with inline_is",1101				)1102				.to_compile_error();1103			}1104			let selector = self1105				.methods1106				.iter()1107				.map(|m| m.selector)1108				.fold(0, |a, b| a ^ b);11091110			if *expect_selector != selector {1111				let mut methods = String::new();1112				for meth in self.methods.iter() {1113					write!(methods, "\n- {}", meth.selector_str).expect("write to string");1114				}1115				return syn::Error::new(name.span(), format!("expected selector mismatch, expected {expect_selector:0>8x}, but implementation has {selector:0>8x}{methods}")).to_compile_error();1116			}1117		}1118		// let methods = self.methods.iter().map(Method::solidity_def);11191120		quote! {1121			#[derive(Debug)]1122			#(#[doc = #docs])*1123			pub enum #call_name #gen_ref {1124				/// Inherited method1125				ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),1126				#(1127					#calls,1128				)*1129				#(1130					#call_sub,1131				)*1132			}1133			impl #gen_ref #call_name #gen_ref {1134				#(1135					#consts1136				)*1137				/// Return this call ERC165 selector1138				pub fn interface_id() -> ::evm_coder::types::bytes4 {1139					let mut interface_id = 0;1140					#(#interface_id)*1141					#(#inline_interface_id)*1142					u32::to_be_bytes(interface_id)1143				}1144				/// Generate solidity definitions for methods described in this interface1145				pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {1146					use evm_coder::solidity::*;1147					use core::fmt::Write;1148					let interface = SolidityInterface {1149						docs: &[#(#docs),*],1150						name: #solidity_name,1151						selector: Self::interface_id(),1152						is: &["Dummy", "ERC165", #(1153							#solidity_is,1154						)* #(1155							#solidity_events_is,1156						)* ],1157						functions: (#(1158							#solidity_functions,1159						)*),1160					};11611162					let mut out = ::evm_coder::types::string::new();1163					if #solidity_name.starts_with("Inline") {1164						out.push_str("/// @dev inlined interface\n");1165					}1166					let _ = interface.format(is_impl, &mut out, tc);1167					tc.collect(out);1168					#(1169						#solidity_event_generators1170					)*1171					#(1172						#solidity_generators1173					)*1174					if is_impl {1175						tc.collect("/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into());1176					} else {1177						tc.collect("/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());1178					}1179				}1180			}1181			impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {1182				fn parse(method_id: ::evm_coder::types::bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {1183					use ::evm_coder::abi::AbiRead;1184					match method_id {1185						::evm_coder::ERC165Call::INTERFACE_ID => return Ok(1186							::evm_coder::ERC165Call::parse(method_id, reader)?1187							.map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))1188						),1189						#(1190							#parsers,1191						)*1192						_ => {},1193					}1194					#(1195						#call_parse1196					)else*1197					return Ok(None);1198				}1199			}1200			impl #generics #call_name #gen_ref1201			#gen_where1202			{1203				/// Is this contract implements specified ERC165 selector1204				pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::bytes4) -> bool {1205					interface_id != u32::to_be_bytes(0xffffff) && (1206						interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||1207						interface_id == Self::interface_id()1208						#(1209							|| #supports_interface1210						)*1211					)1212				}1213			}1214			impl #generics ::evm_coder::Weighted for #call_name #gen_ref1215			#gen_where1216			{1217				#[allow(unused_variables)]1218				fn weight(&self) -> ::evm_coder::execution::DispatchInfo {1219					match self {1220						#(1221							#weight_variants,1222						)*1223						// TODO: It should be very cheap, but not free1224						Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => ::frame_support::weights::Weight::from_ref_time(100).into(),1225						#(1226							#weight_variants_this,1227						)*1228					}1229				}1230			}1231			impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name1232			#gen_where1233			{1234				#[allow(unreachable_code)] // In case of no inner calls1235				fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {1236					use ::evm_coder::abi::AbiWrite;1237					match c.call {1238						#(1239							#call_variants,1240						)*1241						#call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {1242							let mut writer = ::evm_coder::abi::AbiWriter::default();1243							writer.bool(&<#call_name #gen_ref>::supports_interface(self, interface_id));1244							return Ok(writer.into());1245						}1246						_ => {},1247					}1248					let mut writer = ::evm_coder::abi::AbiWriter::default();1249					match c.call {1250						#(1251							#call_variants_this,1252						)*1253						_ => Err(::evm_coder::execution::Error::from("method is not available").into()),1254					}1255				}1256			}1257		}1258	}1259}
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -26,6 +26,8 @@
 use crate::{
 	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},
 	types::*,
+	make_signature,
+	custom_signature::{SignatureUnit, SIGNATURE_SIZE_LIMIT},
 };
 use crate::execution::Result;
 
@@ -378,7 +380,6 @@
 impl_abi_readable!(bytes4, bytes4, false);
 impl_abi_readable!(address, address, false);
 impl_abi_readable!(string, string, true);
-// impl_abi_readable!(bytes, bytes, true);
 
 impl TypeHelper for bytes {
 	fn is_dynamic() -> bool {
@@ -420,6 +421,10 @@
 	}
 }
 
+impl<R: Signature> Signature for Vec<R> {
+	make_signature!(new nameof(R) fixed("[]"));
+}
+
 impl TypeHelper for EthCrossAccount {
 	fn is_dynamic() -> bool {
 		address::is_dynamic() || uint256::is_dynamic()
@@ -471,7 +476,9 @@
 				0 $(+ <$ident>::size())+
 			}
 		}
+
 		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
+
 		impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>
 		where
 			$(
@@ -487,6 +494,7 @@
 				))
 			}
 		}
+
 		#[allow(non_snake_case)]
 		impl<$($ident),+> AbiWrite for ($($ident,)+)
 		where
@@ -503,6 +511,18 @@
 				}
 			}
 		}
+
+		impl<$($ident),+> Signature for ($($ident,)+)
+		where
+		$($ident: Signature,)+
+		{
+			make_signature!(
+				new fixed("(")
+				$(nameof($ident) fixed(","))+
+				shift_left(1)
+				fixed(")")
+			);
+		}
 	};
 }
 
modifiedcrates/evm-coder/src/custom_signature.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/custom_signature.rs
+++ b/crates/evm-coder/src/custom_signature.rs
@@ -2,100 +2,94 @@
 
 pub const SIGNATURE_SIZE_LIMIT: usize = 256;
 
-pub trait Name {
-	const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT];
-	const SIGNATURE_LEN: usize;
-
-	fn name() -> &'static str {
-		from_utf8(&Self::SIGNATURE[..Self::SIGNATURE_LEN]).expect("bad utf-8")
-	}
+#[derive(Debug)]
+pub struct SignaturePreferences {
+	pub open_name: Option<SignatureUnit>,
+	pub open_delimiter: Option<SignatureUnit>,
+	pub param_delimiter: Option<SignatureUnit>,
+	pub close_delimiter: Option<SignatureUnit>,
+	pub close_name: Option<SignatureUnit>,
 }
 
 #[derive(Debug)]
 pub struct FunctionSignature {
-	pub signature: [u8; SIGNATURE_SIZE_LIMIT],
-	pub signature_len: usize,
+	pub data: [u8; SIGNATURE_SIZE_LIMIT],
+	pub len: usize,
+
+	preferences: SignaturePreferences,
 }
 
 impl FunctionSignature {
-	pub const fn new(name: &'static FunctionName) -> FunctionSignature {
-		let mut signature = [0_u8; SIGNATURE_SIZE_LIMIT];
-		let name_len = name.signature_len;
-		let name = name.signature;
+	pub const fn new(preferences: SignaturePreferences) -> FunctionSignature {
+		let mut dst = [0_u8; SIGNATURE_SIZE_LIMIT];
 		let mut dst_offset = 0;
-		let bracket_open = {
-			let mut b = [0_u8; SIGNATURE_SIZE_LIMIT];
-			b[0] = b"("[0];
-			b
-		};
-		crate::make_signature!(@copy(name, signature, name_len, dst_offset));
-		crate::make_signature!(@copy(bracket_open, signature, 1, dst_offset));
+		if let Some(ref name) = preferences.open_name {
+			crate::make_signature!(@copy(name.data, dst, name.len, dst_offset));
+		}
+		if let Some(ref delimiter) = preferences.open_delimiter {
+			crate::make_signature!(@copy(delimiter.data, dst, delimiter.len, dst_offset));
+		}
 		FunctionSignature {
-			signature,
-			signature_len: dst_offset,
+			data: dst,
+			len: dst_offset,
+			preferences,
 		}
 	}
 
 	pub const fn add_param(
 		signature: FunctionSignature,
-		param: ([u8; SIGNATURE_SIZE_LIMIT], usize),
+		param: SignatureUnit,
 	) -> FunctionSignature {
-		let mut dst = signature.signature;
-		let mut dst_offset = signature.signature_len;
-		let (param_name, param_len) = param;
-		let comma = {
-			let mut b = [0_u8; SIGNATURE_SIZE_LIMIT];
-			b[0] = b","[0];
-			b
-		};
+		let mut dst = signature.data;
+		let mut dst_offset = signature.len;
+		crate::make_signature!(@copy(param.data, dst, param.len, dst_offset));
+		if let Some(ref delimiter) = signature.preferences.param_delimiter {
+			crate::make_signature!(@copy(delimiter.data, dst, delimiter.len, dst_offset));
+		}
 		FunctionSignature {
-			signature: {
-				crate::make_signature!(@copy(param_name, dst, param_len, dst_offset));
-				crate::make_signature!(@copy(comma, dst, 1, dst_offset));
-				dst
-			},
-			signature_len: dst_offset,
+			data: dst,
+			len: dst_offset,
+			..signature
 		}
 	}
 
 	pub const fn done(signature: FunctionSignature, owerride: bool) -> FunctionSignature {
-		let mut dst = signature.signature;
-		let mut dst_offset = signature.signature_len - if owerride { 1 } else { 0 };
-		let bracket_close = {
-			let mut b = [0_u8; SIGNATURE_SIZE_LIMIT];
-			b[0] = b")"[0];
-			b
-		};
+		let mut dst = signature.data;
+		let mut dst_offset = signature.len - if owerride { 1 } else { 0 };
+		if let Some(ref delimiter) = signature.preferences.close_delimiter {
+			crate::make_signature!(@copy(delimiter.data, dst, delimiter.len, dst_offset));
+		}
+		if let Some(ref name) = signature.preferences.close_name {
+			crate::make_signature!(@copy(name.data, dst, name.len, dst_offset));
+		}
 		FunctionSignature {
-			signature: {
-				crate::make_signature!(@copy(bracket_close, dst, 1, dst_offset));
-				dst
-			},
-			signature_len: dst_offset,
+			data: dst,
+			len: dst_offset,
+			..signature
 		}
 	}
 
-	// fn as_str(&self) -> &'static str {
-	// 	from_utf8(&self.signature[..self.signature_len]).expect("bad utf-8")
-	// }
+	pub fn as_str(&self) -> &str {
+		from_utf8(&self.data[..self.len]).expect("bad utf-8")
+	}
 }
 
 #[derive(Debug)]
-pub struct FunctionName {
-	signature: [u8; SIGNATURE_SIZE_LIMIT],
-	signature_len: usize,
+pub struct SignatureUnit {
+	pub data: [u8; SIGNATURE_SIZE_LIMIT],
+	pub len: usize,
 }
 
-impl FunctionName {
-	pub const fn new(name: &'static str) -> FunctionName {
+impl SignatureUnit {
+	pub const fn new(name: &'static str) -> SignatureUnit {
 		let mut signature = [0_u8; SIGNATURE_SIZE_LIMIT];
 		let name = name.as_bytes();
 		let name_len = name.len();
 		let mut dst_offset = 0;
 		crate::make_signature!(@copy(name, signature, name_len, dst_offset));
-		FunctionName {
-			signature,
-			signature_len: name_len,
+		SignatureUnit {
+			data: signature,
+			len: name_len,
 		}
 	}
 }
@@ -105,14 +99,14 @@
 macro_rules! make_signature { // May be "define_signature"?
 	(new fn($func:expr)$(,)+) => {
 		{
-			let fs = FunctionSignature::new(& $func);
+			let fs = FunctionSignature::new($func);
 			let fs = FunctionSignature::done(fs, false);
 			fs
 		}
 	};
-	(new fn($func:expr), $($tt:tt)*) => {
+	(new fn($func:expr), $($tt:tt,)*) => {
 		{
-			let fs = FunctionSignature::new(& $func);
+			let fs = FunctionSignature::new($func);
 			let fs = make_signature!(@param; fs, $($tt),*);
 			fs
 		}
@@ -129,16 +123,16 @@
 	};
 
     (new $($tt:tt)*) => {
-        const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT] = {
-            let mut out = [0u8; SIGNATURE_SIZE_LIMIT];
-            let mut dst_offset = 0;
-            make_signature!(@data(out, dst_offset); $($tt)*);
-            out
+        const SIGNATURE: SignatureUnit = SignatureUnit {
+			data: {
+				let mut out = [0u8; SIGNATURE_SIZE_LIMIT];
+				let mut dst_offset = 0;
+				make_signature!(@data(out, dst_offset); $($tt)*);
+				out
+			},
+			len: {0 + make_signature!(@size; $($tt)*)},
         };
-        const SIGNATURE_LEN: usize = 0 + make_signature!(@size; $($tt)*);
     };
-
-	// (@bytes)
 
     (@size;) => {
         0
@@ -147,8 +141,11 @@
         $expr.len() + make_signature!(@size; $($tt)*)
     };
     (@size; nameof($expr:ty) $($tt:tt)*) => {
-        <$expr>::SIGNATURE_LEN + make_signature!(@size; $($tt)*)
+		<$expr>::SIGNATURE.len + make_signature!(@size; $($tt)*)
     };
+	(@size; shift_left($expr:expr) $($tt:tt)*) => {
+		make_signature!(@size; $($tt)*) - $expr
+	};
 
     (@data($dst:ident, $dst_offset:ident);) => {};
     (@data($dst:ident, $dst_offset:ident); fixed($expr:expr) $($tt:tt)*) => {
@@ -161,14 +158,16 @@
     };
     (@data($dst:ident, $dst_offset:ident); nameof($expr:ty) $($tt:tt)*) => {
         {
-			let data = &<$expr>::SIGNATURE;
-			let data_len = <$expr>::SIGNATURE_LEN;
-            make_signature!(@copy(data, $dst, data_len, $dst_offset));
+            make_signature!(@copy(&<$expr>::SIGNATURE.data, $dst, <$expr>::SIGNATURE.len, $dst_offset));
         }
         make_signature!(@data($dst, $dst_offset); $($tt)*)
     };
+	(@data($dst:ident, $dst_offset:ident); shift_left($expr:expr) $($tt:tt)*) => {
+        $dst_offset -= $expr;
+        make_signature!(@data($dst, $dst_offset); $($tt)*)
+    };
 
-	(@copy($src:ident, $dst:ident, $src_len:expr, $dst_offset:ident)) => {
+	(@copy($src:expr, $dst:expr, $src_len:expr, $dst_offset:ident)) => {
 		{
 			let mut src_offset = 0;
 			let src_len: usize = $src_len;
@@ -185,10 +184,16 @@
 mod test {
 	use core::str::from_utf8;
 
-	use frame_support::sp_runtime::app_crypto::sp_core::hexdisplay::AsBytesRef;
+	use super::{SIGNATURE_SIZE_LIMIT, SignatureUnit, FunctionSignature, SignaturePreferences};
 
-	use super::{Name, SIGNATURE_SIZE_LIMIT, FunctionName, FunctionSignature};
+	trait Name {
+		const SIGNATURE: SignatureUnit;
 
+		fn name() -> &'static str {
+			from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
+		}
+	}
+
 	impl Name for u8 {
 		make_signature!(new fixed("uint8"));
 	}
@@ -201,13 +206,26 @@
 	impl<A: Name, B: Name> Name for (A, B) {
 		make_signature!(new fixed("(") nameof(A) fixed(",") nameof(B) fixed(")"));
 	}
+	impl<A: Name> Name for (A,) {
+		make_signature!(new fixed("(") nameof(A) fixed(",") shift_left(1) fixed(")"));
+	}
 
 	struct MaxSize();
 	impl Name for MaxSize {
-		const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT] = [b'!'; SIGNATURE_SIZE_LIMIT];
-		const SIGNATURE_LEN: usize = SIGNATURE_SIZE_LIMIT;
+		const SIGNATURE: SignatureUnit = SignatureUnit {
+			data: [b'!'; SIGNATURE_SIZE_LIMIT],
+			len: SIGNATURE_SIZE_LIMIT,
+		};
 	}
 
+	const SIGNATURE_PREFERENCES: SignaturePreferences = SignaturePreferences {
+		open_name: Some(SignatureUnit::new("some_funk")),
+		open_delimiter: Some(SignatureUnit::new("(")),
+		param_delimiter: Some(SignatureUnit::new(",")),
+		close_delimiter: Some(SignatureUnit::new(")")),
+		close_name: None,
+	};
+
 	#[test]
 	fn simple() {
 		assert_eq!(u8::name(), "uint8");
@@ -269,68 +287,68 @@
 
 	#[test]
 	fn make_func_without_args() {
-		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");
 		const SIG: FunctionSignature = make_signature!(
-			new fn(&SOME_FUNK_NAME),
+			new fn(SIGNATURE_PREFERENCES),
 		);
-		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();
-		assert_eq!(name, "some_funk()");
+		let name = SIG.as_str();
+		similar_asserts::assert_eq!(name, "some_funk()");
 	}
 
 	#[test]
 	fn make_func_with_1_args() {
-		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");
 		const SIG: FunctionSignature = make_signature!(
-			new fn(&SOME_FUNK_NAME),
-			(u8::SIGNATURE, u8::SIGNATURE_LEN)
+			new fn(SIGNATURE_PREFERENCES),
+			(<u8>::SIGNATURE),
 		);
-		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();
-		assert_eq!(name, "some_funk(uint8)");
+		let name = SIG.as_str();
+		similar_asserts::assert_eq!(name, "some_funk(uint8)");
 	}
 
 	#[test]
 	fn make_func_with_2_args() {
-		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");
 		const SIG: FunctionSignature = make_signature!(
-			new fn(&SOME_FUNK_NAME),
-			(u8::SIGNATURE, u8::SIGNATURE_LEN)
-			(<Vec<u32>>::SIGNATURE, <Vec<u32>>::SIGNATURE_LEN)
+			new fn(SIGNATURE_PREFERENCES),
+			(u8::SIGNATURE),
+			(<Vec<u32>>::SIGNATURE),
 		);
-		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();
-		assert_eq!(name, "some_funk(uint8,uint32[])");
+		let name = SIG.as_str();
+		similar_asserts::assert_eq!(name, "some_funk(uint8,uint32[])");
 	}
 
 	#[test]
 	fn make_func_with_3_args() {
-		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");
 		const SIG: FunctionSignature = make_signature!(
-			new fn(&SOME_FUNK_NAME),
-			(u8::SIGNATURE, u8::SIGNATURE_LEN)
-			(u32::SIGNATURE, u32::SIGNATURE_LEN)
-			(<Vec<u32>>::SIGNATURE, <Vec<u32>>::SIGNATURE_LEN)
+			new fn(SIGNATURE_PREFERENCES),
+			(<u8>::SIGNATURE),
+			(<u32>::SIGNATURE),
+			(<Vec<u32>>::SIGNATURE),
 		);
-		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();
-		assert_eq!(name, "some_funk(uint8,uint32,uint32[])");
+		let name = SIG.as_str();
+		similar_asserts::assert_eq!(name, "some_funk(uint8,uint32,uint32[])");
 	}
 
 	#[test]
 	fn make_slice_from_signature() {
-		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");
 		const SIG: FunctionSignature = make_signature!(
-			new fn(&SOME_FUNK_NAME),
-			(u8::SIGNATURE, u8::SIGNATURE_LEN)
-			(u32::SIGNATURE, u32::SIGNATURE_LEN)
-			(<Vec<u32>>::SIGNATURE, <Vec<u32>>::SIGNATURE_LEN)
+			new fn(SIGNATURE_PREFERENCES),
+			(<u8>::SIGNATURE),
+			(<u32>::SIGNATURE),
+			(<Vec<u32>>::SIGNATURE),
 		);
-		const NAME: [u8; SIG.signature_len] = {
-			let mut name: [u8; SIG.signature_len] = [0; SIG.signature_len];
+		const NAME: [u8; SIG.len] = {
+			let mut name: [u8; SIG.len] = [0; SIG.len];
 			let mut i = 0;
-			while i < SIG.signature_len {
-				name[i] = SIG.signature[i];
+			while i < SIG.len {
+				name[i] = SIG.data[i];
 				i += 1;
 			}
 			name
 		};
-		assert_eq!(&NAME, b"some_funk(uint8,uint32,uint32[])");
+		similar_asserts::assert_eq!(&NAME, b"some_funk(uint8,uint32,uint32[])");
+	}
+
+	#[test]
+	fn shift() {
+		assert_eq!(<(u32,)>::name(), "(uint32)");
 	}
 }
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -124,14 +124,13 @@
 	use primitive_types::{U256, H160, H256};
 	use core::str::from_utf8;
 
-	use crate::custom_signature::SIGNATURE_SIZE_LIMIT;
+	use crate::custom_signature::{SignatureUnit, SIGNATURE_SIZE_LIMIT};
 
 	pub trait Signature {
-		const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT];
-		const SIGNATURE_LEN: usize;
+		const SIGNATURE: SignatureUnit;
 
 		fn as_str() -> &'static str {
-			from_utf8(&Self::SIGNATURE[..Self::SIGNATURE_LEN]).expect("bad utf-8")
+			from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
 		}
 	}
 
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -30,7 +30,6 @@
 	marker::PhantomData,
 	cell::{Cell, RefCell},
 	cmp::Reverse,
-	str::from_utf8,
 };
 use impl_trait_for_tuples::impl_for_tuples;
 use crate::{types::*, custom_signature::FunctionSignature};
@@ -514,10 +513,16 @@
 		writeln!(
 			writer,
 			"\t{hide_comment}///  or in textual repr: {}",
-			// from_utf8(self.custom_signature.as_str()).expect("bad utf8")
 			self.selector_str
 		)?;
-		write!(writer, "\t{hide_comment}function {}(", self.name)?;
+		if self.selector_str != self.custom_signature.as_str() {
+			writeln!(
+				writer,
+				"\t{hide_comment}///  or in the expanded repr: {}",
+				self.custom_signature.as_str()
+			)?;
+		}
+		write!(writer, "\tfunction {}(", self.name)?;
 		self.args.solidity_name(writer, tc)?;
 		write!(writer, ")")?;
 		if is_impl {
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -21,7 +21,7 @@
 	types::*,
 	execution::{Result, Error},
 	weight,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 };
 pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -17,7 +17,7 @@
 //! Implementation of magic contract
 
 extern crate alloc;
-use alloc::{format, string::ToString};
+use alloc::string::ToString;
 use core::marker::PhantomData;
 use evm_coder::{
 	abi::AbiWriter,
@@ -25,7 +25,7 @@
 	generate_stubgen, solidity_interface,
 	types::*,
 	ToLog,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 };
 use pallet_evm::{
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -17,7 +17,6 @@
 //! ERC-20 standart support implementation.
 
 extern crate alloc;
-use alloc::{format, string::ToString};
 use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
 use core::convert::TryInto;
 use evm_coder::{
@@ -26,7 +25,7 @@
 	generate_stubgen, solidity_interface,
 	types::*,
 	weight,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 };
 use pallet_common::eth::convert_tuple_to_cross_account;
deletedpallets/nonfungible/expand.rsdiffbeforeafterboth
--- a/pallets/nonfungible/expand.rs
+++ /dev/null
@@ -1,8880 +0,0 @@
-#![feature(prelude_import)]
-//! # Nonfungible Pallet
-//!
-//! The Nonfungible pallet provides functionality for handling nonfungible collections and tokens.
-//!
-//! - [`Config`]
-//! - [`NonfungibleHandle`]
-//! - [`Pallet`]
-//! - [`CommonWeights`](common::CommonWeights)
-//!
-//! ## Overview
-//!
-//! The Nonfungible pallet provides functions for:
-//!
-//! - NFT collection creation and removal
-//! - Minting and burning of NFT tokens
-//! - Retrieving account balances
-//! - Transfering NFT tokens
-//! - Setting and checking allowance for NFT tokens
-//! - Setting properties and permissions for NFT collections and tokens
-//! - Nesting and unnesting tokens
-//!
-//! ### Terminology
-//!
-//! - **NFT token:** Non fungible token.
-//!
-//! - **NFT Collection:** A collection of NFT tokens. All NFT tokens are part of a collection.
-//!   Each collection can define it's own properties, properties for it's tokens and set of permissions.
-//!
-//! - **Balance:** Number of NFT tokens owned by an account
-//!
-//! - **Allowance:** NFT tokens owned by one account that another account is allowed to make operations on
-//!
-//! - **Burning:** The process of “deleting” a token from a collection and from
-//!   an account balance of the owner.
-//!
-//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting
-//!   owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in
-//!   it's child token i.e. parent-child relationship graph shouldn't have cycles.
-//!
-//! - **Properties:** Key-Values pairs. Token properties are attached to a token. Collection properties are
-//!   attached to a collection. Set of permissions could be defined for each property.
-//!
-//! ### Implementations
-//!
-//! The Nonfungible pallet provides implementations for the following traits. If these traits provide
-//! the functionality that you need, then you can avoid coupling with the Nonfungible pallet.
-//!
-//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight
-//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing
-//!   with collections
-//!
-//! ## Interface
-//!
-//! ### Dispatchable Functions
-//!
-//! - `init_collection` - Create NFT collection. NFT collection can be configured to allow or deny access for
-//!   some accounts.
-//! - `destroy_collection` - Destroy exising NFT collection. There should be no tokens in the collection.
-//! - `burn` - Burn NFT token owned by account.
-//! - `transfer` - Transfer NFT token. Transfers should be enabled for NFT collection.
-//!   Nests the NFT token if it is sent to another token.
-//! - `create_item` - Mint NFT token in collection. Sender should have permission to mint tokens.
-//! - `set_allowance` - Set allowance for another account.
-//! - `set_token_property` - Set token property value.
-//! - `delete_token_property` - Remove property from the token.
-//! - `set_collection_properties` - Set collection properties.
-//! - `delete_collection_properties` - Remove properties from the collection.
-//! - `set_property_permission` - Set collection property permission.
-//! - `set_token_property_permissions` - Set token property permissions.
-//!
-//! ## Assumptions
-//!
-//! * To perform operations on tokens sender should be in collection's allow list if collection access mode is `AllowList`.
-#[prelude_import]
-use std::prelude::rust_2021::*;
-#[macro_use]
-extern crate std;
-use erc::ERC721Events;
-use evm_coder::ToLog;
-use frame_support::{
-    BoundedVec, ensure, fail, transactional, storage::with_transaction,
-    pallet_prelude::DispatchResultWithPostInfo, pallet_prelude::Weight,
-    weights::{PostDispatchInfo, Pays},
-};
-use up_data_structs::{
-    AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId,
-    CreateCollectionData, CreateNftExData, mapping::TokenAddressMapping, budget::Budget,
-    Property, PropertyPermission, PropertyKey, PropertyValue, PropertyKeyPermission,
-    Properties, PropertyScope, TrySetProperty, TokenChild, AuxPropertyValue,
-};
-use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
-use pallet_common::{
-    Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,
-    eth::collection_id_to_address,
-};
-use pallet_structure::{Pallet as PalletStructure, Error as StructureError};
-use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
-use sp_core::H160;
-use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
-use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
-use core::ops::Deref;
-use codec::{Encode, Decode, MaxEncodedLen};
-use scale_info::TypeInfo;
-pub use pallet::*;
-use weights::WeightInfo;
-pub mod common {
-    use core::marker::PhantomData;
-    use frame_support::{
-        dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight,
-    };
-    use up_data_structs::{
-        TokenId, CreateItemExData, CollectionId, budget::Budget, Property, PropertyKey,
-        PropertyKeyPermission, PropertyValue,
-    };
-    use pallet_common::{
-        CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,
-        weights::WeightInfo as _,
-    };
-    use sp_runtime::DispatchError;
-    use sp_std::{vec::Vec, vec};
-    use crate::{
-        AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle,
-        Owned, Pallet, SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,
-    };
-    pub struct CommonWeights<T: Config>(PhantomData<T>);
-    impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {
-        fn create_item() -> Weight {
-            <SelfWeightOf<T>>::create_item()
-        }
-        fn create_multiple_items_ex(
-            data: &CreateItemExData<T::CrossAccountId>,
-        ) -> Weight {
-            match data {
-                CreateItemExData::NFT(t) => {
-                    <SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32)
-                        + t
-                            .iter()
-                            .filter_map(|t| {
-                                if t.properties.len() > 0 {
-                                    Some(Self::set_token_properties(t.properties.len() as u32))
-                                } else {
-                                    None
-                                }
-                            })
-                            .fold(Weight::zero(), |a, b| a.saturating_add(b))
-                }
-                _ => Weight::zero(),
-            }
-        }
-        fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {
-            <SelfWeightOf<T>>::create_multiple_items(data.len() as u32)
-                + data
-                    .iter()
-                    .filter_map(|t| match t {
-                        up_data_structs::CreateItemData::NFT(
-                            n,
-                        ) if n.properties.len() > 0 => {
-                            Some(Self::set_token_properties(n.properties.len() as u32))
-                        }
-                        _ => None,
-                    })
-                    .fold(Weight::zero(), |a, b| a.saturating_add(b))
-        }
-        fn burn_item() -> Weight {
-            <SelfWeightOf<T>>::burn_item()
-        }
-        fn set_collection_properties(amount: u32) -> Weight {
-            <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)
-        }
-        fn delete_collection_properties(amount: u32) -> Weight {
-            <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)
-        }
-        fn set_token_properties(amount: u32) -> Weight {
-            <SelfWeightOf<T>>::set_token_properties(amount)
-        }
-        fn delete_token_properties(amount: u32) -> Weight {
-            <SelfWeightOf<T>>::delete_token_properties(amount)
-        }
-        fn set_token_property_permissions(amount: u32) -> Weight {
-            <SelfWeightOf<T>>::set_token_property_permissions(amount)
-        }
-        fn transfer() -> Weight {
-            <SelfWeightOf<T>>::transfer()
-        }
-        fn approve() -> Weight {
-            <SelfWeightOf<T>>::approve()
-        }
-        fn transfer_from() -> Weight {
-            <SelfWeightOf<T>>::transfer_from()
-        }
-        fn burn_from() -> Weight {
-            <SelfWeightOf<T>>::burn_from()
-        }
-        fn burn_recursively_self_raw() -> Weight {
-            <SelfWeightOf<T>>::burn_recursively_self_raw()
-        }
-        fn burn_recursively_breadth_raw(amount: u32) -> Weight {
-            <SelfWeightOf<
-                T,
-            >>::burn_recursively_breadth_plus_self_plus_self_per_each_raw(amount)
-                .saturating_sub(
-                    Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1),
-                )
-        }
-        fn token_owner() -> Weight {
-            <SelfWeightOf<T>>::token_owner()
-        }
-    }
-    fn map_create_data<T: Config>(
-        data: up_data_structs::CreateItemData,
-        to: &T::CrossAccountId,
-    ) -> Result<CreateItemData<T>, DispatchError> {
-        match data {
-            up_data_structs::CreateItemData::NFT(data) => {
-                Ok(CreateItemData::<T> {
-                    properties: data.properties,
-                    owner: to.clone(),
-                })
-            }
-            _ => {
-                return Err(
-                    <Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken
-                        .into(),
-                );
-            }
-        }
-    }
-    /// Implementation of `CommonCollectionOperations` for `NonfungibleHandle`. It wraps Nonfungible Pallete
-    /// methods and adds weight info.
-    impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {
-        fn create_item(
-            &self,
-            sender: T::CrossAccountId,
-            to: T::CrossAccountId,
-            data: up_data_structs::CreateItemData,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            with_weight(
-                <Pallet<
-                    T,
-                >>::create_item(
-                    self,
-                    &sender,
-                    map_create_data::<T>(data, &to)?,
-                    nesting_budget,
-                ),
-                <CommonWeights<T>>::create_item(),
-            )
-        }
-        fn create_multiple_items(
-            &self,
-            sender: T::CrossAccountId,
-            to: T::CrossAccountId,
-            data: Vec<up_data_structs::CreateItemData>,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<T>>::create_multiple_items(&data);
-            let data = data
-                .into_iter()
-                .map(|d| map_create_data::<T>(d, &to))
-                .collect::<Result<Vec<_>, DispatchError>>()?;
-            with_weight(
-                <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),
-                weight,
-            )
-        }
-        fn create_multiple_items_ex(
-            &self,
-            sender: <T>::CrossAccountId,
-            data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);
-            let data = match data {
-                up_data_structs::CreateItemExData::NFT(nft) => nft,
-                _ => {
-                    return Err(
-                        Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken
-                            .into(),
-                    );
-                }
-            };
-            with_weight(
-                <Pallet<
-                    T,
-                >>::create_multiple_items(
-                    self,
-                    &sender,
-                    data.into_inner(),
-                    nesting_budget,
-                ),
-                weight,
-            )
-        }
-        fn set_collection_properties(
-            &self,
-            sender: T::CrossAccountId,
-            properties: Vec<Property>,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<
-                T,
-            >>::set_collection_properties(properties.len() as u32);
-            with_weight(
-                <Pallet<T>>::set_collection_properties(self, &sender, properties),
-                weight,
-            )
-        }
-        fn delete_collection_properties(
-            &self,
-            sender: &T::CrossAccountId,
-            property_keys: Vec<PropertyKey>,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<
-                T,
-            >>::delete_collection_properties(property_keys.len() as u32);
-            with_weight(
-                <Pallet<T>>::delete_collection_properties(self, sender, property_keys),
-                weight,
-            )
-        }
-        fn set_token_properties(
-            &self,
-            sender: T::CrossAccountId,
-            token_id: TokenId,
-            properties: Vec<Property>,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<
-                T,
-            >>::set_token_properties(properties.len() as u32);
-            with_weight(
-                <Pallet<
-                    T,
-                >>::set_token_properties(
-                    self,
-                    &sender,
-                    token_id,
-                    properties.into_iter(),
-                    false,
-                    nesting_budget,
-                ),
-                weight,
-            )
-        }
-        fn delete_token_properties(
-            &self,
-            sender: T::CrossAccountId,
-            token_id: TokenId,
-            property_keys: Vec<PropertyKey>,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<
-                T,
-            >>::delete_token_properties(property_keys.len() as u32);
-            with_weight(
-                <Pallet<
-                    T,
-                >>::delete_token_properties(
-                    self,
-                    &sender,
-                    token_id,
-                    property_keys.into_iter(),
-                    nesting_budget,
-                ),
-                weight,
-            )
-        }
-        fn set_token_property_permissions(
-            &self,
-            sender: &T::CrossAccountId,
-            property_permissions: Vec<PropertyKeyPermission>,
-        ) -> DispatchResultWithPostInfo {
-            let weight = <CommonWeights<
-                T,
-            >>::set_token_property_permissions(property_permissions.len() as u32);
-            with_weight(
-                <Pallet<
-                    T,
-                >>::set_token_property_permissions(self, sender, property_permissions),
-                weight,
-            )
-        }
-        fn burn_item(
-            &self,
-            sender: T::CrossAccountId,
-            token: TokenId,
-            amount: u128,
-        ) -> DispatchResultWithPostInfo {
-            {
-                if !(amount <= 1) {
-                    { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };
-                }
-            };
-            if amount == 1 {
-                with_weight(
-                    <Pallet<T>>::burn(self, &sender, token),
-                    <CommonWeights<T>>::burn_item(),
-                )
-            } else {
-                Ok(().into())
-            }
-        }
-        fn burn_item_recursively(
-            &self,
-            sender: T::CrossAccountId,
-            token: TokenId,
-            self_budget: &dyn Budget,
-            breadth_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            <Pallet<
-                T,
-            >>::burn_recursively(self, &sender, token, self_budget, breadth_budget)
-        }
-        fn transfer(
-            &self,
-            from: T::CrossAccountId,
-            to: T::CrossAccountId,
-            token: TokenId,
-            amount: u128,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            {
-                if !(amount <= 1) {
-                    { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };
-                }
-            };
-            if amount == 1 {
-                with_weight(
-                    <Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),
-                    <CommonWeights<T>>::transfer(),
-                )
-            } else {
-                Ok(().into())
-            }
-        }
-        fn approve(
-            &self,
-            sender: T::CrossAccountId,
-            spender: T::CrossAccountId,
-            token: TokenId,
-            amount: u128,
-        ) -> DispatchResultWithPostInfo {
-            {
-                if !(amount <= 1) {
-                    { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };
-                }
-            };
-            with_weight(
-                if amount == 1 {
-                    <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))
-                } else {
-                    <Pallet<T>>::set_allowance(self, &sender, token, None)
-                },
-                <CommonWeights<T>>::approve(),
-            )
-        }
-        fn transfer_from(
-            &self,
-            sender: T::CrossAccountId,
-            from: T::CrossAccountId,
-            to: T::CrossAccountId,
-            token: TokenId,
-            amount: u128,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            {
-                if !(amount <= 1) {
-                    { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };
-                }
-            };
-            if amount == 1 {
-                with_weight(
-                    <Pallet<
-                        T,
-                    >>::transfer_from(self, &sender, &from, &to, token, nesting_budget),
-                    <CommonWeights<T>>::transfer_from(),
-                )
-            } else {
-                Ok(().into())
-            }
-        }
-        fn burn_from(
-            &self,
-            sender: T::CrossAccountId,
-            from: T::CrossAccountId,
-            token: TokenId,
-            amount: u128,
-            nesting_budget: &dyn Budget,
-        ) -> DispatchResultWithPostInfo {
-            {
-                if !(amount <= 1) {
-                    { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };
-                }
-            };
-            if amount == 1 {
-                with_weight(
-                    <Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),
-                    <CommonWeights<T>>::burn_from(),
-                )
-            } else {
-                Ok(().into())
-            }
-        }
-        fn check_nesting(
-            &self,
-            sender: T::CrossAccountId,
-            from: (CollectionId, TokenId),
-            under: TokenId,
-            nesting_budget: &dyn Budget,
-        ) -> sp_runtime::DispatchResult {
-            <Pallet<T>>::check_nesting(self, sender, from, under, nesting_budget)
-        }
-        fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {
-            <Pallet<T>>::nest((self.id, under), to_nest);
-        }
-        fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {
-            <Pallet<T>>::unnest((self.id, under), to_unnest);
-        }
-        fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
-            <Owned<T>>::iter_prefix((self.id, account)).map(|(id, _)| id).collect()
-        }
-        fn collection_tokens(&self) -> Vec<TokenId> {
-            <TokenData<T>>::iter_prefix((self.id,)).map(|(id, _)| id).collect()
-        }
-        fn token_exists(&self, token: TokenId) -> bool {
-            <Pallet<T>>::token_exists(self, token)
-        }
-        fn last_token_id(&self) -> TokenId {
-            TokenId(<TokensMinted<T>>::get(self.id))
-        }
-        fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {
-            <TokenData<T>>::get((self.id, token)).map(|t| t.owner)
-        }
-        /// Returns token owners.
-        fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {
-            self.token_owner(token)
-                .map_or_else(
-                    || ::alloc::vec::Vec::new(),
-                    |t| <[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([t])),
-                )
-        }
-        fn token_property(
-            &self,
-            token_id: TokenId,
-            key: &PropertyKey,
-        ) -> Option<PropertyValue> {
-            <Pallet<T>>::token_properties((self.id, token_id)).get(key).cloned()
-        }
-        fn token_properties(
-            &self,
-            token_id: TokenId,
-            keys: Option<Vec<PropertyKey>>,
-        ) -> Vec<Property> {
-            let properties = <Pallet<T>>::token_properties((self.id, token_id));
-            keys.map(|keys| {
-                    keys.into_iter()
-                        .filter_map(|key| {
-                            properties
-                                .get(&key)
-                                .map(|value| Property {
-                                    key,
-                                    value: value.clone(),
-                                })
-                        })
-                        .collect()
-                })
-                .unwrap_or_else(|| {
-                    properties
-                        .into_iter()
-                        .map(|(key, value)| Property { key, value })
-                        .collect()
-                })
-        }
-        fn total_supply(&self) -> u32 {
-            <Pallet<T>>::total_supply(self)
-        }
-        fn account_balance(&self, account: T::CrossAccountId) -> u32 {
-            <AccountBalance<T>>::get((self.id, account))
-        }
-        fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {
-            if <TokenData<T>>::get((self.id, token))
-                .map(|a| a.owner == account)
-                .unwrap_or(false)
-            {
-                1
-            } else {
-                0
-            }
-        }
-        fn allowance(
-            &self,
-            sender: T::CrossAccountId,
-            spender: T::CrossAccountId,
-            token: TokenId,
-        ) -> u128 {
-            if <TokenData<T>>::get((self.id, token))
-                .map(|a| a.owner != sender)
-                .unwrap_or(true)
-            {
-                0
-            } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {
-                1
-            } else {
-                0
-            }
-        }
-        fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {
-            None
-        }
-        fn total_pieces(&self, token: TokenId) -> Option<u128> {
-            if <TokenData<T>>::contains_key((self.id, token)) { Some(1) } else { None }
-        }
-    }
-}
-pub mod erc {
-    //! # Nonfungible Pallet EVM API
-    //!
-    //! Provides ERC-721 standart support implementation and EVM API for unique extensions for Nonfungible Pallet.
-    //! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
-    extern crate alloc;
-    use alloc::{format, string::ToString};
-    use core::{
-        char::{REPLACEMENT_CHARACTER, decode_utf16},
-        convert::TryInto,
-    };
-    use evm_coder::{
-        ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,
-        weight, custom_signature::{FunctionName, FunctionSignature},
-        make_signature,
-    };
-    use frame_support::BoundedVec;
-    use up_data_structs::{
-        TokenId, PropertyPermission, PropertyKeyPermission, Property, CollectionId,
-        PropertyKey, CollectionPropertiesVec,
-    };
-    use pallet_evm_coder_substrate::dispatch_to_evm;
-    use sp_std::vec::Vec;
-    use pallet_common::{
-        erc::{
-            CommonEvmHandler, PrecompileResult, CollectionCall,
-            static_property::{key, value as property_value},
-        },
-        CollectionHandle, CollectionPropertyPermissions,
-        eth::convert_tuple_to_cross_account,
-    };
-    use pallet_evm::{account::CrossAccountId, PrecompileHandle};
-    use pallet_evm_coder_substrate::call;
-    use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
-    use crate::{
-        AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData,
-        TokensMinted, SelfWeightOf, weights::WeightInfo, TokenProperties,
-    };
-    /// @title A contract that allows to set and delete token properties and change token property permissions.
-    impl<T: Config> NonfungibleHandle<T> {
-        /// @notice Set permissions for token property.
-        /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
-        /// @param key Property key.
-        /// @param isMutable Permission to mutate property.
-        /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
-        /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
-        fn set_token_property_permission(
-            &mut self,
-            caller: caller,
-            key: string,
-            is_mutable: bool,
-            collection_admin: bool,
-            token_owner: bool,
-        ) -> Result<()> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            <Pallet<
-                T,
-            >>::set_property_permission(
-                    self,
-                    &caller,
-                    PropertyKeyPermission {
-                        key: <Vec<u8>>::from(key)
-                            .try_into()
-                            .map_err(|_| "too long key")?,
-                        permission: PropertyPermission {
-                            mutable: is_mutable,
-                            collection_admin,
-                            token_owner,
-                        },
-                    },
-                )
-                .map_err(dispatch_to_evm::<T>)
-        }
-        /// @notice Set token property value.
-        /// @dev Throws error if `msg.sender` has no permission to edit the property.
-        /// @param tokenId ID of the token.
-        /// @param key Property key.
-        /// @param value Property value.
-        fn set_property(
-            &mut self,
-            caller: caller,
-            token_id: uint256,
-            key: string,
-            value: bytes,
-        ) -> Result<()> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
-            let key = <Vec<u8>>::from(key).try_into().map_err(|_| "key too long")?;
-            let value = value.0.try_into().map_err(|_| "value too long")?;
-            let nesting_budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            <Pallet<
-                T,
-            >>::set_token_property(
-                    self,
-                    &caller,
-                    TokenId(token_id),
-                    Property { key, value },
-                    &nesting_budget,
-                )
-                .map_err(dispatch_to_evm::<T>)
-        }
-        /// @notice Delete token property value.
-        /// @dev Throws error if `msg.sender` has no permission to edit the property.
-        /// @param tokenId ID of the token.
-        /// @param key Property key.
-        fn delete_property(
-            &mut self,
-            token_id: uint256,
-            caller: caller,
-            key: string,
-        ) -> Result<()> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
-            let key = <Vec<u8>>::from(key).try_into().map_err(|_| "key too long")?;
-            let nesting_budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            <Pallet<
-                T,
-            >>::delete_token_property(
-                    self,
-                    &caller,
-                    TokenId(token_id),
-                    key,
-                    &nesting_budget,
-                )
-                .map_err(dispatch_to_evm::<T>)
-        }
-        /// @notice Get token property value.
-        /// @dev Throws error if key not found
-        /// @param tokenId ID of the token.
-        /// @param key Property key.
-        /// @return Property value bytes
-        fn property(&self, token_id: uint256, key: string) -> Result<bytes> {
-            let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
-            let key = <Vec<u8>>::from(key).try_into().map_err(|_| "key too long")?;
-            let props = <TokenProperties<T>>::get((self.id, token_id));
-            let prop = props.get(&key).ok_or("key not found")?;
-            Ok(prop.to_vec().into())
-        }
-    }
-    /// @title A contract that allows to set and delete token properties and change token property permissions.
-    pub enum TokenPropertiesCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        /// @notice Set permissions for token property.
-        /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
-        /// @param key Property key.
-        /// @param isMutable Permission to mutate property.
-        /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
-        /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
-        #[allow(missing_docs)]
-        SetTokenPropertyPermission {
-            key: string,
-            is_mutable: bool,
-            collection_admin: bool,
-            token_owner: bool,
-        },
-        /// @notice Set token property value.
-        /// @dev Throws error if `msg.sender` has no permission to edit the property.
-        /// @param tokenId ID of the token.
-        /// @param key Property key.
-        /// @param value Property value.
-        #[allow(missing_docs)]
-        SetProperty { token_id: uint256, key: string, value: bytes },
-        /// @notice Delete token property value.
-        /// @dev Throws error if `msg.sender` has no permission to edit the property.
-        /// @param tokenId ID of the token.
-        /// @param key Property key.
-        #[allow(missing_docs)]
-        DeleteProperty { token_id: uint256, key: string },
-        /// @notice Get token property value.
-        /// @dev Throws error if key not found
-        /// @param tokenId ID of the token.
-        /// @param key Property key.
-        /// @return Property value bytes
-        #[allow(missing_docs)]
-        Property { token_id: uint256, key: string },
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for TokenPropertiesCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                TokenPropertiesCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                TokenPropertiesCall::SetTokenPropertyPermission {
-                    key: __self_0,
-                    is_mutable: __self_1,
-                    collection_admin: __self_2,
-                    token_owner: __self_3,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field4_finish(
-                        f,
-                        "SetTokenPropertyPermission",
-                        "key",
-                        &__self_0,
-                        "is_mutable",
-                        &__self_1,
-                        "collection_admin",
-                        &__self_2,
-                        "token_owner",
-                        &__self_3,
-                    )
-                }
-                TokenPropertiesCall::SetProperty {
-                    token_id: __self_0,
-                    key: __self_1,
-                    value: __self_2,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field3_finish(
-                        f,
-                        "SetProperty",
-                        "token_id",
-                        &__self_0,
-                        "key",
-                        &__self_1,
-                        "value",
-                        &__self_2,
-                    )
-                }
-                TokenPropertiesCall::DeleteProperty {
-                    token_id: __self_0,
-                    key: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "DeleteProperty",
-                        "token_id",
-                        &__self_0,
-                        "key",
-                        &__self_1,
-                    )
-                }
-                TokenPropertiesCall::Property { token_id: __self_0, key: __self_1 } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "Property",
-                        "token_id",
-                        &__self_0,
-                        "key",
-                        &__self_1,
-                    )
-                }
-            }
-        }
-    }
-    impl<T> TokenPropertiesCall<T> {
-        const SET_TOKEN_PROPERTY_PERMISSION_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(
-                    &&FunctionName::new("setTokenPropertyPermission"),
-                );
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                FunctionSignature::add_param(
-                                    fs,
-                                    (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                                ),
-                                (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                            ),
-                            (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                        ),
-                        (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///setTokenPropertyPermission(string,bool,bool,bool)
-        const SET_TOKEN_PROPERTY_PERMISSION: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::SET_TOKEN_PROPERTY_PERMISSION_SIGNATURE.signature,
-                    Self::SET_TOKEN_PROPERTY_PERMISSION_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const SET_PROPERTY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("setProperty"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                fs,
-                                (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                            ),
-                            (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                        ),
-                        (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///setProperty(uint256,string,bytes)
-        const SET_PROPERTY: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::SET_PROPERTY_SIGNATURE.signature,
-                    Self::SET_PROPERTY_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const DELETE_PROPERTY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("deleteProperty"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                        ),
-                        (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///deleteProperty(uint256,string)
-        const DELETE_PROPERTY: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::DELETE_PROPERTY_SIGNATURE.signature,
-                    Self::DELETE_PROPERTY_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const PROPERTY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("property"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                        ),
-                        (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///property(uint256,string)
-        const PROPERTY: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::PROPERTY_SIGNATURE.signature,
-                    Self::PROPERTY_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::SET_TOKEN_PROPERTY_PERMISSION);
-            interface_id ^= u32::from_be_bytes(Self::SET_PROPERTY);
-            interface_id ^= u32::from_be_bytes(Self::DELETE_PROPERTY);
-            interface_id ^= u32::from_be_bytes(Self::PROPERTY);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[
-                    " @title A contract that allows to set and delete token properties and change token property permissions.",
-                ],
-                name: "TokenProperties",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Set permissions for token property.",
-                            " @dev Throws error if `msg.sender` is not admin or owner of the collection.",
-                            " @param key Property key.",
-                            " @param isMutable Permission to mutate property.",
-                            " @param collectionAdmin Permission to mutate property by collection admin if property is mutable.",
-                            " @param tokenOwner Permission to mutate property by token owner if property is mutable.",
-                        ],
-                        selector_str: "setTokenPropertyPermission(string,bool,bool,bool)",
-                        selector: u32::from_be_bytes(
-                            Self::SET_TOKEN_PROPERTY_PERMISSION,
-                        ),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("setTokenPropertyPermission"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    FunctionSignature::add_param(
-                                                        fs,
-                                                        (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                                                    ),
-                                                    (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                                                ),
-                                                (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                                            ),
-                                            (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "setTokenPropertyPermission",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<string>>::new("key"),
-                            <NamedArgument<bool>>::new("isMutable"),
-                            <NamedArgument<bool>>::new("collectionAdmin"),
-                            <NamedArgument<bool>>::new("tokenOwner"),
-                        ),
-                        result: <UnnamedArgument<()>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Set token property value.",
-                            " @dev Throws error if `msg.sender` has no permission to edit the property.",
-                            " @param tokenId ID of the token.",
-                            " @param key Property key.",
-                            " @param value Property value.",
-                        ],
-                        selector_str: "setProperty(uint256,string,bytes)",
-                        selector: u32::from_be_bytes(Self::SET_PROPERTY),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("setProperty"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    fs,
-                                                    (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                                ),
-                                                (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                                            ),
-                                            (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "setProperty",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<uint256>>::new("tokenId"),
-                            <NamedArgument<string>>::new("key"),
-                            <NamedArgument<bytes>>::new("value"),
-                        ),
-                        result: <UnnamedArgument<()>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Delete token property value.",
-                            " @dev Throws error if `msg.sender` has no permission to edit the property.",
-                            " @param tokenId ID of the token.",
-                            " @param key Property key.",
-                        ],
-                        selector_str: "deleteProperty(uint256,string)",
-                        selector: u32::from_be_bytes(Self::DELETE_PROPERTY),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("deleteProperty"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                            ),
-                                            (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "deleteProperty",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<uint256>>::new("tokenId"),
-                            <NamedArgument<string>>::new("key"),
-                        ),
-                        result: <UnnamedArgument<()>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Get token property value.",
-                            " @dev Throws error if key not found",
-                            " @param tokenId ID of the token.",
-                            " @param key Property key.",
-                            " @return Property value bytes",
-                        ],
-                        selector_str: "property(uint256,string)",
-                        selector: u32::from_be_bytes(Self::PROPERTY),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("property"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                            ),
-                                            (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "property",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<uint256>>::new("tokenId"),
-                            <NamedArgument<string>>::new("key"),
-                        ),
-                        result: <UnnamedArgument<bytes>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "TokenProperties".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for TokenPropertiesCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::SET_TOKEN_PROPERTY_PERMISSION => {
-                    return Ok(
-                        Some(Self::SetTokenPropertyPermission {
-                            key: reader.abi_read()?,
-                            is_mutable: reader.abi_read()?,
-                            collection_admin: reader.abi_read()?,
-                            token_owner: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::SET_PROPERTY => {
-                    return Ok(
-                        Some(Self::SetProperty {
-                            token_id: reader.abi_read()?,
-                            key: reader.abi_read()?,
-                            value: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::DELETE_PROPERTY => {
-                    return Ok(
-                        Some(Self::DeleteProperty {
-                            token_id: reader.abi_read()?,
-                            key: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::PROPERTY => {
-                    return Ok(
-                        Some(Self::Property {
-                            token_id: reader.abi_read()?,
-                            key: reader.abi_read()?,
-                        }),
-                    );
-                }
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> TokenPropertiesCall<T> {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for TokenPropertiesCall<T> {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::SetTokenPropertyPermission { .. } => ().into(),
-                Self::SetProperty { .. } => ().into(),
-                Self::DeleteProperty { .. } => ().into(),
-                Self::Property { .. } => ().into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<TokenPropertiesCall<T>>
-    for NonfungibleHandle<T> {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<TokenPropertiesCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                TokenPropertiesCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<TokenPropertiesCall<
-                                T,
-                            >>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                TokenPropertiesCall::SetTokenPropertyPermission {
-                    key,
-                    is_mutable,
-                    collection_admin,
-                    token_owner,
-                } => {
-                    let result = self
-                        .set_token_property_permission(
-                            c.caller.clone(),
-                            key,
-                            is_mutable,
-                            collection_admin,
-                            token_owner,
-                        )?;
-                    (&result).to_result()
-                }
-                TokenPropertiesCall::SetProperty { token_id, key, value } => {
-                    let result = self
-                        .set_property(c.caller.clone(), token_id, key, value)?;
-                    (&result).to_result()
-                }
-                TokenPropertiesCall::DeleteProperty { token_id, key } => {
-                    let result = self.delete_property(token_id, c.caller.clone(), key)?;
-                    (&result).to_result()
-                }
-                TokenPropertiesCall::Property { token_id, key } => {
-                    let result = self.property(token_id, key)?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    pub enum ERC721Events {
-        /// @dev This emits when ownership of any NFT changes by any mechanism.
-        ///  This event emits when NFTs are created (`from` == 0) and destroyed
-        ///  (`to` == 0). Exception: during contract creation, any number of NFTs
-        ///  may be created and assigned without emitting Transfer. At the time of
-        ///  any transfer, the approved address for that NFT (if any) is reset to none.
-        Transfer {
-            #[indexed]
-            from: address,
-            #[indexed]
-            to: address,
-            #[indexed]
-            token_id: uint256,
-        },
-        /// @dev This emits when the approved address for an NFT is changed or
-        ///  reaffirmed. The zero address indicates there is no approved address.
-        ///  When a Transfer event emits, this also indicates that the approved
-        ///  address for that NFT (if any) is reset to none.
-        Approval {
-            #[indexed]
-            owner: address,
-            #[indexed]
-            approved: address,
-            #[indexed]
-            token_id: uint256,
-        },
-        /// @dev This emits when an operator is enabled or disabled for an owner.
-        ///  The operator can manage all NFTs of the owner.
-        #[allow(dead_code)]
-        ApprovalForAll {
-            #[indexed]
-            owner: address,
-            #[indexed]
-            operator: address,
-            approved: bool,
-        },
-    }
-    impl ERC721Events {
-        ///Transfer(address,address,uint256)
-        const TRANSFER: [u8; 32] = [
-            221u8,
-            242u8,
-            82u8,
-            173u8,
-            27u8,
-            226u8,
-            200u8,
-            155u8,
-            105u8,
-            194u8,
-            176u8,
-            104u8,
-            252u8,
-            55u8,
-            141u8,
-            170u8,
-            149u8,
-            43u8,
-            167u8,
-            241u8,
-            99u8,
-            196u8,
-            161u8,
-            22u8,
-            40u8,
-            245u8,
-            90u8,
-            77u8,
-            245u8,
-            35u8,
-            179u8,
-            239u8,
-        ];
-        ///Approval(address,address,uint256)
-        const APPROVAL: [u8; 32] = [
-            140u8,
-            91u8,
-            225u8,
-            229u8,
-            235u8,
-            236u8,
-            125u8,
-            91u8,
-            209u8,
-            79u8,
-            113u8,
-            66u8,
-            125u8,
-            30u8,
-            132u8,
-            243u8,
-            221u8,
-            3u8,
-            20u8,
-            192u8,
-            247u8,
-            178u8,
-            41u8,
-            30u8,
-            91u8,
-            32u8,
-            10u8,
-            200u8,
-            199u8,
-            195u8,
-            185u8,
-            37u8,
-        ];
-        ///ApprovalForAll(address,address,bool)
-        const APPROVAL_FOR_ALL: [u8; 32] = [
-            23u8,
-            48u8,
-            126u8,
-            171u8,
-            57u8,
-            171u8,
-            97u8,
-            7u8,
-            232u8,
-            137u8,
-            152u8,
-            69u8,
-            173u8,
-            61u8,
-            89u8,
-            189u8,
-            150u8,
-            83u8,
-            242u8,
-            0u8,
-            242u8,
-            32u8,
-            146u8,
-            4u8,
-            137u8,
-            202u8,
-            43u8,
-            89u8,
-            55u8,
-            105u8,
-            108u8,
-            49u8,
-        ];
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[],
-                selector: [0; 4],
-                name: "ERC721Events",
-                is: &[],
-                functions: (
-                    SolidityEvent {
-                        name: "Transfer",
-                        args: (
-                            <SolidityEventArgument<address>>::new(true, "from"),
-                            <SolidityEventArgument<address>>::new(true, "to"),
-                            <SolidityEventArgument<uint256>>::new(true, "tokenId"),
-                        ),
-                    },
-                    SolidityEvent {
-                        name: "Approval",
-                        args: (
-                            <SolidityEventArgument<address>>::new(true, "owner"),
-                            <SolidityEventArgument<address>>::new(true, "approved"),
-                            <SolidityEventArgument<uint256>>::new(true, "tokenId"),
-                        ),
-                    },
-                    SolidityEvent {
-                        name: "ApprovalForAll",
-                        args: (
-                            <SolidityEventArgument<address>>::new(true, "owner"),
-                            <SolidityEventArgument<address>>::new(true, "operator"),
-                            <SolidityEventArgument<bool>>::new(false, "approved"),
-                        ),
-                    },
-                ),
-            };
-            let mut out = string::new();
-            out.push_str("/// @dev inlined interface\n");
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-        }
-    }
-    #[automatically_derived]
-    impl ::evm_coder::events::ToLog for ERC721Events {
-        fn to_log(&self, contract: address) -> ::ethereum::Log {
-            use ::evm_coder::events::ToTopic;
-            use ::evm_coder::abi::AbiWrite;
-            let mut writer = ::evm_coder::abi::AbiWriter::new();
-            let mut topics = Vec::new();
-            match self {
-                Self::Transfer { from, to, token_id } => {
-                    topics.push(topic::from(Self::TRANSFER));
-                    topics.push(from.to_topic());
-                    topics.push(to.to_topic());
-                    topics.push(token_id.to_topic());
-                }
-                Self::Approval { owner, approved, token_id } => {
-                    topics.push(topic::from(Self::APPROVAL));
-                    topics.push(owner.to_topic());
-                    topics.push(approved.to_topic());
-                    topics.push(token_id.to_topic());
-                }
-                Self::ApprovalForAll { owner, operator, approved } => {
-                    topics.push(topic::from(Self::APPROVAL_FOR_ALL));
-                    topics.push(owner.to_topic());
-                    topics.push(operator.to_topic());
-                    approved.abi_write(&mut writer);
-                }
-            }
-            ::ethereum::Log {
-                address: contract,
-                topics,
-                data: writer.finish(),
-            }
-        }
-    }
-    pub enum ERC721MintableEvents {
-        #[allow(dead_code)]
-        MintingFinished {},
-    }
-    impl ERC721MintableEvents {
-        ///MintingFinished()
-        const MINTING_FINISHED: [u8; 32] = [
-            184u8,
-            40u8,
-            217u8,
-            181u8,
-            199u8,
-            128u8,
-            149u8,
-            222u8,
-            238u8,
-            239u8,
-            242u8,
-            236u8,
-            162u8,
-            229u8,
-            212u8,
-            254u8,
-            4u8,
-            108u8,
-            227u8,
-            254u8,
-            180u8,
-            201u8,
-            151u8,
-            2u8,
-            98u8,
-            74u8,
-            63u8,
-            211u8,
-            132u8,
-            173u8,
-            45u8,
-            188u8,
-        ];
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[],
-                selector: [0; 4],
-                name: "ERC721MintableEvents",
-                is: &[],
-                functions: (
-                    SolidityEvent {
-                        name: "MintingFinished",
-                        args: (),
-                    },
-                ),
-            };
-            let mut out = string::new();
-            out.push_str("/// @dev inlined interface\n");
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-        }
-    }
-    #[automatically_derived]
-    impl ::evm_coder::events::ToLog for ERC721MintableEvents {
-        fn to_log(&self, contract: address) -> ::ethereum::Log {
-            use ::evm_coder::events::ToTopic;
-            use ::evm_coder::abi::AbiWrite;
-            let mut writer = ::evm_coder::abi::AbiWriter::new();
-            let mut topics = Vec::new();
-            match self {
-                Self::MintingFinished {} => {
-                    topics.push(topic::from(Self::MINTING_FINISHED));
-                }
-            }
-            ::ethereum::Log {
-                address: contract,
-                topics,
-                data: writer.finish(),
-            }
-        }
-    }
-    /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
-    /// @dev See https://eips.ethereum.org/EIPS/eip-721
-    impl<T: Config> NonfungibleHandle<T> {
-        /// @notice A descriptive name for a collection of NFTs in this contract
-        fn name(&self) -> Result<string> {
-            Ok(
-                decode_utf16(self.name.iter().copied())
-                    .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-                    .collect::<string>(),
-            )
-        }
-        /// @notice An abbreviated name for NFTs in this contract
-        fn symbol(&self) -> Result<string> {
-            Ok(string::from_utf8_lossy(&self.token_prefix).into())
-        }
-        /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
-        ///
-        /// @dev If the token has a `url` property and it is not empty, it is returned.
-        ///  Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
-        ///  If the collection property `baseURI` is empty or absent, return "" (empty string)
-        ///  otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
-        ///  otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
-        ///
-        /// @return token's const_metadata
-        fn token_uri(&self, token_id: uint256) -> Result<string> {
-            let token_id_u32: u32 = token_id
-                .try_into()
-                .map_err(|_| "token id overflow")?;
-            if let Ok(url) = get_token_property(self, token_id_u32, &key::url()) {
-                if !url.is_empty() {
-                    return Ok(url);
-                }
-            } else if !is_erc721_metadata_compatible::<T>(self.id) {
-                return Err("tokenURI not set".into());
-            }
-            if let Some(base_uri)
-                = pallet_common::Pallet::<
-                    T,
-                >::get_collection_property(self.id, &key::base_uri()) {
-                if !base_uri.is_empty() {
-                    let base_uri = string::from_utf8(base_uri.into_inner())
-                        .map_err(|e| {
-                            Error::Revert({
-                                let res = ::alloc::fmt::format(
-                                    ::core::fmt::Arguments::new_v1(
-                                        &[
-                                            "Can not convert value \"baseURI\" to string with error \"",
-                                            "\"",
-                                        ],
-                                        &[::core::fmt::ArgumentV1::new_display(&e)],
-                                    ),
-                                );
-                                res
-                            })
-                        })?;
-                    if let Ok(suffix)
-                        = get_token_property(self, token_id_u32, &key::suffix()) {
-                        if !suffix.is_empty() {
-                            return Ok(base_uri + suffix.as_str());
-                        }
-                    }
-                    return Ok(base_uri + token_id.to_string().as_str());
-                }
-            }
-            Ok("".into())
-        }
-    }
-    /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
-    /// @dev See https://eips.ethereum.org/EIPS/eip-721
-    pub enum ERC721MetadataCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        Name,
-        Symbol,
-        /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
-        ///
-        /// @dev If the token has a `url` property and it is not empty, it is returned.
-        ///  Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
-        ///  If the collection property `baseURI` is empty or absent, return "" (empty string)
-        ///  otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
-        ///  otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
-        ///
-        /// @return token's const_metadata
-        #[allow(missing_docs)]
-        TokenUri { token_id: uint256 },
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721MetadataCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                ERC721MetadataCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                ERC721MetadataCall::Name => ::core::fmt::Formatter::write_str(f, "Name"),
-                ERC721MetadataCall::Symbol => {
-                    ::core::fmt::Formatter::write_str(f, "Symbol")
-                }
-                ERC721MetadataCall::TokenUri { token_id: __self_0 } => {
-                    ::core::fmt::Formatter::debug_struct_field1_finish(
-                        f,
-                        "TokenUri",
-                        "token_id",
-                        &__self_0,
-                    )
-                }
-            }
-        }
-    }
-    impl<T> ERC721MetadataCall<T> {
-        const NAME_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("name"));
-                let fs = FunctionSignature::done(fs, false);
-                fs
-            }
-        };
-        ///name()
-        const NAME: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::NAME_SIGNATURE.signature,
-                    Self::NAME_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const SYMBOL_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("symbol"));
-                let fs = FunctionSignature::done(fs, false);
-                fs
-            }
-        };
-        ///symbol()
-        const SYMBOL: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::SYMBOL_SIGNATURE.signature,
-                    Self::SYMBOL_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const TOKEN_URI_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("tokenURI"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///tokenURI(uint256)
-        const TOKEN_URI: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TOKEN_URI_SIGNATURE.signature,
-                    Self::TOKEN_URI_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::NAME);
-            interface_id ^= u32::from_be_bytes(Self::SYMBOL);
-            interface_id ^= u32::from_be_bytes(Self::TOKEN_URI);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[
-                    " @title ERC-721 Non-Fungible Token Standard, optional metadata extension",
-                    " @dev See https://eips.ethereum.org/EIPS/eip-721",
-                ],
-                name: "ERC721Metadata",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[
-                            " @notice A descriptive name for a collection of NFTs in this contract",
-                        ],
-                        selector_str: "name()",
-                        selector: u32::from_be_bytes(Self::NAME),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("name"),
-                                    );
-                                    let fs = FunctionSignature::done(fs, false);
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "name",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (),
-                        result: <UnnamedArgument<string>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice An abbreviated name for NFTs in this contract",
-                        ],
-                        selector_str: "symbol()",
-                        selector: u32::from_be_bytes(Self::SYMBOL),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("symbol"),
-                                    );
-                                    let fs = FunctionSignature::done(fs, false);
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "symbol",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (),
-                        result: <UnnamedArgument<string>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice A distinct Uniform Resource Identifier (URI) for a given asset.",
-                            "",
-                            " @dev If the token has a `url` property and it is not empty, it is returned.",
-                            "  Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.",
-                            "  If the collection property `baseURI` is empty or absent, return \"\" (empty string)",
-                            "  otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix",
-                            "  otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).",
-                            "",
-                            " @return token's const_metadata",
-                        ],
-                        selector_str: "tokenURI(uint256)",
-                        selector: u32::from_be_bytes(Self::TOKEN_URI),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("tokenURI"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "tokenURI",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (<NamedArgument<uint256>>::new("tokenId"),),
-                        result: <UnnamedArgument<string>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "ERC721Metadata".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for ERC721MetadataCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::NAME => return Ok(Some(Self::Name)),
-                Self::SYMBOL => return Ok(Some(Self::Symbol)),
-                Self::TOKEN_URI => {
-                    return Ok(
-                        Some(Self::TokenUri {
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> ERC721MetadataCall<T> {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for ERC721MetadataCall<T> {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::Name => ().into(),
-                Self::Symbol => ().into(),
-                Self::TokenUri { .. } => ().into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<ERC721MetadataCall<T>>
-    for NonfungibleHandle<T> {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<ERC721MetadataCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                ERC721MetadataCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<ERC721MetadataCall<
-                                T,
-                            >>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                ERC721MetadataCall::Name => {
-                    let result = self.name()?;
-                    (&result).to_result()
-                }
-                ERC721MetadataCall::Symbol => {
-                    let result = self.symbol()?;
-                    (&result).to_result()
-                }
-                ERC721MetadataCall::TokenUri { token_id } => {
-                    let result = self.token_uri(token_id)?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
-    /// @dev See https://eips.ethereum.org/EIPS/eip-721
-    impl<T: Config> NonfungibleHandle<T> {
-        /// @notice Enumerate valid NFTs
-        /// @param index A counter less than `totalSupply()`
-        /// @return The token identifier for the `index`th NFT,
-        ///  (sort order not specified)
-        fn token_by_index(&self, index: uint256) -> Result<uint256> {
-            Ok(index)
-        }
-        /// @dev Not implemented
-        fn token_of_owner_by_index(
-            &self,
-            _owner: address,
-            _index: uint256,
-        ) -> Result<uint256> {
-            Err("not implemented".into())
-        }
-        /// @notice Count NFTs tracked by this contract
-        /// @return A count of valid NFTs tracked by this contract, where each one of
-        ///  them has an assigned and queryable owner not equal to the zero address
-        fn total_supply(&self) -> Result<uint256> {
-            self.consume_store_reads(1)?;
-            Ok(<Pallet<T>>::total_supply(self).into())
-        }
-    }
-    /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
-    /// @dev See https://eips.ethereum.org/EIPS/eip-721
-    pub enum ERC721EnumerableCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        /// @notice Enumerate valid NFTs
-        /// @param index A counter less than `totalSupply()`
-        /// @return The token identifier for the `index`th NFT,
-        ///  (sort order not specified)
-        #[allow(missing_docs)]
-        TokenByIndex { index: uint256 },
-        /// @dev Not implemented
-        #[allow(missing_docs)]
-        TokenOfOwnerByIndex { _owner: address, _index: uint256 },
-        TotalSupply,
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721EnumerableCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                ERC721EnumerableCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                ERC721EnumerableCall::TokenByIndex { index: __self_0 } => {
-                    ::core::fmt::Formatter::debug_struct_field1_finish(
-                        f,
-                        "TokenByIndex",
-                        "index",
-                        &__self_0,
-                    )
-                }
-                ERC721EnumerableCall::TokenOfOwnerByIndex {
-                    _owner: __self_0,
-                    _index: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "TokenOfOwnerByIndex",
-                        "_owner",
-                        &__self_0,
-                        "_index",
-                        &__self_1,
-                    )
-                }
-                ERC721EnumerableCall::TotalSupply => {
-                    ::core::fmt::Formatter::write_str(f, "TotalSupply")
-                }
-            }
-        }
-    }
-    impl<T> ERC721EnumerableCall<T> {
-        const TOKEN_BY_INDEX_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("tokenByIndex"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///tokenByIndex(uint256)
-        const TOKEN_BY_INDEX: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TOKEN_BY_INDEX_SIGNATURE.signature,
-                    Self::TOKEN_BY_INDEX_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const TOKEN_OF_OWNER_BY_INDEX_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(
-                    &&FunctionName::new("tokenOfOwnerByIndex"),
-                );
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///tokenOfOwnerByIndex(address,uint256)
-        const TOKEN_OF_OWNER_BY_INDEX: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TOKEN_OF_OWNER_BY_INDEX_SIGNATURE.signature,
-                    Self::TOKEN_OF_OWNER_BY_INDEX_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const TOTAL_SUPPLY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("totalSupply"));
-                let fs = FunctionSignature::done(fs, false);
-                fs
-            }
-        };
-        ///totalSupply()
-        const TOTAL_SUPPLY: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TOTAL_SUPPLY_SIGNATURE.signature,
-                    Self::TOTAL_SUPPLY_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::TOKEN_BY_INDEX);
-            interface_id ^= u32::from_be_bytes(Self::TOKEN_OF_OWNER_BY_INDEX);
-            interface_id ^= u32::from_be_bytes(Self::TOTAL_SUPPLY);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[
-                    " @title ERC-721 Non-Fungible Token Standard, optional enumeration extension",
-                    " @dev See https://eips.ethereum.org/EIPS/eip-721",
-                ],
-                name: "ERC721Enumerable",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Enumerate valid NFTs",
-                            " @param index A counter less than `totalSupply()`",
-                            " @return The token identifier for the `index`th NFT,",
-                            "  (sort order not specified)",
-                        ],
-                        selector_str: "tokenByIndex(uint256)",
-                        selector: u32::from_be_bytes(Self::TOKEN_BY_INDEX),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("tokenByIndex"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "tokenByIndex",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (<NamedArgument<uint256>>::new("index"),),
-                        result: <UnnamedArgument<uint256>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "tokenOfOwnerByIndex(address,uint256)",
-                        selector: u32::from_be_bytes(Self::TOKEN_OF_OWNER_BY_INDEX),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("tokenOfOwnerByIndex"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "tokenOfOwnerByIndex",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("owner"),
-                            <NamedArgument<uint256>>::new("index"),
-                        ),
-                        result: <UnnamedArgument<uint256>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Count NFTs tracked by this contract",
-                            " @return A count of valid NFTs tracked by this contract, where each one of",
-                            "  them has an assigned and queryable owner not equal to the zero address",
-                        ],
-                        selector_str: "totalSupply()",
-                        selector: u32::from_be_bytes(Self::TOTAL_SUPPLY),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("totalSupply"),
-                                    );
-                                    let fs = FunctionSignature::done(fs, false);
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "totalSupply",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (),
-                        result: <UnnamedArgument<uint256>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "ERC721Enumerable".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for ERC721EnumerableCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::TOKEN_BY_INDEX => {
-                    return Ok(
-                        Some(Self::TokenByIndex {
-                            index: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::TOKEN_OF_OWNER_BY_INDEX => {
-                    return Ok(
-                        Some(Self::TokenOfOwnerByIndex {
-                            _owner: reader.abi_read()?,
-                            _index: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::TOTAL_SUPPLY => return Ok(Some(Self::TotalSupply)),
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> ERC721EnumerableCall<T> {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for ERC721EnumerableCall<T> {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::TokenByIndex { .. } => ().into(),
-                Self::TokenOfOwnerByIndex { .. } => ().into(),
-                Self::TotalSupply => ().into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<ERC721EnumerableCall<T>>
-    for NonfungibleHandle<T> {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<ERC721EnumerableCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                ERC721EnumerableCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<ERC721EnumerableCall<
-                                T,
-                            >>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                ERC721EnumerableCall::TokenByIndex { index } => {
-                    let result = self.token_by_index(index)?;
-                    (&result).to_result()
-                }
-                ERC721EnumerableCall::TokenOfOwnerByIndex { _owner, _index } => {
-                    let result = self.token_of_owner_by_index(_owner, _index)?;
-                    (&result).to_result()
-                }
-                ERC721EnumerableCall::TotalSupply => {
-                    let result = self.total_supply()?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    /// @title ERC-721 Non-Fungible Token Standard
-    /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
-    impl<T: Config> NonfungibleHandle<T> {
-        /// @notice Count all NFTs assigned to an owner
-        /// @dev NFTs assigned to the zero address are considered invalid, and this
-        ///  function throws for queries about the zero address.
-        /// @param owner An address for whom to query the balance
-        /// @return The number of NFTs owned by `owner`, possibly zero
-        fn balance_of(&self, owner: address) -> Result<uint256> {
-            self.consume_store_reads(1)?;
-            let owner = T::CrossAccountId::from_eth(owner);
-            let balance = <AccountBalance<T>>::get((self.id, owner));
-            Ok(balance.into())
-        }
-        /// @notice Find the owner of an NFT
-        /// @dev NFTs assigned to zero address are considered invalid, and queries
-        ///  about them do throw.
-        /// @param tokenId The identifier for an NFT
-        /// @return The address of the owner of the NFT
-        fn owner_of(&self, token_id: uint256) -> Result<address> {
-            self.consume_store_reads(1)?;
-            let token: TokenId = token_id.try_into()?;
-            Ok(
-                *<TokenData<T>>::get((self.id, token))
-                    .ok_or("token not found")?
-                    .owner
-                    .as_eth(),
-            )
-        }
-        /// @dev Not implemented
-        fn safe_transfer_from_with_data(
-            &mut self,
-            _from: address,
-            _to: address,
-            _token_id: uint256,
-            _data: bytes,
-        ) -> Result<void> {
-            Err("not implemented".into())
-        }
-        /// @dev Not implemented
-        fn safe_transfer_from(
-            &mut self,
-            _from: address,
-            _to: address,
-            _token_id: uint256,
-        ) -> Result<void> {
-            Err("not implemented".into())
-        }
-        /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
-        ///  TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
-        ///  THEY MAY BE PERMANENTLY LOST
-        /// @dev Throws unless `msg.sender` is the current owner or an authorized
-        ///  operator for this NFT. Throws if `from` is not the current owner. Throws
-        ///  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from The current owner of the NFT
-        /// @param to The new owner
-        /// @param tokenId The NFT to transfer
-        fn transfer_from(
-            &mut self,
-            caller: caller,
-            from: address,
-            to: address,
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let from = T::CrossAccountId::from_eth(from);
-            let to = T::CrossAccountId::from_eth(to);
-            let token = token_id.try_into()?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            <Pallet<T>>::transfer_from(self, &caller, &from, &to, token, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @notice Set or reaffirm the approved address for an NFT
-        /// @dev The zero address indicates there is no approved address.
-        /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
-        ///  operator of the current owner.
-        /// @param approved The new approved NFT controller
-        /// @param tokenId The NFT to approve
-        fn approve(
-            &mut self,
-            caller: caller,
-            approved: address,
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let approved = T::CrossAccountId::from_eth(approved);
-            let token = token_id.try_into()?;
-            <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @dev Not implemented
-        fn set_approval_for_all(
-            &mut self,
-            _caller: caller,
-            _operator: address,
-            _approved: bool,
-        ) -> Result<void> {
-            Err("not implemented".into())
-        }
-        /// @dev Not implemented
-        fn get_approved(&self, _token_id: uint256) -> Result<address> {
-            Err("not implemented".into())
-        }
-        /// @dev Not implemented
-        fn is_approved_for_all(
-            &self,
-            _owner: address,
-            _operator: address,
-        ) -> Result<address> {
-            Err("not implemented".into())
-        }
-    }
-    /// @title ERC-721 Non-Fungible Token Standard
-    /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
-    pub enum ERC721Call<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        /// @notice Count all NFTs assigned to an owner
-        /// @dev NFTs assigned to the zero address are considered invalid, and this
-        ///  function throws for queries about the zero address.
-        /// @param owner An address for whom to query the balance
-        /// @return The number of NFTs owned by `owner`, possibly zero
-        #[allow(missing_docs)]
-        BalanceOf { owner: address },
-        /// @notice Find the owner of an NFT
-        /// @dev NFTs assigned to zero address are considered invalid, and queries
-        ///  about them do throw.
-        /// @param tokenId The identifier for an NFT
-        /// @return The address of the owner of the NFT
-        #[allow(missing_docs)]
-        OwnerOf { token_id: uint256 },
-        /// @dev Not implemented
-        #[allow(missing_docs)]
-        SafeTransferFromWithData {
-            _from: address,
-            _to: address,
-            _token_id: uint256,
-            _data: bytes,
-        },
-        /// @dev Not implemented
-        #[allow(missing_docs)]
-        SafeTransferFrom { _from: address, _to: address, _token_id: uint256 },
-        /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
-        ///  TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
-        ///  THEY MAY BE PERMANENTLY LOST
-        /// @dev Throws unless `msg.sender` is the current owner or an authorized
-        ///  operator for this NFT. Throws if `from` is not the current owner. Throws
-        ///  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from The current owner of the NFT
-        /// @param to The new owner
-        /// @param tokenId The NFT to transfer
-        #[allow(missing_docs)]
-        TransferFrom { from: address, to: address, token_id: uint256 },
-        /// @notice Set or reaffirm the approved address for an NFT
-        /// @dev The zero address indicates there is no approved address.
-        /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
-        ///  operator of the current owner.
-        /// @param approved The new approved NFT controller
-        /// @param tokenId The NFT to approve
-        #[allow(missing_docs)]
-        Approve { approved: address, token_id: uint256 },
-        /// @dev Not implemented
-        #[allow(missing_docs)]
-        SetApprovalForAll { _operator: address, _approved: bool },
-        /// @dev Not implemented
-        #[allow(missing_docs)]
-        GetApproved { _token_id: uint256 },
-        /// @dev Not implemented
-        #[allow(missing_docs)]
-        IsApprovedForAll { _owner: address, _operator: address },
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721Call<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                ERC721Call::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                ERC721Call::BalanceOf { owner: __self_0 } => {
-                    ::core::fmt::Formatter::debug_struct_field1_finish(
-                        f,
-                        "BalanceOf",
-                        "owner",
-                        &__self_0,
-                    )
-                }
-                ERC721Call::OwnerOf { token_id: __self_0 } => {
-                    ::core::fmt::Formatter::debug_struct_field1_finish(
-                        f,
-                        "OwnerOf",
-                        "token_id",
-                        &__self_0,
-                    )
-                }
-                ERC721Call::SafeTransferFromWithData {
-                    _from: __self_0,
-                    _to: __self_1,
-                    _token_id: __self_2,
-                    _data: __self_3,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field4_finish(
-                        f,
-                        "SafeTransferFromWithData",
-                        "_from",
-                        &__self_0,
-                        "_to",
-                        &__self_1,
-                        "_token_id",
-                        &__self_2,
-                        "_data",
-                        &__self_3,
-                    )
-                }
-                ERC721Call::SafeTransferFrom {
-                    _from: __self_0,
-                    _to: __self_1,
-                    _token_id: __self_2,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field3_finish(
-                        f,
-                        "SafeTransferFrom",
-                        "_from",
-                        &__self_0,
-                        "_to",
-                        &__self_1,
-                        "_token_id",
-                        &__self_2,
-                    )
-                }
-                ERC721Call::TransferFrom {
-                    from: __self_0,
-                    to: __self_1,
-                    token_id: __self_2,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field3_finish(
-                        f,
-                        "TransferFrom",
-                        "from",
-                        &__self_0,
-                        "to",
-                        &__self_1,
-                        "token_id",
-                        &__self_2,
-                    )
-                }
-                ERC721Call::Approve { approved: __self_0, token_id: __self_1 } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "Approve",
-                        "approved",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                    )
-                }
-                ERC721Call::SetApprovalForAll {
-                    _operator: __self_0,
-                    _approved: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "SetApprovalForAll",
-                        "_operator",
-                        &__self_0,
-                        "_approved",
-                        &__self_1,
-                    )
-                }
-                ERC721Call::GetApproved { _token_id: __self_0 } => {
-                    ::core::fmt::Formatter::debug_struct_field1_finish(
-                        f,
-                        "GetApproved",
-                        "_token_id",
-                        &__self_0,
-                    )
-                }
-                ERC721Call::IsApprovedForAll {
-                    _owner: __self_0,
-                    _operator: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "IsApprovedForAll",
-                        "_owner",
-                        &__self_0,
-                        "_operator",
-                        &__self_1,
-                    )
-                }
-            }
-        }
-    }
-    impl<T> ERC721Call<T> {
-        const BALANCE_OF_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("balanceOf"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///balanceOf(address)
-        const BALANCE_OF: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::BALANCE_OF_SIGNATURE.signature,
-                    Self::BALANCE_OF_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const OWNER_OF_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("ownerOf"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///ownerOf(uint256)
-        const OWNER_OF: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::OWNER_OF_SIGNATURE.signature,
-                    Self::OWNER_OF_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const SAFE_TRANSFER_FROM_WITH_DATA_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("safeTransferFrom"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                FunctionSignature::add_param(
-                                    fs,
-                                    (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                ),
-                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                            ),
-                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                        ),
-                        (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///safeTransferFrom(address,address,uint256,bytes)
-        const SAFE_TRANSFER_FROM_WITH_DATA: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::SAFE_TRANSFER_FROM_WITH_DATA_SIGNATURE.signature,
-                    Self::SAFE_TRANSFER_FROM_WITH_DATA_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const SAFE_TRANSFER_FROM_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("safeTransferFrom"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                fs,
-                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                            ),
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///safeTransferFrom(address,address,uint256)
-        const SAFE_TRANSFER_FROM: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::SAFE_TRANSFER_FROM_SIGNATURE.signature,
-                    Self::SAFE_TRANSFER_FROM_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const TRANSFER_FROM_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("transferFrom"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                fs,
-                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                            ),
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///transferFrom(address,address,uint256)
-        const TRANSFER_FROM: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TRANSFER_FROM_SIGNATURE.signature,
-                    Self::TRANSFER_FROM_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const APPROVE_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("approve"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///approve(address,uint256)
-        const APPROVE: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::APPROVE_SIGNATURE.signature,
-                    Self::APPROVE_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const SET_APPROVAL_FOR_ALL_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(
-                    &&FunctionName::new("setApprovalForAll"),
-                );
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///setApprovalForAll(address,bool)
-        const SET_APPROVAL_FOR_ALL: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::SET_APPROVAL_FOR_ALL_SIGNATURE.signature,
-                    Self::SET_APPROVAL_FOR_ALL_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const GET_APPROVED_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("getApproved"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///getApproved(uint256)
-        const GET_APPROVED: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::GET_APPROVED_SIGNATURE.signature,
-                    Self::GET_APPROVED_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const IS_APPROVED_FOR_ALL_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("isApprovedForAll"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///isApprovedForAll(address,address)
-        const IS_APPROVED_FOR_ALL: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::IS_APPROVED_FOR_ALL_SIGNATURE.signature,
-                    Self::IS_APPROVED_FOR_ALL_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::BALANCE_OF);
-            interface_id ^= u32::from_be_bytes(Self::OWNER_OF);
-            interface_id ^= u32::from_be_bytes(Self::SAFE_TRANSFER_FROM_WITH_DATA);
-            interface_id ^= u32::from_be_bytes(Self::SAFE_TRANSFER_FROM);
-            interface_id ^= u32::from_be_bytes(Self::TRANSFER_FROM);
-            interface_id ^= u32::from_be_bytes(Self::APPROVE);
-            interface_id ^= u32::from_be_bytes(Self::SET_APPROVAL_FOR_ALL);
-            interface_id ^= u32::from_be_bytes(Self::GET_APPROVED);
-            interface_id ^= u32::from_be_bytes(Self::IS_APPROVED_FOR_ALL);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[
-                    " @title ERC-721 Non-Fungible Token Standard",
-                    " @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md",
-                ],
-                name: "ERC721",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165", "ERC721Events"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Count all NFTs assigned to an owner",
-                            " @dev NFTs assigned to the zero address are considered invalid, and this",
-                            "  function throws for queries about the zero address.",
-                            " @param owner An address for whom to query the balance",
-                            " @return The number of NFTs owned by `owner`, possibly zero",
-                        ],
-                        selector_str: "balanceOf(address)",
-                        selector: u32::from_be_bytes(Self::BALANCE_OF),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("balanceOf"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "balanceOf",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (<NamedArgument<address>>::new("owner"),),
-                        result: <UnnamedArgument<uint256>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Find the owner of an NFT",
-                            " @dev NFTs assigned to zero address are considered invalid, and queries",
-                            "  about them do throw.",
-                            " @param tokenId The identifier for an NFT",
-                            " @return The address of the owner of the NFT",
-                        ],
-                        selector_str: "ownerOf(uint256)",
-                        selector: u32::from_be_bytes(Self::OWNER_OF),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("ownerOf"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "ownerOf",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (<NamedArgument<uint256>>::new("tokenId"),),
-                        result: <UnnamedArgument<address>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "safeTransferFrom(address,address,uint256,bytes)",
-                        selector: u32::from_be_bytes(Self::SAFE_TRANSFER_FROM_WITH_DATA),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("safeTransferFrom"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    FunctionSignature::add_param(
-                                                        fs,
-                                                        (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                                    ),
-                                                    (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                                ),
-                                                (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                            ),
-                                            (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "safeTransferFrom",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("from"),
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                            <NamedArgument<bytes>>::new("data"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "safeTransferFrom(address,address,uint256)",
-                        selector: u32::from_be_bytes(Self::SAFE_TRANSFER_FROM),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("safeTransferFrom"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    fs,
-                                                    (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                                ),
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "safeTransferFrom",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("from"),
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE",
-                            "  TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE",
-                            "  THEY MAY BE PERMANENTLY LOST",
-                            " @dev Throws unless `msg.sender` is the current owner or an authorized",
-                            "  operator for this NFT. Throws if `from` is not the current owner. Throws",
-                            "  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.",
-                            " @param from The current owner of the NFT",
-                            " @param to The new owner",
-                            " @param tokenId The NFT to transfer",
-                        ],
-                        selector_str: "transferFrom(address,address,uint256)",
-                        selector: u32::from_be_bytes(Self::TRANSFER_FROM),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("transferFrom"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    fs,
-                                                    (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                                ),
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "transferFrom",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("from"),
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Set or reaffirm the approved address for an NFT",
-                            " @dev The zero address indicates there is no approved address.",
-                            " @dev Throws unless `msg.sender` is the current NFT owner, or an authorized",
-                            "  operator of the current owner.",
-                            " @param approved The new approved NFT controller",
-                            " @param tokenId The NFT to approve",
-                        ],
-                        selector_str: "approve(address,uint256)",
-                        selector: u32::from_be_bytes(Self::APPROVE),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("approve"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "approve",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("approved"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "setApprovalForAll(address,bool)",
-                        selector: u32::from_be_bytes(Self::SET_APPROVAL_FOR_ALL),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("setApprovalForAll"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "setApprovalForAll",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("operator"),
-                            <NamedArgument<bool>>::new("approved"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "getApproved(uint256)",
-                        selector: u32::from_be_bytes(Self::GET_APPROVED),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("getApproved"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "getApproved",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (<NamedArgument<uint256>>::new("tokenId"),),
-                        result: <UnnamedArgument<address>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "isApprovedForAll(address,address)",
-                        selector: u32::from_be_bytes(Self::IS_APPROVED_FOR_ALL),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("isApprovedForAll"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "isApprovedForAll",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("owner"),
-                            <NamedArgument<address>>::new("operator"),
-                        ),
-                        result: <UnnamedArgument<address>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "ERC721".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            ERC721Events::generate_solidity_interface(tc, is_impl);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for ERC721Call<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::BALANCE_OF => {
-                    return Ok(
-                        Some(Self::BalanceOf {
-                            owner: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::OWNER_OF => {
-                    return Ok(
-                        Some(Self::OwnerOf {
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::SAFE_TRANSFER_FROM_WITH_DATA => {
-                    return Ok(
-                        Some(Self::SafeTransferFromWithData {
-                            _from: reader.abi_read()?,
-                            _to: reader.abi_read()?,
-                            _token_id: reader.abi_read()?,
-                            _data: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::SAFE_TRANSFER_FROM => {
-                    return Ok(
-                        Some(Self::SafeTransferFrom {
-                            _from: reader.abi_read()?,
-                            _to: reader.abi_read()?,
-                            _token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::TRANSFER_FROM => {
-                    return Ok(
-                        Some(Self::TransferFrom {
-                            from: reader.abi_read()?,
-                            to: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::APPROVE => {
-                    return Ok(
-                        Some(Self::Approve {
-                            approved: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::SET_APPROVAL_FOR_ALL => {
-                    return Ok(
-                        Some(Self::SetApprovalForAll {
-                            _operator: reader.abi_read()?,
-                            _approved: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::GET_APPROVED => {
-                    return Ok(
-                        Some(Self::GetApproved {
-                            _token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::IS_APPROVED_FOR_ALL => {
-                    return Ok(
-                        Some(Self::IsApprovedForAll {
-                            _owner: reader.abi_read()?,
-                            _operator: reader.abi_read()?,
-                        }),
-                    );
-                }
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> ERC721Call<T> {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for ERC721Call<T> {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::BalanceOf { .. } => ().into(),
-                Self::OwnerOf { .. } => ().into(),
-                Self::SafeTransferFromWithData { .. } => ().into(),
-                Self::SafeTransferFrom { .. } => ().into(),
-                Self::TransferFrom { from, to, token_id } => {
-                    (<SelfWeightOf<T>>::transfer_from()).into()
-                }
-                Self::Approve { approved, token_id } => {
-                    (<SelfWeightOf<T>>::approve()).into()
-                }
-                Self::SetApprovalForAll { .. } => ().into(),
-                Self::GetApproved { .. } => ().into(),
-                Self::IsApprovedForAll { .. } => ().into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<ERC721Call<T>> for NonfungibleHandle<T> {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<ERC721Call<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                ERC721Call::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(&<ERC721Call<T>>::supports_interface(self, interface_id));
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                ERC721Call::BalanceOf { owner } => {
-                    let result = self.balance_of(owner)?;
-                    (&result).to_result()
-                }
-                ERC721Call::OwnerOf { token_id } => {
-                    let result = self.owner_of(token_id)?;
-                    (&result).to_result()
-                }
-                ERC721Call::SafeTransferFromWithData {
-                    _from,
-                    _to,
-                    _token_id,
-                    _data,
-                } => {
-                    let result = self
-                        .safe_transfer_from_with_data(_from, _to, _token_id, _data)?;
-                    (&result).to_result()
-                }
-                ERC721Call::SafeTransferFrom { _from, _to, _token_id } => {
-                    let result = self.safe_transfer_from(_from, _to, _token_id)?;
-                    (&result).to_result()
-                }
-                ERC721Call::TransferFrom { from, to, token_id } => {
-                    let result = self
-                        .transfer_from(c.caller.clone(), from, to, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721Call::Approve { approved, token_id } => {
-                    let result = self.approve(c.caller.clone(), approved, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721Call::SetApprovalForAll { _operator, _approved } => {
-                    let result = self
-                        .set_approval_for_all(c.caller.clone(), _operator, _approved)?;
-                    (&result).to_result()
-                }
-                ERC721Call::GetApproved { _token_id } => {
-                    let result = self.get_approved(_token_id)?;
-                    (&result).to_result()
-                }
-                ERC721Call::IsApprovedForAll { _owner, _operator } => {
-                    let result = self.is_approved_for_all(_owner, _operator)?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    /// @title ERC721 Token that can be irreversibly burned (destroyed).
-    impl<T: Config> NonfungibleHandle<T> {
-        /// @notice Burns a specific ERC721 token.
-        /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
-        ///  operator of the current owner.
-        /// @param tokenId The NFT to approve
-        fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let token = token_id.try_into()?;
-            <Pallet<T>>::burn(self, &caller, token).map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-    }
-    /// @title ERC721 Token that can be irreversibly burned (destroyed).
-    pub enum ERC721BurnableCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        /// @notice Burns a specific ERC721 token.
-        /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
-        ///  operator of the current owner.
-        /// @param tokenId The NFT to approve
-        #[allow(missing_docs)]
-        Burn { token_id: uint256 },
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721BurnableCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                ERC721BurnableCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                ERC721BurnableCall::Burn { token_id: __self_0 } => {
-                    ::core::fmt::Formatter::debug_struct_field1_finish(
-                        f,
-                        "Burn",
-                        "token_id",
-                        &__self_0,
-                    )
-                }
-            }
-        }
-    }
-    impl<T> ERC721BurnableCall<T> {
-        const BURN_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("burn"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///burn(uint256)
-        const BURN: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::BURN_SIGNATURE.signature,
-                    Self::BURN_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::BURN);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[
-                    " @title ERC721 Token that can be irreversibly burned (destroyed).",
-                ],
-                name: "ERC721Burnable",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Burns a specific ERC721 token.",
-                            " @dev Throws unless `msg.sender` is the current NFT owner, or an authorized",
-                            "  operator of the current owner.",
-                            " @param tokenId The NFT to approve",
-                        ],
-                        selector_str: "burn(uint256)",
-                        selector: u32::from_be_bytes(Self::BURN),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("burn"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "burn",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (<NamedArgument<uint256>>::new("tokenId"),),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "ERC721Burnable".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for ERC721BurnableCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::BURN => {
-                    return Ok(
-                        Some(Self::Burn {
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> ERC721BurnableCall<T> {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for ERC721BurnableCall<T> {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::Burn { token_id } => (<SelfWeightOf<T>>::burn_item()).into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<ERC721BurnableCall<T>>
-    for NonfungibleHandle<T> {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<ERC721BurnableCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                ERC721BurnableCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<ERC721BurnableCall<
-                                T,
-                            >>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                ERC721BurnableCall::Burn { token_id } => {
-                    let result = self.burn(c.caller.clone(), token_id)?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    /// @title ERC721 minting logic.
-    impl<T: Config> NonfungibleHandle<T> {
-        fn minting_finished(&self) -> Result<bool> {
-            Ok(false)
-        }
-        /// @notice Function to mint token.
-        /// @dev `tokenId` should be obtained with `nextTokenId` method,
-        ///  unlike standard, you can't specify it manually
-        /// @param to The new owner
-        /// @param tokenId ID of the minted NFT
-        fn mint(
-            &mut self,
-            caller: caller,
-            to: address,
-            token_id: uint256,
-        ) -> Result<bool> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let to = T::CrossAccountId::from_eth(to);
-            let token_id: u32 = token_id.try_into()?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            if <TokensMinted<T>>::get(self.id).checked_add(1).ok_or("item id overflow")?
-                != token_id
-            {
-                return Err("item id should be next".into());
-            }
-            <Pallet<
-                T,
-            >>::create_item(
-                    self,
-                    &caller,
-                    CreateItemData::<T> {
-                        properties: BoundedVec::default(),
-                        owner: to,
-                    },
-                    &budget,
-                )
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(true)
-        }
-        /// @notice Function to mint token with the given tokenUri.
-        /// @dev `tokenId` should be obtained with `nextTokenId` method,
-        ///  unlike standard, you can't specify it manually
-        /// @param to The new owner
-        /// @param tokenId ID of the minted NFT
-        /// @param tokenUri Token URI that would be stored in the NFT properties
-        fn mint_with_token_uri(
-            &mut self,
-            caller: caller,
-            to: address,
-            token_id: uint256,
-            token_uri: string,
-        ) -> Result<bool> {
-            let key = key::url();
-            let permission = get_token_permission::<T>(self.id, &key)?;
-            if !permission.collection_admin {
-                return Err("Operation is not allowed".into());
-            }
-            let caller = T::CrossAccountId::from_eth(caller);
-            let to = T::CrossAccountId::from_eth(to);
-            let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            if <TokensMinted<T>>::get(self.id).checked_add(1).ok_or("item id overflow")?
-                != token_id
-            {
-                return Err("item id should be next".into());
-            }
-            let mut properties = CollectionPropertiesVec::default();
-            properties
-                .try_push(Property {
-                    key,
-                    value: token_uri
-                        .into_bytes()
-                        .try_into()
-                        .map_err(|_| "token uri is too long")?,
-                })
-                .map_err(|e| Error::Revert({
-                    let res = ::alloc::fmt::format(
-                        ::core::fmt::Arguments::new_v1(
-                            &["Can\'t add property: "],
-                            &[::core::fmt::ArgumentV1::new_debug(&e)],
-                        ),
-                    );
-                    res
-                }))?;
-            <Pallet<
-                T,
-            >>::create_item(
-                    self,
-                    &caller,
-                    CreateItemData::<T> {
-                        properties,
-                        owner: to,
-                    },
-                    &budget,
-                )
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(true)
-        }
-        /// @dev Not implemented
-        fn finish_minting(&mut self, _caller: caller) -> Result<bool> {
-            Err("not implementable".into())
-        }
-    }
-    /// @title ERC721 minting logic.
-    pub enum ERC721MintableCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        MintingFinished,
-        /// @notice Function to mint token.
-        /// @dev `tokenId` should be obtained with `nextTokenId` method,
-        ///  unlike standard, you can't specify it manually
-        /// @param to The new owner
-        /// @param tokenId ID of the minted NFT
-        #[allow(missing_docs)]
-        Mint { to: address, token_id: uint256 },
-        /// @notice Function to mint token with the given tokenUri.
-        /// @dev `tokenId` should be obtained with `nextTokenId` method,
-        ///  unlike standard, you can't specify it manually
-        /// @param to The new owner
-        /// @param tokenId ID of the minted NFT
-        /// @param tokenUri Token URI that would be stored in the NFT properties
-        #[allow(missing_docs)]
-        MintWithTokenUri { to: address, token_id: uint256, token_uri: string },
-        FinishMinting,
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721MintableCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                ERC721MintableCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                ERC721MintableCall::MintingFinished => {
-                    ::core::fmt::Formatter::write_str(f, "MintingFinished")
-                }
-                ERC721MintableCall::Mint { to: __self_0, token_id: __self_1 } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "Mint",
-                        "to",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                    )
-                }
-                ERC721MintableCall::MintWithTokenUri {
-                    to: __self_0,
-                    token_id: __self_1,
-                    token_uri: __self_2,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field3_finish(
-                        f,
-                        "MintWithTokenUri",
-                        "to",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                        "token_uri",
-                        &__self_2,
-                    )
-                }
-                ERC721MintableCall::FinishMinting => {
-                    ::core::fmt::Formatter::write_str(f, "FinishMinting")
-                }
-            }
-        }
-    }
-    impl<T> ERC721MintableCall<T> {
-        const MINTING_FINISHED_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("mintingFinished"));
-                let fs = FunctionSignature::done(fs, false);
-                fs
-            }
-        };
-        ///mintingFinished()
-        const MINTING_FINISHED: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::MINTING_FINISHED_SIGNATURE.signature,
-                    Self::MINTING_FINISHED_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const MINT_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("mint"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///mint(address,uint256)
-        const MINT: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::MINT_SIGNATURE.signature,
-                    Self::MINT_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const MINT_WITH_TOKEN_URI_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("mintWithTokenURI"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                fs,
-                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                            ),
-                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                        ),
-                        (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///mintWithTokenURI(address,uint256,string)
-        const MINT_WITH_TOKEN_URI: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::MINT_WITH_TOKEN_URI_SIGNATURE.signature,
-                    Self::MINT_WITH_TOKEN_URI_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const FINISH_MINTING_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("finishMinting"));
-                let fs = FunctionSignature::done(fs, false);
-                fs
-            }
-        };
-        ///finishMinting()
-        const FINISH_MINTING: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::FINISH_MINTING_SIGNATURE.signature,
-                    Self::FINISH_MINTING_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::MINTING_FINISHED);
-            interface_id ^= u32::from_be_bytes(Self::MINT);
-            interface_id ^= u32::from_be_bytes(Self::MINT_WITH_TOKEN_URI);
-            interface_id ^= u32::from_be_bytes(Self::FINISH_MINTING);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[" @title ERC721 minting logic."],
-                name: "ERC721Mintable",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165", "ERC721MintableEvents"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[],
-                        selector_str: "mintingFinished()",
-                        selector: u32::from_be_bytes(Self::MINTING_FINISHED),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("mintingFinished"),
-                                    );
-                                    let fs = FunctionSignature::done(fs, false);
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "mintingFinished",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (),
-                        result: <UnnamedArgument<bool>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Function to mint token.",
-                            " @dev `tokenId` should be obtained with `nextTokenId` method,",
-                            "  unlike standard, you can't specify it manually",
-                            " @param to The new owner",
-                            " @param tokenId ID of the minted NFT",
-                        ],
-                        selector_str: "mint(address,uint256)",
-                        selector: u32::from_be_bytes(Self::MINT),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("mint"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "mint",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<bool>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Function to mint token with the given tokenUri.",
-                            " @dev `tokenId` should be obtained with `nextTokenId` method,",
-                            "  unlike standard, you can't specify it manually",
-                            " @param to The new owner",
-                            " @param tokenId ID of the minted NFT",
-                            " @param tokenUri Token URI that would be stored in the NFT properties",
-                        ],
-                        selector_str: "mintWithTokenURI(address,uint256,string)",
-                        selector: u32::from_be_bytes(Self::MINT_WITH_TOKEN_URI),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("mintWithTokenURI"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    fs,
-                                                    (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                                ),
-                                                (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                            ),
-                                            (<string>::SIGNATURE, <string>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "mintWithTokenURI",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                            <NamedArgument<string>>::new("tokenUri"),
-                        ),
-                        result: <UnnamedArgument<bool>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @dev Not implemented"],
-                        selector_str: "finishMinting()",
-                        selector: u32::from_be_bytes(Self::FINISH_MINTING),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("finishMinting"),
-                                    );
-                                    let fs = FunctionSignature::done(fs, false);
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "finishMinting",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (),
-                        result: <UnnamedArgument<bool>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "ERC721Mintable".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            ERC721MintableEvents::generate_solidity_interface(tc, is_impl);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for ERC721MintableCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::MINTING_FINISHED => return Ok(Some(Self::MintingFinished)),
-                Self::MINT => {
-                    return Ok(
-                        Some(Self::Mint {
-                            to: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::MINT_WITH_TOKEN_URI => {
-                    return Ok(
-                        Some(Self::MintWithTokenUri {
-                            to: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                            token_uri: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::FINISH_MINTING => return Ok(Some(Self::FinishMinting)),
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> ERC721MintableCall<T> {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for ERC721MintableCall<T> {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::MintingFinished => ().into(),
-                Self::Mint { to, token_id } => (<SelfWeightOf<T>>::create_item()).into(),
-                Self::MintWithTokenUri { to, token_id, token_uri } => {
-                    (<SelfWeightOf<T>>::create_item()).into()
-                }
-                Self::FinishMinting => ().into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<ERC721MintableCall<T>>
-    for NonfungibleHandle<T> {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<ERC721MintableCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                ERC721MintableCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<ERC721MintableCall<
-                                T,
-                            >>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                ERC721MintableCall::MintingFinished => {
-                    let result = self.minting_finished()?;
-                    (&result).to_result()
-                }
-                ERC721MintableCall::Mint { to, token_id } => {
-                    let result = self.mint(c.caller.clone(), to, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721MintableCall::MintWithTokenUri { to, token_id, token_uri } => {
-                    let result = self
-                        .mint_with_token_uri(c.caller.clone(), to, token_id, token_uri)?;
-                    (&result).to_result()
-                }
-                ERC721MintableCall::FinishMinting => {
-                    let result = self.finish_minting(c.caller.clone())?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    fn get_token_property<T: Config>(
-        collection: &CollectionHandle<T>,
-        token_id: u32,
-        key: &up_data_structs::PropertyKey,
-    ) -> Result<string> {
-        collection.consume_store_reads(1)?;
-        let properties = <TokenProperties<T>>::try_get((collection.id, token_id))
-            .map_err(|_| Error::Revert("Token properties not found".into()))?;
-        if let Some(property) = properties.get(key) {
-            return Ok(string::from_utf8_lossy(property).into());
-        }
-        Err("Property tokenURI not found".into())
-    }
-    fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {
-        if let Some(shema_name)
-            = pallet_common::Pallet::<
-                T,
-            >::get_collection_property(collection_id, &key::schema_name()) {
-            let shema_name = shema_name.into_inner();
-            shema_name == property_value::ERC721_METADATA
-        } else {
-            false
-        }
-    }
-    fn get_token_permission<T: Config>(
-        collection_id: CollectionId,
-        key: &PropertyKey,
-    ) -> Result<PropertyPermission> {
-        let token_property_permissions = CollectionPropertyPermissions::<
-            T,
-        >::try_get(collection_id)
-            .map_err(|_| Error::Revert("No permissions for collection".into()))?;
-        let a = token_property_permissions
-            .get(key)
-            .map(Clone::clone)
-            .ok_or_else(|| {
-                let key = string::from_utf8(key.clone().into_inner())
-                    .unwrap_or_default();
-                Error::Revert({
-                    let res = ::alloc::fmt::format(
-                        ::core::fmt::Arguments::new_v1(
-                            &["No permission for key "],
-                            &[::core::fmt::ArgumentV1::new_display(&key)],
-                        ),
-                    );
-                    res
-                })
-            })?;
-        Ok(a)
-    }
-    fn has_token_permission<T: Config>(
-        collection_id: CollectionId,
-        key: &PropertyKey,
-    ) -> bool {
-        if let Ok(token_property_permissions)
-            = CollectionPropertyPermissions::<T>::try_get(collection_id) {
-            return token_property_permissions.contains_key(key);
-        }
-        false
-    }
-    /// @title Unique extensions for ERC721.
-    impl<T: Config> NonfungibleHandle<T>
-    where
-        T::AccountId: From<[u8; 32]>,
-    {
-        /// @notice Set or reaffirm the approved address for an NFT
-        /// @dev The zero address indicates there is no approved address.
-        /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
-        ///  operator of the current owner.
-        /// @param approved The new substrate address approved NFT controller
-        /// @param tokenId The NFT to approve
-        fn approve_cross(
-            &mut self,
-            caller: caller,
-            approved: (address, uint256),
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let approved = convert_tuple_to_cross_account::<T>(approved)?;
-            let token = token_id.try_into()?;
-            <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @notice Transfer ownership of an NFT
-        /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
-        ///  is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param to The new owner
-        /// @param tokenId The NFT to transfer
-        fn transfer(
-            &mut self,
-            caller: caller,
-            to: address,
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let to = T::CrossAccountId::from_eth(to);
-            let token = token_id.try_into()?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            <Pallet<T>>::transfer(self, &caller, &to, token, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @notice Transfer ownership of an NFT from cross account address to cross account address
-        /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
-        ///  is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from Cross acccount address of current owner
-        /// @param to Cross acccount address of new owner
-        /// @param tokenId The NFT to transfer
-        fn transfer_from_cross(
-            &mut self,
-            caller: caller,
-            from: EthCrossAccount,
-            to: EthCrossAccount,
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let from = from.into_sub_cross_account::<T>()?;
-            let to = to.into_sub_cross_account::<T>()?;
-            let token_id = token_id.try_into()?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            Pallet::<T>::transfer_from(self, &caller, &from, &to, token_id, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @notice Burns a specific ERC721 token.
-        /// @dev Throws unless `msg.sender` is the current owner or an authorized
-        ///  operator for this NFT. Throws if `from` is not the current owner. Throws
-        ///  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from The current owner of the NFT
-        /// @param tokenId The NFT to transfer
-        fn burn_from(
-            &mut self,
-            caller: caller,
-            from: address,
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let from = T::CrossAccountId::from_eth(from);
-            let token = token_id.try_into()?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @notice Burns a specific ERC721 token.
-        /// @dev Throws unless `msg.sender` is the current owner or an authorized
-        ///  operator for this NFT. Throws if `from` is not the current owner. Throws
-        ///  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from The current owner of the NFT
-        /// @param tokenId The NFT to transfer
-        fn burn_from_cross(
-            &mut self,
-            caller: caller,
-            from: (address, uint256),
-            token_id: uint256,
-        ) -> Result<void> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let from = convert_tuple_to_cross_account::<T>(from)?;
-            let token = token_id.try_into()?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(())
-        }
-        /// @notice Returns next free NFT ID.
-        fn next_token_id(&self) -> Result<uint256> {
-            self.consume_store_reads(1)?;
-            Ok(
-                <TokensMinted<T>>::get(self.id)
-                    .checked_add(1)
-                    .ok_or("item id overflow")?
-                    .into(),
-            )
-        }
-        /// @notice Function to mint multiple tokens.
-        /// @dev `tokenIds` should be an array of consecutive numbers and first number
-        ///  should be obtained with `nextTokenId` method
-        /// @param to The new owner
-        /// @param tokenIds IDs of the minted NFTs
-        fn mint_bulk(
-            &mut self,
-            caller: caller,
-            to: address,
-            token_ids: Vec<uint256>,
-        ) -> Result<bool> {
-            let caller = T::CrossAccountId::from_eth(caller);
-            let to = T::CrossAccountId::from_eth(to);
-            let mut expected_index = <TokensMinted<T>>::get(self.id)
-                .checked_add(1)
-                .ok_or("item id overflow")?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            let total_tokens = token_ids.len();
-            for id in token_ids.into_iter() {
-                let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
-                if id != expected_index {
-                    return Err("item id should be next".into());
-                }
-                expected_index = expected_index
-                    .checked_add(1)
-                    .ok_or("item id overflow")?;
-            }
-            let data = (0..total_tokens)
-                .map(|_| CreateItemData::<T> {
-                    properties: BoundedVec::default(),
-                    owner: to.clone(),
-                })
-                .collect();
-            <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(true)
-        }
-        /// @notice Function to mint multiple tokens with the given tokenUris.
-        /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
-        ///  numbers and first number should be obtained with `nextTokenId` method
-        /// @param to The new owner
-        /// @param tokens array of pairs of token ID and token URI for minted tokens
-        fn mint_bulk_with_token_uri(
-            &mut self,
-            caller: caller,
-            to: address,
-            tokens: Vec<(uint256, string)>,
-        ) -> Result<bool> {
-            let key = key::url();
-            let caller = T::CrossAccountId::from_eth(caller);
-            let to = T::CrossAccountId::from_eth(to);
-            let mut expected_index = <TokensMinted<T>>::get(self.id)
-                .checked_add(1)
-                .ok_or("item id overflow")?;
-            let budget = self
-                .recorder
-                .weight_calls_budget(<StructureWeight<T>>::find_parent());
-            let mut data = Vec::with_capacity(tokens.len());
-            for (id, token_uri) in tokens {
-                let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
-                if id != expected_index {
-                    return Err("item id should be next".into());
-                }
-                expected_index = expected_index
-                    .checked_add(1)
-                    .ok_or("item id overflow")?;
-                let mut properties = CollectionPropertiesVec::default();
-                properties
-                    .try_push(Property {
-                        key: key.clone(),
-                        value: token_uri
-                            .into_bytes()
-                            .try_into()
-                            .map_err(|_| "token uri is too long")?,
-                    })
-                    .map_err(|e| Error::Revert({
-                        let res = ::alloc::fmt::format(
-                            ::core::fmt::Arguments::new_v1(
-                                &["Can\'t add property: "],
-                                &[::core::fmt::ArgumentV1::new_debug(&e)],
-                            ),
-                        );
-                        res
-                    }))?;
-                data.push(CreateItemData::<T> {
-                    properties,
-                    owner: to.clone(),
-                });
-            }
-            <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)
-                .map_err(dispatch_to_evm::<T>)?;
-            Ok(true)
-        }
-    }
-    /// @title Unique extensions for ERC721.
-    pub enum ERC721UniqueExtensionsCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        /// @notice Set or reaffirm the approved address for an NFT
-        /// @dev The zero address indicates there is no approved address.
-        /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
-        ///  operator of the current owner.
-        /// @param approved The new substrate address approved NFT controller
-        /// @param tokenId The NFT to approve
-        #[allow(missing_docs)]
-        ApproveCross { approved: (address, uint256), token_id: uint256 },
-        /// @notice Transfer ownership of an NFT
-        /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
-        ///  is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param to The new owner
-        /// @param tokenId The NFT to transfer
-        #[allow(missing_docs)]
-        Transfer { to: address, token_id: uint256 },
-        /// @notice Transfer ownership of an NFT from cross account address to cross account address
-        /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
-        ///  is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from Cross acccount address of current owner
-        /// @param to Cross acccount address of new owner
-        /// @param tokenId The NFT to transfer
-        #[allow(missing_docs)]
-        TransferFromCross {
-            from: EthCrossAccount,
-            to: EthCrossAccount,
-            token_id: uint256,
-        },
-        /// @notice Burns a specific ERC721 token.
-        /// @dev Throws unless `msg.sender` is the current owner or an authorized
-        ///  operator for this NFT. Throws if `from` is not the current owner. Throws
-        ///  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from The current owner of the NFT
-        /// @param tokenId The NFT to transfer
-        #[allow(missing_docs)]
-        BurnFrom { from: address, token_id: uint256 },
-        /// @notice Burns a specific ERC721 token.
-        /// @dev Throws unless `msg.sender` is the current owner or an authorized
-        ///  operator for this NFT. Throws if `from` is not the current owner. Throws
-        ///  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
-        /// @param from The current owner of the NFT
-        /// @param tokenId The NFT to transfer
-        #[allow(missing_docs)]
-        BurnFromCross { from: (address, uint256), token_id: uint256 },
-        NextTokenId,
-        /// @notice Function to mint multiple tokens.
-        /// @dev `tokenIds` should be an array of consecutive numbers and first number
-        ///  should be obtained with `nextTokenId` method
-        /// @param to The new owner
-        /// @param tokenIds IDs of the minted NFTs
-        #[allow(missing_docs)]
-        MintBulk { to: address, token_ids: Vec<uint256> },
-        /// @notice Function to mint multiple tokens with the given tokenUris.
-        /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
-        ///  numbers and first number should be obtained with `nextTokenId` method
-        /// @param to The new owner
-        /// @param tokens array of pairs of token ID and token URI for minted tokens
-        #[allow(missing_docs)]
-        MintBulkWithTokenUri { to: address, tokens: Vec<(uint256, string)> },
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721UniqueExtensionsCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                ERC721UniqueExtensionsCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                ERC721UniqueExtensionsCall::ApproveCross {
-                    approved: __self_0,
-                    token_id: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "ApproveCross",
-                        "approved",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                    )
-                }
-                ERC721UniqueExtensionsCall::Transfer {
-                    to: __self_0,
-                    token_id: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "Transfer",
-                        "to",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                    )
-                }
-                ERC721UniqueExtensionsCall::TransferFromCross {
-                    from: __self_0,
-                    to: __self_1,
-                    token_id: __self_2,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field3_finish(
-                        f,
-                        "TransferFromCross",
-                        "from",
-                        &__self_0,
-                        "to",
-                        &__self_1,
-                        "token_id",
-                        &__self_2,
-                    )
-                }
-                ERC721UniqueExtensionsCall::BurnFrom {
-                    from: __self_0,
-                    token_id: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "BurnFrom",
-                        "from",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                    )
-                }
-                ERC721UniqueExtensionsCall::BurnFromCross {
-                    from: __self_0,
-                    token_id: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "BurnFromCross",
-                        "from",
-                        &__self_0,
-                        "token_id",
-                        &__self_1,
-                    )
-                }
-                ERC721UniqueExtensionsCall::NextTokenId => {
-                    ::core::fmt::Formatter::write_str(f, "NextTokenId")
-                }
-                ERC721UniqueExtensionsCall::MintBulk {
-                    to: __self_0,
-                    token_ids: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "MintBulk",
-                        "to",
-                        &__self_0,
-                        "token_ids",
-                        &__self_1,
-                    )
-                }
-                ERC721UniqueExtensionsCall::MintBulkWithTokenUri {
-                    to: __self_0,
-                    tokens: __self_1,
-                } => {
-                    ::core::fmt::Formatter::debug_struct_field2_finish(
-                        f,
-                        "MintBulkWithTokenUri",
-                        "to",
-                        &__self_0,
-                        "tokens",
-                        &__self_1,
-                    )
-                }
-            }
-        }
-    }
-    impl<T> ERC721UniqueExtensionsCall<T> {
-        const APPROVE_CROSS_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("approveCross"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///approveCross((address,uint256),uint256)
-        const APPROVE_CROSS: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::APPROVE_CROSS_SIGNATURE.signature,
-                    Self::APPROVE_CROSS_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const TRANSFER_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("transfer"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///transfer(address,uint256)
-        const TRANSFER: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TRANSFER_SIGNATURE.signature,
-                    Self::TRANSFER_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const TRANSFER_FROM_CROSS_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(
-                    &&FunctionName::new("transferFromCross"),
-                );
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            FunctionSignature::add_param(
-                                fs,
-                                (
-                                    <EthCrossAccount>::SIGNATURE,
-                                    <EthCrossAccount>::SIGNATURE_LEN,
-                                ),
-                            ),
-                            (
-                                <EthCrossAccount>::SIGNATURE,
-                                <EthCrossAccount>::SIGNATURE_LEN,
-                            ),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///transferFromCross(EthCrossAccount,EthCrossAccount,uint256)
-        const TRANSFER_FROM_CROSS: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::TRANSFER_FROM_CROSS_SIGNATURE.signature,
-                    Self::TRANSFER_FROM_CROSS_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const BURN_FROM_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("burnFrom"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        FunctionSignature::add_param(
-                            fs,
-                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                        ),
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///burnFrom(address,uint256)
-        const BURN_FROM: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::BURN_FROM_SIGNATURE.signature,
-                    Self::BURN_FROM_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const BURN_FROM_CROSS_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("burnFromCross"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///burnFromCross((address,uint256),uint256)
-        const BURN_FROM_CROSS: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::BURN_FROM_CROSS_SIGNATURE.signature,
-                    Self::BURN_FROM_CROSS_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const NEXT_TOKEN_ID_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("nextTokenId"));
-                let fs = FunctionSignature::done(fs, false);
-                fs
-            }
-        };
-        ///nextTokenId()
-        const NEXT_TOKEN_ID: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::NEXT_TOKEN_ID_SIGNATURE.signature,
-                    Self::NEXT_TOKEN_ID_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const MINT_BULK_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(&&FunctionName::new("mintBulk"));
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///mintBulk(address,uint256[])
-        const MINT_BULK: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::MINT_BULK_SIGNATURE.signature,
-                    Self::MINT_BULK_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        const MINT_BULK_WITH_TOKEN_URI_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {
-            {
-                let fs = FunctionSignature::new(
-                    &&FunctionName::new("mintBulkWithTokenURI"),
-                );
-                let fs = FunctionSignature::done(
-                    FunctionSignature::add_param(
-                        fs,
-                        (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                    ),
-                    true,
-                );
-                fs
-            }
-        };
-        ///mintBulkWithTokenURI(address,(uint256,string)[])
-        const MINT_BULK_WITH_TOKEN_URI: ::evm_coder::types::bytes4 = {
-            let a = ::evm_coder::sha3_const::Keccak256::new()
-                .update_with_size(
-                    &Self::MINT_BULK_WITH_TOKEN_URI_SIGNATURE.signature,
-                    Self::MINT_BULK_WITH_TOKEN_URI_SIGNATURE.signature_len,
-                )
-                .finalize();
-            [a[0], a[1], a[2], a[3]]
-        };
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            interface_id ^= u32::from_be_bytes(Self::APPROVE_CROSS);
-            interface_id ^= u32::from_be_bytes(Self::TRANSFER);
-            interface_id ^= u32::from_be_bytes(Self::TRANSFER_FROM_CROSS);
-            interface_id ^= u32::from_be_bytes(Self::BURN_FROM);
-            interface_id ^= u32::from_be_bytes(Self::BURN_FROM_CROSS);
-            interface_id ^= u32::from_be_bytes(Self::NEXT_TOKEN_ID);
-            interface_id ^= u32::from_be_bytes(Self::MINT_BULK);
-            interface_id ^= u32::from_be_bytes(Self::MINT_BULK_WITH_TOKEN_URI);
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[" @title Unique extensions for ERC721."],
-                name: "ERC721UniqueExtensions",
-                selector: Self::interface_id(),
-                is: &["Dummy", "ERC165"],
-                functions: (
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Set or reaffirm the approved address for an NFT",
-                            " @dev The zero address indicates there is no approved address.",
-                            " @dev Throws unless `msg.sender` is the current NFT owner, or an authorized",
-                            "  operator of the current owner.",
-                            " @param approved The new substrate address approved NFT controller",
-                            " @param tokenId The NFT to approve",
-                        ],
-                        selector_str: "approveCross((address,uint256),uint256)",
-                        selector: u32::from_be_bytes(Self::APPROVE_CROSS),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("approveCross"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "approveCross",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<(address, uint256)>>::new("approved"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Transfer ownership of an NFT",
-                            " @dev Throws unless `msg.sender` is the current owner. Throws if `to`",
-                            "  is the zero address. Throws if `tokenId` is not a valid NFT.",
-                            " @param to The new owner",
-                            " @param tokenId The NFT to transfer",
-                        ],
-                        selector_str: "transfer(address,uint256)",
-                        selector: u32::from_be_bytes(Self::TRANSFER),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("transfer"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "transfer",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Transfer ownership of an NFT from cross account address to cross account address",
-                            " @dev Throws unless `msg.sender` is the current owner. Throws if `to`",
-                            "  is the zero address. Throws if `tokenId` is not a valid NFT.",
-                            " @param from Cross acccount address of current owner",
-                            " @param to Cross acccount address of new owner",
-                            " @param tokenId The NFT to transfer",
-                        ],
-                        selector_str: "transferFromCross(EthCrossAccount,EthCrossAccount,uint256)",
-                        selector: u32::from_be_bytes(Self::TRANSFER_FROM_CROSS),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("transferFromCross"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                FunctionSignature::add_param(
-                                                    fs,
-                                                    (
-                                                        <EthCrossAccount>::SIGNATURE,
-                                                        <EthCrossAccount>::SIGNATURE_LEN,
-                                                    ),
-                                                ),
-                                                (
-                                                    <EthCrossAccount>::SIGNATURE,
-                                                    <EthCrossAccount>::SIGNATURE_LEN,
-                                                ),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "transferFromCross",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<EthCrossAccount>>::new("from"),
-                            <NamedArgument<EthCrossAccount>>::new("to"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Burns a specific ERC721 token.",
-                            " @dev Throws unless `msg.sender` is the current owner or an authorized",
-                            "  operator for this NFT. Throws if `from` is not the current owner. Throws",
-                            "  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.",
-                            " @param from The current owner of the NFT",
-                            " @param tokenId The NFT to transfer",
-                        ],
-                        selector_str: "burnFrom(address,uint256)",
-                        selector: u32::from_be_bytes(Self::BURN_FROM),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("burnFrom"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            FunctionSignature::add_param(
-                                                fs,
-                                                (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                            ),
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "burnFrom",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("from"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Burns a specific ERC721 token.",
-                            " @dev Throws unless `msg.sender` is the current owner or an authorized",
-                            "  operator for this NFT. Throws if `from` is not the current owner. Throws",
-                            "  if `to` is the zero address. Throws if `tokenId` is not a valid NFT.",
-                            " @param from The current owner of the NFT",
-                            " @param tokenId The NFT to transfer",
-                        ],
-                        selector_str: "burnFromCross((address,uint256),uint256)",
-                        selector: u32::from_be_bytes(Self::BURN_FROM_CROSS),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("burnFromCross"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "burnFromCross",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<(address, uint256)>>::new("from"),
-                            <NamedArgument<uint256>>::new("tokenId"),
-                        ),
-                        result: <UnnamedArgument<void>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[" @notice Returns next free NFT ID."],
-                        selector_str: "nextTokenId()",
-                        selector: u32::from_be_bytes(Self::NEXT_TOKEN_ID),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("nextTokenId"),
-                                    );
-                                    let fs = FunctionSignature::done(fs, false);
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "nextTokenId",
-                        mutability: SolidityMutability::View,
-                        is_payable: false,
-                        args: (),
-                        result: <UnnamedArgument<uint256>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Function to mint multiple tokens.",
-                            " @dev `tokenIds` should be an array of consecutive numbers and first number",
-                            "  should be obtained with `nextTokenId` method",
-                            " @param to The new owner",
-                            " @param tokenIds IDs of the minted NFTs",
-                        ],
-                        selector_str: "mintBulk(address,uint256[])",
-                        selector: u32::from_be_bytes(Self::MINT_BULK),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("mintBulk"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "mintBulk",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<Vec<uint256>>>::new("tokenIds"),
-                        ),
-                        result: <UnnamedArgument<bool>>::default(),
-                    },
-                    SolidityFunction {
-                        docs: &[
-                            " @notice Function to mint multiple tokens with the given tokenUris.",
-                            " @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive",
-                            "  numbers and first number should be obtained with `nextTokenId` method",
-                            " @param to The new owner",
-                            " @param tokens array of pairs of token ID and token URI for minted tokens",
-                        ],
-                        selector_str: "mintBulkWithTokenURI(address,(uint256,string)[])",
-                        selector: u32::from_be_bytes(Self::MINT_BULK_WITH_TOKEN_URI),
-                        custom_signature: {
-                            const cs: FunctionSignature = {
-                                {
-                                    let fs = FunctionSignature::new(
-                                        &&FunctionName::new("mintBulkWithTokenURI"),
-                                    );
-                                    let fs = FunctionSignature::done(
-                                        FunctionSignature::add_param(
-                                            fs,
-                                            (<address>::SIGNATURE, <address>::SIGNATURE_LEN),
-                                        ),
-                                        true,
-                                    );
-                                    fs
-                                }
-                            };
-                            cs
-                        },
-                        name: "mintBulkWithTokenURI",
-                        mutability: SolidityMutability::Mutable,
-                        is_payable: false,
-                        args: (
-                            <NamedArgument<address>>::new("to"),
-                            <NamedArgument<Vec<(uint256, string)>>>::new("tokens"),
-                        ),
-                        result: <UnnamedArgument<bool>>::default(),
-                    },
-                ),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "ERC721UniqueExtensions".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for ERC721UniqueExtensionsCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                Self::APPROVE_CROSS => {
-                    return Ok(
-                        Some(Self::ApproveCross {
-                            approved: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::TRANSFER => {
-                    return Ok(
-                        Some(Self::Transfer {
-                            to: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::TRANSFER_FROM_CROSS => {
-                    return Ok(
-                        Some(Self::TransferFromCross {
-                            from: reader.abi_read()?,
-                            to: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::BURN_FROM => {
-                    return Ok(
-                        Some(Self::BurnFrom {
-                            from: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::BURN_FROM_CROSS => {
-                    return Ok(
-                        Some(Self::BurnFromCross {
-                            from: reader.abi_read()?,
-                            token_id: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::NEXT_TOKEN_ID => return Ok(Some(Self::NextTokenId)),
-                Self::MINT_BULK => {
-                    return Ok(
-                        Some(Self::MintBulk {
-                            to: reader.abi_read()?,
-                            token_ids: reader.abi_read()?,
-                        }),
-                    );
-                }
-                Self::MINT_BULK_WITH_TOKEN_URI => {
-                    return Ok(
-                        Some(Self::MintBulkWithTokenUri {
-                            to: reader.abi_read()?,
-                            tokens: reader.abi_read()?,
-                        }),
-                    );
-                }
-                _ => {}
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> ERC721UniqueExtensionsCall<T>
-    where
-        T::AccountId: From<[u8; 32]>,
-    {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id())
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for ERC721UniqueExtensionsCall<T>
-    where
-        T::AccountId: From<[u8; 32]>,
-    {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-                Self::ApproveCross { approved, token_id } => {
-                    (<SelfWeightOf<T>>::approve()).into()
-                }
-                Self::Transfer { to, token_id } => (<SelfWeightOf<T>>::transfer()).into(),
-                Self::TransferFromCross { from, to, token_id } => {
-                    (<SelfWeightOf<T>>::transfer()).into()
-                }
-                Self::BurnFrom { from, token_id } => {
-                    (<SelfWeightOf<T>>::burn_from()).into()
-                }
-                Self::BurnFromCross { from, token_id } => {
-                    (<SelfWeightOf<T>>::burn_from()).into()
-                }
-                Self::NextTokenId => ().into(),
-                Self::MintBulk { to, token_ids } => {
-                    (<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))
-                        .into()
-                }
-                Self::MintBulkWithTokenUri { to, tokens } => {
-                    (<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))
-                        .into()
-                }
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<ERC721UniqueExtensionsCall<T>>
-    for NonfungibleHandle<T>
-    where
-        T::AccountId: From<[u8; 32]>,
-    {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<ERC721UniqueExtensionsCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                ERC721UniqueExtensionsCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<ERC721UniqueExtensionsCall<
-                                T,
-                            >>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                ERC721UniqueExtensionsCall::ApproveCross { approved, token_id } => {
-                    let result = self
-                        .approve_cross(c.caller.clone(), approved, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::Transfer { to, token_id } => {
-                    let result = self.transfer(c.caller.clone(), to, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::TransferFromCross { from, to, token_id } => {
-                    let result = self
-                        .transfer_from_cross(c.caller.clone(), from, to, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::BurnFrom { from, token_id } => {
-                    let result = self.burn_from(c.caller.clone(), from, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::BurnFromCross { from, token_id } => {
-                    let result = self.burn_from_cross(c.caller.clone(), from, token_id)?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::NextTokenId => {
-                    let result = self.next_token_id()?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::MintBulk { to, token_ids } => {
-                    let result = self.mint_bulk(c.caller.clone(), to, token_ids)?;
-                    (&result).to_result()
-                }
-                ERC721UniqueExtensionsCall::MintBulkWithTokenUri { to, tokens } => {
-                    let result = self
-                        .mint_bulk_with_token_uri(c.caller.clone(), to, tokens)?;
-                    (&result).to_result()
-                }
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    impl<T: Config> NonfungibleHandle<T>
-    where
-        T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
-    {}
-    pub enum UniqueNFTCall<T> {
-        /// Inherited method
-        ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),
-        ERC721(ERC721Call<T>),
-        ERC721Metadata(ERC721MetadataCall<T>),
-        ERC721Enumerable(ERC721EnumerableCall<T>),
-        ERC721UniqueExtensions(ERC721UniqueExtensionsCall<T>),
-        ERC721Mintable(ERC721MintableCall<T>),
-        ERC721Burnable(ERC721BurnableCall<T>),
-        Collection(CollectionCall<T>),
-        TokenProperties(TokenPropertiesCall<T>),
-    }
-    #[automatically_derived]
-    impl<T: ::core::fmt::Debug> ::core::fmt::Debug for UniqueNFTCall<T> {
-        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-            match self {
-                UniqueNFTCall::ERC165Call(__self_0, __self_1) => {
-                    ::core::fmt::Formatter::debug_tuple_field2_finish(
-                        f,
-                        "ERC165Call",
-                        &__self_0,
-                        &__self_1,
-                    )
-                }
-                UniqueNFTCall::ERC721(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "ERC721",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::ERC721Metadata(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "ERC721Metadata",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::ERC721Enumerable(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "ERC721Enumerable",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::ERC721UniqueExtensions(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "ERC721UniqueExtensions",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::ERC721Mintable(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "ERC721Mintable",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::ERC721Burnable(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "ERC721Burnable",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::Collection(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "Collection",
-                        &__self_0,
-                    )
-                }
-                UniqueNFTCall::TokenProperties(__self_0) => {
-                    ::core::fmt::Formatter::debug_tuple_field1_finish(
-                        f,
-                        "TokenProperties",
-                        &__self_0,
-                    )
-                }
-            }
-        }
-    }
-    impl<T> UniqueNFTCall<T> {
-        /// Return this call ERC165 selector
-        pub fn interface_id() -> ::evm_coder::types::bytes4 {
-            let mut interface_id = 0;
-            u32::to_be_bytes(interface_id)
-        }
-        /// Generate solidity definitions for methods described in this interface
-        pub fn generate_solidity_interface(
-            tc: &evm_coder::solidity::TypeCollector,
-            is_impl: bool,
-        ) {
-            use evm_coder::solidity::*;
-            use core::fmt::Write;
-            let interface = SolidityInterface {
-                docs: &[],
-                name: "UniqueNFT",
-                selector: Self::interface_id(),
-                is: &[
-                    "Dummy",
-                    "ERC165",
-                    "ERC721",
-                    "ERC721Metadata",
-                    "ERC721Enumerable",
-                    "ERC721UniqueExtensions",
-                    "ERC721Mintable",
-                    "ERC721Burnable",
-                    "Collection",
-                    "TokenProperties",
-                ],
-                functions: (),
-            };
-            let mut out = ::evm_coder::types::string::new();
-            if "UniqueNFT".starts_with("Inline") {
-                out.push_str("/// @dev inlined interface\n");
-            }
-            let _ = interface.format(is_impl, &mut out, tc);
-            tc.collect(out);
-            <ERC721Call<T>>::generate_solidity_interface(tc, is_impl);
-            <ERC721MetadataCall<T>>::generate_solidity_interface(tc, is_impl);
-            <ERC721EnumerableCall<T>>::generate_solidity_interface(tc, is_impl);
-            <ERC721UniqueExtensionsCall<T>>::generate_solidity_interface(tc, is_impl);
-            <ERC721MintableCall<T>>::generate_solidity_interface(tc, is_impl);
-            <ERC721BurnableCall<T>>::generate_solidity_interface(tc, is_impl);
-            <CollectionCall<T>>::generate_solidity_interface(tc, is_impl);
-            <TokenPropertiesCall<T>>::generate_solidity_interface(tc, is_impl);
-            if is_impl {
-                tc.collect(
-                    "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"
-                        .into(),
-                );
-            } else {
-                tc.collect(
-                    "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
-                        .into(),
-                );
-            }
-        }
-    }
-    impl<T> ::evm_coder::Call for UniqueNFTCall<T> {
-        fn parse(
-            method_id: ::evm_coder::types::bytes4,
-            reader: &mut ::evm_coder::abi::AbiReader,
-        ) -> ::evm_coder::execution::Result<Option<Self>> {
-            use ::evm_coder::abi::AbiRead;
-            match method_id {
-                ::evm_coder::ERC165Call::INTERFACE_ID => {
-                    return Ok(
-                        ::evm_coder::ERC165Call::parse(method_id, reader)?
-                            .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),
-                    );
-                }
-                _ => {}
-            }
-            if let Some(parsed_call) = <ERC721Call<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::ERC721(parsed_call)))
-            } else if let Some(parsed_call)
-                = <ERC721MetadataCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::ERC721Metadata(parsed_call)))
-            } else if let Some(parsed_call)
-                = <ERC721EnumerableCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::ERC721Enumerable(parsed_call)))
-            } else if let Some(parsed_call)
-                = <ERC721UniqueExtensionsCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::ERC721UniqueExtensions(parsed_call)))
-            } else if let Some(parsed_call)
-                = <ERC721MintableCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::ERC721Mintable(parsed_call)))
-            } else if let Some(parsed_call)
-                = <ERC721BurnableCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::ERC721Burnable(parsed_call)))
-            } else if let Some(parsed_call)
-                = <CollectionCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::Collection(parsed_call)))
-            } else if let Some(parsed_call)
-                = <TokenPropertiesCall<T>>::parse(method_id, reader)? {
-                return Ok(Some(Self::TokenProperties(parsed_call)))
-            }
-            return Ok(None);
-        }
-    }
-    impl<T: Config> UniqueNFTCall<T>
-    where
-        T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
-    {
-        /// Is this contract implements specified ERC165 selector
-        pub fn supports_interface(
-            this: &NonfungibleHandle<T>,
-            interface_id: ::evm_coder::types::bytes4,
-        ) -> bool {
-            interface_id != u32::to_be_bytes(0xffffff)
-                && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
-                    || interface_id == Self::interface_id()
-                    || <ERC721Call<T>>::supports_interface(this, interface_id)
-                    || <ERC721MetadataCall<T>>::supports_interface(this, interface_id)
-                    || <ERC721EnumerableCall<T>>::supports_interface(this, interface_id)
-                    || <ERC721UniqueExtensionsCall<
-                        T,
-                    >>::supports_interface(this, interface_id)
-                    || <ERC721MintableCall<T>>::supports_interface(this, interface_id)
-                    || <ERC721BurnableCall<T>>::supports_interface(this, interface_id)
-                    || <CollectionCall<T>>::supports_interface(this, interface_id)
-                    || <TokenPropertiesCall<T>>::supports_interface(this, interface_id))
-        }
-    }
-    impl<T: Config> ::evm_coder::Weighted for UniqueNFTCall<T>
-    where
-        T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
-    {
-        #[allow(unused_variables)]
-        fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-            match self {
-                Self::ERC721(call) => call.weight(),
-                Self::ERC721Metadata(call) => call.weight(),
-                Self::ERC721Enumerable(call) => call.weight(),
-                Self::ERC721UniqueExtensions(call) => call.weight(),
-                Self::ERC721Mintable(call) => call.weight(),
-                Self::ERC721Burnable(call) => call.weight(),
-                Self::Collection(call) => call.weight(),
-                Self::TokenProperties(call) => call.weight(),
-                Self::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { .. },
-                    _,
-                ) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-            }
-        }
-    }
-    impl<T: Config> ::evm_coder::Callable<UniqueNFTCall<T>> for NonfungibleHandle<T>
-    where
-        T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
-    {
-        #[allow(unreachable_code)]
-        fn call(
-            &mut self,
-            c: Msg<UniqueNFTCall<T>>,
-        ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-            use ::evm_coder::abi::AbiWrite;
-            match c.call {
-                UniqueNFTCall::ERC721(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        ERC721Call<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::ERC721Metadata(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        ERC721MetadataCall<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::ERC721Enumerable(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        ERC721EnumerableCall<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::ERC721UniqueExtensions(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        ERC721UniqueExtensionsCall<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::ERC721Mintable(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        ERC721MintableCall<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::ERC721Burnable(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        ERC721BurnableCall<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::Collection(call) => {
-                    return <CollectionHandle<
-                        T,
-                    > as ::evm_coder::Callable<
-                        CollectionCall<T>,
-                    >>::call(
-                        self.common_mut(),
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::TokenProperties(call) => {
-                    return <Self as ::evm_coder::Callable<
-                        TokenPropertiesCall<T>,
-                    >>::call(
-                        self,
-                        Msg {
-                            call,
-                            caller: c.caller,
-                            value: c.value,
-                        },
-                    );
-                }
-                UniqueNFTCall::ERC165Call(
-                    ::evm_coder::ERC165Call::SupportsInterface { interface_id },
-                    _,
-                ) => {
-                    let mut writer = ::evm_coder::abi::AbiWriter::default();
-                    writer
-                        .bool(
-                            &<UniqueNFTCall<T>>::supports_interface(self, interface_id),
-                        );
-                    return Ok(writer.into());
-                }
-                _ => {}
-            }
-            let mut writer = ::evm_coder::abi::AbiWriter::default();
-            match c.call {
-                _ => {
-                    Err(
-                        ::evm_coder::execution::Error::from("method is not available")
-                            .into(),
-                    )
-                }
-            }
-        }
-    }
-    impl<T: Config> CommonEvmHandler for NonfungibleHandle<T>
-    where
-        T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
-    {
-        const CODE: &'static [u8] = b"`\xe0`@R`&`\x80\x81\x81R\x90b\x00\x138`\xa09`\x01\x90b\x00\x00\"\x90\x82b\x00\x00\xdcV[P4\x80\x15b\x00\x000W`\x00\x80\xfd[Pb\x00\x01\xa8V[cNH{q`\xe0\x1b`\x00R`A`\x04R`$`\x00\xfd[`\x01\x81\x81\x1c\x90\x82\x16\x80b\x00\x00bW`\x7f\x82\x16\x91P[` \x82\x10\x81\x03b\x00\x00\x83WcNH{q`\xe0\x1b`\x00R`\"`\x04R`$`\x00\xfd[P\x91\x90PV[`\x1f\x82\x11\x15b\x00\x00\xd7W`\x00\x81\x81R` \x81 `\x1f\x85\x01`\x05\x1c\x81\x01` \x86\x10\x15b\x00\x00\xb2WP\x80[`\x1f\x85\x01`\x05\x1c\x82\x01\x91P[\x81\x81\x10\x15b\x00\x00\xd3W\x82\x81U`\x01\x01b\x00\x00\xbeV[PPP[PPPV[\x81Q`\x01`\x01`@\x1b\x03\x81\x11\x15b\x00\x00\xf8Wb\x00\x00\xf8b\x00\x007V[b\x00\x01\x10\x81b\x00\x01\t\x84Tb\x00\x00MV[\x84b\x00\x00\x89V[` \x80`\x1f\x83\x11`\x01\x81\x14b\x00\x01HW`\x00\x84\x15b\x00\x01/WP\x85\x83\x01Q[`\x00\x19`\x03\x86\x90\x1b\x1c\x19\x16`\x01\x85\x90\x1b\x17\x85Ub\x00\x00\xd3V[`\x00\x85\x81R` \x81 `\x1f\x19\x86\x16\x91[\x82\x81\x10\x15b\x00\x01yW\x88\x86\x01Q\x82U\x94\x84\x01\x94`\x01\x90\x91\x01\x90\x84\x01b\x00\x01XV[P\x85\x82\x10\x15b\x00\x01\x98W\x87\x85\x01Q`\x00\x19`\x03\x88\x90\x1b`\xf8\x16\x1c\x19\x16\x81U[PPPPP`\x01\x90\x81\x1b\x01\x90UPV[a\x11\x80\x80b\x00\x01\xb8`\x009`\x00\xf3\xfe`\x80`@R4\x80\x15a\x00\x10W`\x00\x80\xfd[P`\x046\x10a\x03\xdaW`\x005`\xe0\x1c\x80cj8A\xdb\x11a\x02\nW\x80c\x98\x11\xb0\xc7\x11a\x01%W\x80c\xcf$\xfdm\x11a\x00\xb8W\x80c\xdfr};\x11a\x00\x87W\x80c\xdfr};\x14a\x05\xaaW\x80c\xe5\xc9\x91?\x14a\x04{W\x80c\xe9\x85\xe9\xc5\x14a\x06PW\x80c\xf6\xb4\xdf\xb4\x14a\x06^W\x80c\xfa\xfd{B\x14a\x04\x97W`\x00\x80\xfd[\x80c\xcf$\xfdm\x14a\x064W\x80c\xd3KU\xb8\x14a\x042W\x80c\xd5\xcfC\x0b\x14a\x06BW\x80c\xd6:\x8e\x11\x14a\x05\xeeW`\x00\x80\xfd[\x80c\xa9\x05\x9c\xbb\x11a\x00\xf4W\x80c\xa9\x05\x9c\xbb\x14a\x04mW\x80c\xb8\x8dO\xde\x14a\x06\x18W\x80c\xbb/ZX\x14a\x04\x89W\x80c\xc8{V\xdd\x14a\x06&W`\x00\x80\xfd[\x80c\x98\x11\xb0\xc7\x14a\x05\xeeW\x80c\x99;\x7f\xba\x14a\x05\xfcW\x80c\xa0\x18J:\x14a\x04{W\x80c\xa2,\xb4e\x14a\x06\nW`\x00\x80\xfd[\x80cy\xccg\x90\x11a\x01\x9dW\x80c\x85\x9a\xa7\xd6\x11a\x01lW\x80c\x85\x9a\xa7\xd6\x14a\x04{W\x80c\x85\xc5\x1a\xcb\x14a\x04\x97W\x80c\x92\xe4b\xc7\x14a\x04\x97W\x80c\x95\xd8\x9bA\x14a\x042W`\x00\x80\xfd[\x80cy\xccg\x90\x14a\x04mW\x80c{}\xeb\xce\x14a\x05\xe0W\x80c}d\xbc\xb4\x14a\x04\x1cW\x80c\x84\xa1\xd5\xa8\x14a\x04{W`\x00\x80\xfd[\x80cp\xa0\x821\x11a\x01\xd9W\x80cp\xa0\x821\x14a\x05\xbfW\x80cr(\xc3\'\x14a\x05\xcdW\x80cuyJ<\x14a\x04\xb3W\x80cv#@.\x14a\x04\x97W`\x00\x80\xfd[\x80cj8A\xdb\x14a\x05\x9cW\x80cl\x0c\xd1s\x14a\x04{W\x80cn\x03&\xa3\x14a\x05\x0fW\x80cn\xc0\xa9\xf1\x14a\x05\xaaW`\x00\x80\xfd[\x80c/\x07?f\x11a\x02\xfaW\x80cB\x96lh\x11a\x02\x8dW\x80cX\x13!k\x11a\x02\\W\x80cX\x13!k\x14a\x05yW\x80ccR!\x1e\x14a\x04GW\x80cd\x87#\x96\x14a\x05\x8eW\x80cg\x84O\xe6\x14a\x04\x97W`\x00\x80\xfd[\x80cB\x96lh\x14a\x05AW\x80cD\xa9\x94^\x14a\x05OW\x80cOl\xcc\xe7\x14a\x05]W\x80cP\xbbN\x7f\x14a\x05kW`\x00\x80\xfd[\x80c>u\xa9\x05\x11a\x02\xc9W\x80c>u\xa9\x05\x14a\x05\x17W\x80c@\xc1\x0f\x19\x14a\x05%W\x80cA\x83]L\x14a\x053W\x80cB\x84.\x0e\x14a\x04\xd7W`\x00\x80\xfd[\x80c/\x07?f\x14a\x04\xe5W\x80c/t\\Y\x14a\x04\xf3W\x80c6T0\x06\x14a\x05\x01W\x80c<P\xe9z\x14a\x05\x0fW`\x00\x80\xfd[\x80c\t\xbaE*\x11a\x03rW\x80c\x17R\xd6{\x11a\x03AW\x80c\x17R\xd6{\x14a\x04\xa5W\x80c\x18\x16\r\xdd\x14a\x04\xb3W\x80c\"-\x97\xfa\x14a\x04\xc9W\x80c#\xb8r\xdd\x14a\x04\xd7W`\x00\x80\xfd[\x80c\t\xbaE*\x14a\x04{W\x80c\x0e\xcd\n\xb0\x14a\x04\x89W\x80c\x11-E\x86\x14a\x03\xdfW\x80c\x13\xaf@5\x14a\x04\x97W`\x00\x80\xfd[\x80c\x06a\x11\xd1\x11a\x03\xaeW\x80c\x06a\x11\xd1\x14a\x04$W\x80c\x06\xfd\xde\x03\x14a\x042W\x80c\x08\x18\x12\xfc\x14a\x04GW\x80c\t^\xa7\xb3\x14a\x04mW`\x00\x80\xfd[\x80b\x01\x8e\x84\x14a\x03\xdfW\x80c\x01\xff\xc9\xa7\x14a\x03\xf4W\x80c\x05\x8a\xc1\x85\x14a\x04\x1cW\x80c\x05\xd2\x03[\x14a\x04\x1cW[`\x00\x80\xfd[a\x03\xf2a\x03\xed6`\x04a\x07$V[a\x06fV[\x00[a\x04\x07a\x04\x026`\x04a\x07FV[a\x06\x8aV[`@Q\x90\x15\x15\x81R` \x01[`@Q\x80\x91\x03\x90\xf3[a\x04\x07a\x06\x8aV[a\x03\xf2a\x03\xed6`\x04a\x08MV[a\x04:a\x06\xa7V[`@Qa\x04\x13\x91\x90a\x08\xd9V[a\x04Ua\x04\x026`\x04a\x08\xecV[`@Q`\x01`\x01`\xa0\x1b\x03\x90\x91\x16\x81R` \x01a\x04\x13V[a\x03\xf2a\x03\xed6`\x04a\t\x1cV[a\x03\xf2a\x03\xed6`\x04a\t\x9cV[a\x03\xf2a\x03\xed6`\x04a\t\xb8V[a\x03\xf2a\x03\xed6`\x04a\t\xe3V[a\x03\xf2a\x03\xed6`\x04a\t\xfeV[a\x04\xbba\x06\x8aV[`@Q\x90\x81R` \x01a\x04\x13V[a\x03\xf2a\x03\xed6`\x04a\njV[a\x03\xf2a\x03\xed6`\x04a\n\xd8V[a\x03\xf2a\x03\xed6`\x04a\x0b\x14V[a\x04\xbba\x04\x026`\x04a\t\x1cV[a\x04\x07a\x04\x026`\x04a\x0b\x90V[a\x03\xf2a\x06fV[a\x04\x07a\x04\x026`\x04a\t\x9cV[a\x04\x07a\x04\x026`\x04a\t\x1cV[a\x03\xf2a\x03\xed6`\x04a\x0c\x95V[a\x03\xf2a\x03\xed6`\x04a\x08\xecV[a\x04\x07a\x04\x026`\x04a\x0c\xb8V[a\x04\xbba\x04\x026`\x04a\x08\xecV[a\x04\x07a\x04\x026`\x04a\r[V[a\x05\x81a\x06\xa7V[`@Qa\x04\x13\x91\x90a\r\xa7V[a\x03\xf2a\x03\xed6`\x04a\x0e\x07V[a\x03\xf2a\x03\xed6`\x04a\x0e\xa2V[a\x05\xb2a\x06\xf6V[`@Qa\x04\x13\x91\x90a\x0e\xfcV[a\x04\xbba\x04\x026`\x04a\t\xe3V[a\x04:a\x05\xdb6`\x04a\x08MV[a\x06\xa7V[a\x03\xf2a\x03\xed6`\x04a\x0f\x1cV[a\x04\x07a\x04\x026`\x04a\t\xe3V[a\x03\xf2a\x03\xed6`\x04a\x0fXV[a\x03\xf2a\x03\xed6`\x04a\x0f\xa5V[a\x03\xf2a\x03\xed6`\x04a\x0f\xcfV[a\x04:a\x05\xdb6`\x04a\x08\xecV[a\x04:a\x05\xdb6`\x04a\x0f\x1cV[a\x03\xf2a\x03\xed6`\x04a\x106V[a\x04Ua\x04\x026`\x04a\x10tV[a\x04Ua\x06\x8aV[`\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x06\x81\x91\x90a\x10\x9eV[`@Q\x80\x91\x03\x90\xfd[`\x00`\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x06\x81\x91\x90a\x10\x9eV[```\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x06\x81\x91\x90a\x10\x9eV[\x92\x91PPV[`@\x80Q\x80\x82\x01\x90\x91R`\x00\x80\x82R` \x82\x01R\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x06\xcaW\x90PP\x90P\x90V[`@\x80Q\x80\x82\x01\x90\x91R`\x00\x80\x82R` \x82\x01Ra\x06fV[\x805\x80\x15\x15\x81\x14a\x07\x1fW`\x00\x80\xfd[\x91\x90PV[`\x00` \x82\x84\x03\x12\x15a\x076W`\x00\x80\xfd[a\x07?\x82a\x07\x0fV[\x93\x92PPPV[`\x00` \x82\x84\x03\x12\x15a\x07XW`\x00\x80\xfd[\x815`\x01`\x01`\xe0\x1b\x03\x19\x81\x16\x81\x14a\x07?W`\x00\x80\xfd[cNH{q`\xe0\x1b`\x00R`A`\x04R`$`\x00\xfd[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1b\x03\x81\x11\x82\x82\x10\x17\x15a\x07\xa8Wa\x07\xa8a\x07pV[`@R\x90V[`@Q`\x1f\x82\x01`\x1f\x19\x16\x81\x01`\x01`\x01`@\x1b\x03\x81\x11\x82\x82\x10\x17\x15a\x07\xd6Wa\x07\xd6a\x07pV[`@R\x91\x90PV[`\x00\x82`\x1f\x83\x01\x12a\x07\xefW`\x00\x80\xfd[\x815`\x01`\x01`@\x1b\x03\x81\x11\x15a\x08\x08Wa\x08\x08a\x07pV[a\x08\x1b`\x1f\x82\x01`\x1f\x19\x16` \x01a\x07\xaeV[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x080W`\x00\x80\xfd[\x81` \x85\x01` \x83\x017`\x00\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[`\x00\x80`@\x83\x85\x03\x12\x15a\x08`W`\x00\x80\xfd[\x825\x91P` \x83\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x08}W`\x00\x80\xfd[a\x08\x89\x85\x82\x86\x01a\x07\xdeV[\x91PP\x92P\x92\x90PV[`\x00\x81Q\x80\x84R`\x00[\x81\x81\x10\x15a\x08\xb9W` \x81\x85\x01\x81\x01Q\x86\x83\x01\x82\x01R\x01a\x08\x9dV[P`\x00` \x82\x86\x01\x01R` `\x1f\x19`\x1f\x83\x01\x16\x85\x01\x01\x91PP\x92\x91PPV[` \x81R`\x00a\x07?` \x83\x01\x84a\x08\x93V[`\x00` \x82\x84\x03\x12\x15a\x08\xfeW`\x00\x80\xfd[P5\x91\x90PV[\x805`\x01`\x01`\xa0\x1b\x03\x81\x16\x81\x14a\x07\x1fW`\x00\x80\xfd[`\x00\x80`@\x83\x85\x03\x12\x15a\t/W`\x00\x80\xfd[a\t8\x83a\t\x05V[\x94` \x93\x90\x93\x015\x93PPPV[`\x00`@\x82\x84\x03\x12\x15a\tXW`\x00\x80\xfd[`@Q`@\x81\x01\x81\x81\x10`\x01`\x01`@\x1b\x03\x82\x11\x17\x15a\tzWa\tza\x07pV[`@R\x90P\x80a\t\x89\x83a\t\x05V[\x81R` \x83\x015` \x82\x01RP\x92\x91PPV[`\x00`@\x82\x84\x03\x12\x15a\t\xaeW`\x00\x80\xfd[a\x07?\x83\x83a\tFV[`\x00\x80``\x83\x85\x03\x12\x15a\t\xcbW`\x00\x80\xfd[a\t\xd5\x84\x84a\tFV[\x94`@\x93\x90\x93\x015\x93PPPV[`\x00` \x82\x84\x03\x12\x15a\t\xf5W`\x00\x80\xfd[a\x07?\x82a\t\x05V[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\n\x13W`\x00\x80\xfd[\x835\x92P` \x84\x015`\x01`\x01`@\x1b\x03\x80\x82\x11\x15a\n1W`\x00\x80\xfd[a\n=\x87\x83\x88\x01a\x07\xdeV[\x93P`@\x86\x015\x91P\x80\x82\x11\x15a\nSW`\x00\x80\xfd[Pa\n`\x86\x82\x87\x01a\x07\xdeV[\x91PP\x92P\x92P\x92V[`\x00\x80`\x00\x80`\x80\x85\x87\x03\x12\x15a\n\x80W`\x00\x80\xfd[\x845`\x01`\x01`@\x1b\x03\x81\x11\x15a\n\x96W`\x00\x80\xfd[a\n\xa2\x87\x82\x88\x01a\x07\xdeV[\x94PPa\n\xb1` \x86\x01a\x07\x0fV[\x92Pa\n\xbf`@\x86\x01a\x07\x0fV[\x91Pa\n\xcd``\x86\x01a\x07\x0fV[\x90P\x92\x95\x91\x94P\x92PV[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\n\xedW`\x00\x80\xfd[a\n\xf6\x84a\t\x05V[\x92Pa\x0b\x04` \x85\x01a\t\x05V[\x91P`@\x84\x015\x90P\x92P\x92P\x92V[`\x00\x80`@\x83\x85\x03\x12\x15a\x0b\'W`\x00\x80\xfd[\x825`\x01`\x01`@\x1b\x03\x80\x82\x11\x15a\x0b>W`\x00\x80\xfd[a\x0bJ\x86\x83\x87\x01a\x07\xdeV[\x93P` \x85\x015\x91P\x80\x82\x11\x15a\x0b`W`\x00\x80\xfd[Pa\x08\x89\x85\x82\x86\x01a\x07\xdeV[`\x00`\x01`\x01`@\x1b\x03\x82\x11\x15a\x0b\x86Wa\x0b\x86a\x07pV[P`\x05\x1b` \x01\x90V[`\x00\x80`@\x80\x84\x86\x03\x12\x15a\x0b\xa4W`\x00\x80\xfd[a\x0b\xad\x84a\t\x05V[\x92P` \x80\x85\x015`\x01`\x01`@\x1b\x03\x80\x82\x11\x15a\x0b\xcaW`\x00\x80\xfd[\x81\x87\x01\x91P\x87`\x1f\x83\x01\x12a\x0b\xdeW`\x00\x80\xfd[\x815a\x0b\xf1a\x0b\xec\x82a\x0bmV[a\x07\xaeV[\x81\x81R`\x05\x91\x90\x91\x1b\x83\x01\x84\x01\x90\x84\x81\x01\x90\x8a\x83\x11\x15a\x0c\x10W`\x00\x80\xfd[\x85\x85\x01[\x83\x81\x10\x15a\x0c\x83W\x805\x85\x81\x11\x15a\x0c,W`\x00\x80\x81\xfd[\x86\x01\x80\x8d\x03`\x1f\x19\x01\x89\x13\x15a\x0cBW`\x00\x80\x81\xfd[a\x0cJa\x07\x86V[\x88\x82\x015\x81R\x89\x82\x015\x87\x81\x11\x15a\x0cbW`\x00\x80\x81\xfd[a\x0cp\x8f\x8b\x83\x86\x01\x01a\x07\xdeV[\x82\x8b\x01RP\x84RP\x91\x86\x01\x91\x86\x01a\x0c\x14V[P\x80\x97PPPPPPPP\x92P\x92\x90PV[`\x00` \x82\x84\x03\x12\x15a\x0c\xa7W`\x00\x80\xfd[\x815`\xff\x81\x16\x81\x14a\x07?W`\x00\x80\xfd[`\x00\x80`@\x83\x85\x03\x12\x15a\x0c\xcbW`\x00\x80\xfd[a\x0c\xd4\x83a\t\x05V[\x91P` \x80\x84\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0c\xf0W`\x00\x80\xfd[\x84\x01`\x1f\x81\x01\x86\x13a\r\x01W`\x00\x80\xfd[\x805a\r\x0fa\x0b\xec\x82a\x0bmV[\x81\x81R`\x05\x91\x90\x91\x1b\x82\x01\x83\x01\x90\x83\x81\x01\x90\x88\x83\x11\x15a\r.W`\x00\x80\xfd[\x92\x84\x01\x92[\x82\x84\x10\x15a\rLW\x835\x82R\x92\x84\x01\x92\x90\x84\x01\x90a\r3V[\x80\x95PPPPPP\x92P\x92\x90PV[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\rpW`\x00\x80\xfd[a\ry\x84a\t\x05V[\x92P` \x84\x015\x91P`@\x84\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\r\x9bW`\x00\x80\xfd[a\n`\x86\x82\x87\x01a\x07\xdeV[` \x80\x82R\x82Q\x82\x82\x01\x81\x90R`\x00\x91\x90`@\x90\x81\x85\x01\x90\x86\x84\x01\x85[\x82\x81\x10\x15a\r\xfaWa\r\xea\x84\x83Q\x80Q`\x01`\x01`\xa0\x1b\x03\x16\x82R` \x90\x81\x01Q\x91\x01RV[\x92\x84\x01\x92\x90\x85\x01\x90`\x01\x01a\r\xc4V[P\x91\x97\x96PPPPPPPV[`\x00\x80`@\x83\x85\x03\x12\x15a\x0e\x1aW`\x00\x80\xfd[a\x0e#\x83a\x07\x0fV[\x91P` \x80\x84\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0e?W`\x00\x80\xfd[\x84\x01`\x1f\x81\x01\x86\x13a\x0ePW`\x00\x80\xfd[\x805a\x0e^a\x0b\xec\x82a\x0bmV[\x81\x81R`\x05\x91\x90\x91\x1b\x82\x01\x83\x01\x90\x83\x81\x01\x90\x88\x83\x11\x15a\x0e}W`\x00\x80\xfd[\x92\x84\x01\x92[\x82\x84\x10\x15a\rLWa\x0e\x93\x84a\t\x05V[\x82R\x92\x84\x01\x92\x90\x84\x01\x90a\x0e\x82V[`\x00\x80`@\x83\x85\x03\x12\x15a\x0e\xb5W`\x00\x80\xfd[\x825`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0e\xcbW`\x00\x80\xfd[a\x0e\xd7\x85\x82\x86\x01a\x07\xdeV[\x92PP` \x83\x015c\xff\xff\xff\xff\x81\x16\x81\x14a\x0e\xf1W`\x00\x80\xfd[\x80\x91PP\x92P\x92\x90PV[\x81Q`\x01`\x01`\xa0\x1b\x03\x16\x81R` \x80\x83\x01Q\x90\x82\x01R`@\x81\x01a\x06\xc4V[`\x00` \x82\x84\x03\x12\x15a\x0f.W`\x00\x80\xfd[\x815`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0fDW`\x00\x80\xfd[a\x0fP\x84\x82\x85\x01a\x07\xdeV[\x94\x93PPPPV[`\x00\x80`@\x83\x85\x03\x12\x15a\x0fkW`\x00\x80\xfd[\x825`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0f\x81W`\x00\x80\xfd[a\x0f\x8d\x85\x82\x86\x01a\x07\xdeV[\x92PPa\x0f\x9c` \x84\x01a\x07\x0fV[\x90P\x92P\x92\x90PV[`\x00\x80`@\x83\x85\x03\x12\x15a\x0f\xb8W`\x00\x80\xfd[a\x0f\xc1\x83a\t\x05V[\x91Pa\x0f\x9c` \x84\x01a\x07\x0fV[`\x00\x80`\x00\x80`\x80\x85\x87\x03\x12\x15a\x0f\xe5W`\x00\x80\xfd[a\x0f\xee\x85a\t\x05V[\x93Pa\x0f\xfc` \x86\x01a\t\x05V[\x92P`@\x85\x015\x91P``\x85\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x10\x1eW`\x00\x80\xfd[a\x10*\x87\x82\x88\x01a\x07\xdeV[\x91PP\x92\x95\x91\x94P\x92PV[`\x00\x80`\x00`\xa0\x84\x86\x03\x12\x15a\x10KW`\x00\x80\xfd[a\x10U\x85\x85a\tFV[\x92Pa\x10d\x85`@\x86\x01a\tFV[\x91P`\x80\x84\x015\x90P\x92P\x92P\x92V[`\x00\x80`@\x83\x85\x03\x12\x15a\x10\x87W`\x00\x80\xfd[a\x10\x90\x83a\t\x05V[\x91Pa\x0f\x9c` \x84\x01a\t\x05V[`\x00` \x80\x83R`\x00\x84T\x81`\x01\x82\x81\x1c\x91P\x80\x83\x16\x80a\x10\xc0W`\x7f\x83\x16\x92P[\x85\x83\x10\x81\x03a\x10\xddWcNH{q`\xe0\x1b\x85R`\"`\x04R`$\x85\xfd[\x87\x86\x01\x83\x81R` \x01\x81\x80\x15a\x10\xfaW`\x01\x81\x14a\x11\x10Wa\x11;V[`\xff\x19\x86\x16\x82R\x84\x15\x15`\x05\x1b\x82\x01\x96Pa\x11;V[`\x00\x8b\x81R` \x90 `\x00[\x86\x81\x10\x15a\x115W\x81T\x84\x82\x01R\x90\x85\x01\x90\x89\x01a\x11\x1cV[\x83\x01\x97PP[P\x94\x99\x98PPPPPPPPPV\xfe\xa2dipfsX\"\x12 eT\x15\xcb|u\xb1F\x80}\xaa]\xc0#\xe0\xdeO$^\x96a\xfb1\xc5\xb0\xfa\t\x12\x00>F\xa8dsolcC\x00\x08\x10\x003this contract is implemented in native";
-        fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
-            call::<T, UniqueNFTCall<T>, _, _>(handle, self)
-        }
-    }
-}
-pub mod weights {
-    //! Autogenerated weights for pallet_nonfungible
-    //!
-    //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-    //! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
-    //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
-    #![allow(unused_parens)]
-    #![allow(unused_imports)]
-    #![allow(clippy::unnecessary_cast)]
-    use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
-    use sp_std::marker::PhantomData;
-    /// Weight functions needed for pallet_nonfungible.
-    pub trait WeightInfo {
-        fn create_item() -> Weight;
-        fn create_multiple_items(b: u32) -> Weight;
-        fn create_multiple_items_ex(b: u32) -> Weight;
-        fn burn_item() -> Weight;
-        fn burn_recursively_self_raw() -> Weight;
-        fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32) -> Weight;
-        fn transfer() -> Weight;
-        fn approve() -> Weight;
-        fn transfer_from() -> Weight;
-        fn burn_from() -> Weight;
-        fn set_token_property_permissions(b: u32) -> Weight;
-        fn set_token_properties(b: u32) -> Weight;
-        fn delete_token_properties(b: u32) -> Weight;
-        fn token_owner() -> Weight;
-    }
-    /// Weights for pallet_nonfungible using the Substrate node and recommended hardware.
-    pub struct SubstrateWeight<T>(PhantomData<T>);
-    impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
-        fn create_item() -> Weight {
-            Weight::from_ref_time(25_905_000)
-                .saturating_add(T::DbWeight::get().reads(2 as u64))
-                .saturating_add(T::DbWeight::get().writes(4 as u64))
-        }
-        fn create_multiple_items(b: u32) -> Weight {
-            Weight::from_ref_time(24_955_000)
-                .saturating_add(
-                    Weight::from_ref_time(5_340_000).saturating_mul(b as u64),
-                )
-                .saturating_add(T::DbWeight::get().reads(2 as u64))
-                .saturating_add(T::DbWeight::get().writes(2 as u64))
-                .saturating_add(
-                    T::DbWeight::get().writes((2 as u64).saturating_mul(b as u64)),
-                )
-        }
-        fn create_multiple_items_ex(b: u32) -> Weight {
-            Weight::from_ref_time(13_666_000)
-                .saturating_add(
-                    Weight::from_ref_time(8_299_000).saturating_mul(b as u64),
-                )
-                .saturating_add(T::DbWeight::get().reads(1 as u64))
-                .saturating_add(
-                    T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)),
-                )
-                .saturating_add(T::DbWeight::get().writes(1 as u64))
-                .saturating_add(
-                    T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64)),
-                )
-        }
-        fn burn_item() -> Weight {
-            Weight::from_ref_time(36_205_000)
-                .saturating_add(T::DbWeight::get().reads(5 as u64))
-                .saturating_add(T::DbWeight::get().writes(5 as u64))
-        }
-        fn burn_recursively_self_raw() -> Weight {
-            Weight::from_ref_time(44_550_000)
-                .saturating_add(T::DbWeight::get().reads(5 as u64))
-                .saturating_add(T::DbWeight::get().writes(5 as u64))
-        }
-        fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(312_125_000).saturating_mul(b as u64),
-                )
-                .saturating_add(T::DbWeight::get().reads(7 as u64))
-                .saturating_add(
-                    T::DbWeight::get().reads((4 as u64).saturating_mul(b as u64)),
-                )
-                .saturating_add(T::DbWeight::get().writes(6 as u64))
-                .saturating_add(
-                    T::DbWeight::get().writes((4 as u64).saturating_mul(b as u64)),
-                )
-        }
-        fn transfer() -> Weight {
-            Weight::from_ref_time(31_116_000)
-                .saturating_add(T::DbWeight::get().reads(4 as u64))
-                .saturating_add(T::DbWeight::get().writes(5 as u64))
-        }
-        fn approve() -> Weight {
-            Weight::from_ref_time(20_802_000)
-                .saturating_add(T::DbWeight::get().reads(2 as u64))
-                .saturating_add(T::DbWeight::get().writes(1 as u64))
-        }
-        fn transfer_from() -> Weight {
-            Weight::from_ref_time(36_083_000)
-                .saturating_add(T::DbWeight::get().reads(4 as u64))
-                .saturating_add(T::DbWeight::get().writes(6 as u64))
-        }
-        fn burn_from() -> Weight {
-            Weight::from_ref_time(41_781_000)
-                .saturating_add(T::DbWeight::get().reads(5 as u64))
-                .saturating_add(T::DbWeight::get().writes(6 as u64))
-        }
-        fn set_token_property_permissions(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(15_705_000).saturating_mul(b as u64),
-                )
-                .saturating_add(T::DbWeight::get().reads(1 as u64))
-                .saturating_add(T::DbWeight::get().writes(1 as u64))
-        }
-        fn set_token_properties(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(590_344_000).saturating_mul(b as u64),
-                )
-                .saturating_add(T::DbWeight::get().reads(2 as u64))
-                .saturating_add(T::DbWeight::get().writes(1 as u64))
-        }
-        fn delete_token_properties(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(605_836_000).saturating_mul(b as u64),
-                )
-                .saturating_add(T::DbWeight::get().reads(2 as u64))
-                .saturating_add(T::DbWeight::get().writes(1 as u64))
-        }
-        fn token_owner() -> Weight {
-            Weight::from_ref_time(4_366_000)
-                .saturating_add(T::DbWeight::get().reads(1 as u64))
-        }
-    }
-    impl WeightInfo for () {
-        fn create_item() -> Weight {
-            Weight::from_ref_time(25_905_000)
-                .saturating_add(RocksDbWeight::get().reads(2 as u64))
-                .saturating_add(RocksDbWeight::get().writes(4 as u64))
-        }
-        fn create_multiple_items(b: u32) -> Weight {
-            Weight::from_ref_time(24_955_000)
-                .saturating_add(
-                    Weight::from_ref_time(5_340_000).saturating_mul(b as u64),
-                )
-                .saturating_add(RocksDbWeight::get().reads(2 as u64))
-                .saturating_add(RocksDbWeight::get().writes(2 as u64))
-                .saturating_add(
-                    RocksDbWeight::get().writes((2 as u64).saturating_mul(b as u64)),
-                )
-        }
-        fn create_multiple_items_ex(b: u32) -> Weight {
-            Weight::from_ref_time(13_666_000)
-                .saturating_add(
-                    Weight::from_ref_time(8_299_000).saturating_mul(b as u64),
-                )
-                .saturating_add(RocksDbWeight::get().reads(1 as u64))
-                .saturating_add(
-                    RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)),
-                )
-                .saturating_add(RocksDbWeight::get().writes(1 as u64))
-                .saturating_add(
-                    RocksDbWeight::get().writes((3 as u64).saturating_mul(b as u64)),
-                )
-        }
-        fn burn_item() -> Weight {
-            Weight::from_ref_time(36_205_000)
-                .saturating_add(RocksDbWeight::get().reads(5 as u64))
-                .saturating_add(RocksDbWeight::get().writes(5 as u64))
-        }
-        fn burn_recursively_self_raw() -> Weight {
-            Weight::from_ref_time(44_550_000)
-                .saturating_add(RocksDbWeight::get().reads(5 as u64))
-                .saturating_add(RocksDbWeight::get().writes(5 as u64))
-        }
-        fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(312_125_000).saturating_mul(b as u64),
-                )
-                .saturating_add(RocksDbWeight::get().reads(7 as u64))
-                .saturating_add(
-                    RocksDbWeight::get().reads((4 as u64).saturating_mul(b as u64)),
-                )
-                .saturating_add(RocksDbWeight::get().writes(6 as u64))
-                .saturating_add(
-                    RocksDbWeight::get().writes((4 as u64).saturating_mul(b as u64)),
-                )
-        }
-        fn transfer() -> Weight {
-            Weight::from_ref_time(31_116_000)
-                .saturating_add(RocksDbWeight::get().reads(4 as u64))
-                .saturating_add(RocksDbWeight::get().writes(5 as u64))
-        }
-        fn approve() -> Weight {
-            Weight::from_ref_time(20_802_000)
-                .saturating_add(RocksDbWeight::get().reads(2 as u64))
-                .saturating_add(RocksDbWeight::get().writes(1 as u64))
-        }
-        fn transfer_from() -> Weight {
-            Weight::from_ref_time(36_083_000)
-                .saturating_add(RocksDbWeight::get().reads(4 as u64))
-                .saturating_add(RocksDbWeight::get().writes(6 as u64))
-        }
-        fn burn_from() -> Weight {
-            Weight::from_ref_time(41_781_000)
-                .saturating_add(RocksDbWeight::get().reads(5 as u64))
-                .saturating_add(RocksDbWeight::get().writes(6 as u64))
-        }
-        fn set_token_property_permissions(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(15_705_000).saturating_mul(b as u64),
-                )
-                .saturating_add(RocksDbWeight::get().reads(1 as u64))
-                .saturating_add(RocksDbWeight::get().writes(1 as u64))
-        }
-        fn set_token_properties(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(590_344_000).saturating_mul(b as u64),
-                )
-                .saturating_add(RocksDbWeight::get().reads(2 as u64))
-                .saturating_add(RocksDbWeight::get().writes(1 as u64))
-        }
-        fn delete_token_properties(b: u32) -> Weight {
-            (Weight::from_ref_time(0))
-                .saturating_add(
-                    Weight::from_ref_time(605_836_000).saturating_mul(b as u64),
-                )
-                .saturating_add(RocksDbWeight::get().reads(2 as u64))
-                .saturating_add(RocksDbWeight::get().writes(1 as u64))
-        }
-        fn token_owner() -> Weight {
-            Weight::from_ref_time(4_366_000)
-                .saturating_add(RocksDbWeight::get().reads(1 as u64))
-        }
-    }
-}
-pub type CreateItemData<T> = CreateNftExData<
-    <T as pallet_evm::account::Config>::CrossAccountId,
->;
-pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
-/// Token data, stored independently from other data used to describe it
-/// for the convenience of database access. Notably contains the owner account address.
-pub struct ItemDataVersion1<CrossAccountId> {
-    pub const_data: BoundedVec<u8, CustomDataLimit>,
-    pub variable_data: BoundedVec<u8, CustomDataLimit>,
-    pub owner: CrossAccountId,
-}
-#[allow(deprecated)]
-const _: () = {
-    #[automatically_derived]
-    impl<CrossAccountId> ::codec::Encode for ItemDataVersion1<CrossAccountId>
-    where
-        CrossAccountId: ::codec::Encode,
-        CrossAccountId: ::codec::Encode,
-    {
-        fn encode_to<__CodecOutputEdqy: ::codec::Output + ?::core::marker::Sized>(
-            &self,
-            __codec_dest_edqy: &mut __CodecOutputEdqy,
-        ) {
-            ::codec::Encode::encode_to(&self.const_data, __codec_dest_edqy);
-            ::codec::Encode::encode_to(&self.variable_data, __codec_dest_edqy);
-            ::codec::Encode::encode_to(&self.owner, __codec_dest_edqy);
-        }
-    }
-    #[automatically_derived]
-    impl<CrossAccountId> ::codec::EncodeLike for ItemDataVersion1<CrossAccountId>
-    where
-        CrossAccountId: ::codec::Encode,
-        CrossAccountId: ::codec::Encode,
-    {}
-};
-#[allow(deprecated)]
-const _: () = {
-    #[automatically_derived]
-    impl<CrossAccountId> ::codec::Decode for ItemDataVersion1<CrossAccountId>
-    where
-        CrossAccountId: ::codec::Decode,
-        CrossAccountId: ::codec::Decode,
-    {
-        fn decode<__CodecInputEdqy: ::codec::Input>(
-            __codec_input_edqy: &mut __CodecInputEdqy,
-        ) -> ::core::result::Result<Self, ::codec::Error> {
-            ::core::result::Result::Ok(ItemDataVersion1::<CrossAccountId> {
-                const_data: {
-                    let __codec_res_edqy = <BoundedVec<
-                        u8,
-                        CustomDataLimit,
-                    > as ::codec::Decode>::decode(__codec_input_edqy);
-                    match __codec_res_edqy {
-                        ::core::result::Result::Err(e) => {
-                            return ::core::result::Result::Err(
-                                e.chain("Could not decode `ItemDataVersion1::const_data`"),
-                            );
-                        }
-                        ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,
-                    }
-                },
-                variable_data: {
-                    let __codec_res_edqy = <BoundedVec<
-                        u8,
-                        CustomDataLimit,
-                    > as ::codec::Decode>::decode(__codec_input_edqy);
-                    match __codec_res_edqy {
-                        ::core::result::Result::Err(e) => {
-                            return ::core::result::Result::Err(
-                                e
-                                    .chain("Could not decode `ItemDataVersion1::variable_data`"),
-                            );
-                        }
-                        ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,
-                    }
-                },
-                owner: {
-                    let __codec_res_edqy = <CrossAccountId as ::codec::Decode>::decode(
-                        __codec_input_edqy,
-                    );
-                    match __codec_res_edqy {
-                        ::core::result::Result::Err(e) => {
-                            return ::core::result::Result::Err(
-                                e.chain("Could not decode `ItemDataVersion1::owner`"),
-                            );
-                        }
-                        ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,
-                    }
-                },
-            })
-        }
-    }
-};
-#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
-const _: () = {
-    impl<CrossAccountId> ::scale_info::TypeInfo for ItemDataVersion1<CrossAccountId>
-    where
-        CrossAccountId: ::scale_info::TypeInfo + 'static,
-        CrossAccountId: ::scale_info::TypeInfo + 'static,
-    {
-        type Identity = Self;
-        fn type_info() -> ::scale_info::Type {
-            ::scale_info::Type::builder()
-                .path(::scale_info::Path::new("ItemDataVersion1", "pallet_nonfungible"))
-                .type_params(
-                    <[_]>::into_vec(
-                        #[rustc_box]
-                        ::alloc::boxed::Box::new([
-                            ::scale_info::TypeParameter::new(
-                                "CrossAccountId",
-                                ::core::option::Option::Some(
-                                    ::scale_info::meta_type::<CrossAccountId>(),
-                                ),
-                            ),
-                        ]),
-                    ),
-                )
-                .docs(
-                    &[
-                        "Token data, stored independently from other data used to describe it",
-                        "for the convenience of database access. Notably contains the owner account address.",
-                    ],
-                )
-                .composite(
-                    ::scale_info::build::Fields::named()
-                        .field(|f| {
-                            f
-                                .ty::<BoundedVec<u8, CustomDataLimit>>()
-                                .name("const_data")
-                                .type_name("BoundedVec<u8, CustomDataLimit>")
-                                .docs(&[])
-                        })
-                        .field(|f| {
-                            f
-                                .ty::<BoundedVec<u8, CustomDataLimit>>()
-                                .name("variable_data")
-                                .type_name("BoundedVec<u8, CustomDataLimit>")
-                                .docs(&[])
-                        })
-                        .field(|f| {
-                            f
-                                .ty::<CrossAccountId>()
-                                .name("owner")
-                                .type_name("CrossAccountId")
-                                .docs(&[])
-                        }),
-                )
-        }
-    }
-};
-const _: () = {
-    impl<CrossAccountId> ::codec::MaxEncodedLen for ItemDataVersion1<CrossAccountId>
-    where
-        CrossAccountId: ::codec::MaxEncodedLen,
-        CrossAccountId: ::codec::MaxEncodedLen,
-    {
-        fn max_encoded_len() -> ::core::primitive::usize {
-            0_usize
-                .saturating_add(<BoundedVec<u8, CustomDataLimit>>::max_encoded_len())
-                .saturating_add(<BoundedVec<u8, CustomDataLimit>>::max_encoded_len())
-                .saturating_add(<CrossAccountId>::max_encoded_len())
-        }
-    }
-};
-/// Token data, stored independently from other data used to describe it
-/// for the convenience of database access. Notably contains the owner account address.
-/// # Versioning
-/// Changes between 1 and 2:
-/// - const_data: BoundedVec < u8, CustomDataLimit > was removed
-/// - variable_data: BoundedVec < u8, CustomDataLimit > was removed
-pub struct ItemData<CrossAccountId> {
-    pub owner: CrossAccountId,
-}
-#[allow(deprecated)]
-const _: () = {
-    #[automatically_derived]
-    impl<CrossAccountId> ::codec::Encode for ItemData<CrossAccountId>
-    where
-        CrossAccountId: ::codec::Encode,
-        CrossAccountId: ::codec::Encode,
-    {
-        fn encode_to<__CodecOutputEdqy: ::codec::Output + ?::core::marker::Sized>(
-            &self,
-            __codec_dest_edqy: &mut __CodecOutputEdqy,
-        ) {
-            ::codec::Encode::encode_to(&&self.owner, __codec_dest_edqy)
-        }
-        fn encode(&self) -> ::codec::alloc::vec::Vec<::core::primitive::u8> {
-            ::codec::Encode::encode(&&self.owner)
-        }
-        fn using_encoded<R, F: ::core::ops::FnOnce(&[::core::primitive::u8]) -> R>(
-            &self,
-            f: F,
-        ) -> R {
-            ::codec::Encode::using_encoded(&&self.owner, f)
-        }
-    }
-    #[automatically_derived]
-    impl<CrossAccountId> ::codec::EncodeLike for ItemData<CrossAccountId>
-    where
-        CrossAccountId: ::codec::Encode,
-        CrossAccountId: ::codec::Encode,
-    {}
-};
-#[allow(deprecated)]
-const _: () = {
-    #[automatically_derived]
-    impl<CrossAccountId> ::codec::Decode for ItemData<CrossAccountId>
-    where
-        CrossAccountId: ::codec::Decode,
-        CrossAccountId: ::codec::Decode,
-    {
-        fn decode<__CodecInputEdqy: ::codec::Input>(
-            __codec_input_edqy: &mut __CodecInputEdqy,
-        ) -> ::core::result::Result<Self, ::codec::Error> {
-            ::core::result::Result::Ok(ItemData::<CrossAccountId> {
-                owner: {
-                    let __codec_res_edqy = <CrossAccountId as ::codec::Decode>::decode(
-                        __codec_input_edqy,
-                    );
-                    match __codec_res_edqy {
-                        ::core::result::Result::Err(e) => {
-                            return ::core::result::Result::Err(
-                                e.chain("Could not decode `ItemData::owner`"),
-                            );
-                        }
-                        ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,
-                    }
-                },
-            })
-        }
-    }
-};
-#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
-const _: () = {
-    impl<CrossAccountId> ::scale_info::TypeInfo for ItemData<CrossAccountId>
-    where
-        CrossAccountId: ::scale_info::TypeInfo + 'static,
-        CrossAccountId: ::scale_info::TypeInfo + 'static,
-    {
-        type Identity = Self;
-        fn type_info() -> ::scale_info::Type {
-            ::scale_info::Type::builder()
-                .path(::scale_info::Path::new("ItemData", "pallet_nonfungible"))
-                .type_params(
-                    <[_]>::into_vec(
-                        #[rustc_box]
-                        ::alloc::boxed::Box::new([
-                            ::scale_info::TypeParameter::new(
-                                "CrossAccountId",
-                                ::core::option::Option::Some(
-                                    ::scale_info::meta_type::<CrossAccountId>(),
-                                ),
-                            ),
-                        ]),
-                    ),
-                )
-                .docs(
-                    &[
-                        "Token data, stored independently from other data used to describe it",
-                        "for the convenience of database access. Notably contains the owner account address.",
-                        "# Versioning",
-                        "Changes between 1 and 2:",
-                        "- const_data: BoundedVec < u8, CustomDataLimit > was removed",
-                        "- variable_data: BoundedVec < u8, CustomDataLimit > was removed",
-                    ],
-                )
-                .composite(
-                    ::scale_info::build::Fields::named()
-                        .field(|f| {
-                            f
-                                .ty::<CrossAccountId>()
-                                .name("owner")
-                                .type_name("CrossAccountId")
-                                .docs(&[])
-                        }),
-                )
-        }
-    }
-};
-const _: () = {
-    impl<CrossAccountId> ::codec::MaxEncodedLen for ItemData<CrossAccountId>
-    where
-        CrossAccountId: ::codec::MaxEncodedLen,
-        CrossAccountId: ::codec::MaxEncodedLen,
-    {
-        fn max_encoded_len() -> ::core::primitive::usize {
-            0_usize.saturating_add(<CrossAccountId>::max_encoded_len())
-        }
-    }
-};
-impl<CrossAccountId> From<ItemDataVersion1<CrossAccountId>>
-for ItemData<CrossAccountId> {
-    fn from(old: ItemDataVersion1<CrossAccountId>) -> Self {
-        let ItemDataVersion1 { const_data, variable_data, owner } = old;
-        let _ = &const_data;
-        let _ = &variable_data;
-        Self { owner }
-    }
-}
-pub type ItemDataVersion2<CrossAccountId> = ItemData<CrossAccountId>;
-/**
-			The module that hosts all the
-			[FRAME](https://docs.substrate.io/main-docs/build/events-errors/)
-			types needed to add this pallet to a
-			runtime.
-			*/
-pub mod pallet {
-    use super::*;
-    use frame_support::{
-        Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key,
-        traits::StorageVersion,
-    };
-    use frame_system::pallet_prelude::*;
-    use up_data_structs::{CollectionId, TokenId};
-    use super::weights::WeightInfo;
-    #[scale_info(skip_type_params(T), capture_docs = "always")]
-    /**
-			Custom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)
-			of this pallet.
-			*/
-    pub enum Error<T> {
-        #[doc(hidden)]
-        #[codec(skip)]
-        __Ignore(frame_support::sp_std::marker::PhantomData<(T)>, frame_support::Never),
-        /// Not Nonfungible item data used to mint in Nonfungible collection.
-        NotNonfungibleDataUsedToMintFungibleCollectionToken,
-        /// Used amount > 1 with NFT
-        NonfungibleItemsHaveNoAmount,
-        /// Unable to burn NFT with children
-        CantBurnNftWithChildren,
-    }
-    #[allow(deprecated)]
-    const _: () = {
-        #[automatically_derived]
-        impl<T> ::codec::Encode for Error<T> {
-            fn encode_to<__CodecOutputEdqy: ::codec::Output + ?::core::marker::Sized>(
-                &self,
-                __codec_dest_edqy: &mut __CodecOutputEdqy,
-            ) {
-                match *self {
-                    Error::NotNonfungibleDataUsedToMintFungibleCollectionToken => {
-                        __codec_dest_edqy.push_byte(0usize as ::core::primitive::u8);
-                    }
-                    Error::NonfungibleItemsHaveNoAmount => {
-                        __codec_dest_edqy.push_byte(1usize as ::core::primitive::u8);
-                    }
-                    Error::CantBurnNftWithChildren => {
-                        __codec_dest_edqy.push_byte(2usize as ::core::primitive::u8);
-                    }
-                    _ => {}
-                }
-            }
-        }
-        #[automatically_derived]
-        impl<T> ::codec::EncodeLike for Error<T> {}
-    };
-    #[allow(deprecated)]
-    const _: () = {
-        #[automatically_derived]
-        impl<T> ::codec::Decode for Error<T> {
-            fn decode<__CodecInputEdqy: ::codec::Input>(
-                __codec_input_edqy: &mut __CodecInputEdqy,
-            ) -> ::core::result::Result<Self, ::codec::Error> {
-                match __codec_input_edqy
-                    .read_byte()
-                    .map_err(|e| {
-                        e.chain("Could not decode `Error`, failed to read variant byte")
-                    })?
-                {
-                    __codec_x_edqy if __codec_x_edqy
-                        == 0usize as ::core::primitive::u8 => {
-                        ::core::result::Result::Ok(
-                            Error::<
-                                T,
-                            >::NotNonfungibleDataUsedToMintFungibleCollectionToken,
-                        )
-                    }
-                    __codec_x_edqy if __codec_x_edqy
-                        == 1usize as ::core::primitive::u8 => {
-                        ::core::result::Result::Ok(
-                            Error::<T>::NonfungibleItemsHaveNoAmount,
-                        )
-                    }
-                    __codec_x_edqy if __codec_x_edqy
-                        == 2usize as ::core::primitive::u8 => {
-                        ::core::result::Result::Ok(Error::<T>::CantBurnNftWithChildren)
-                    }
-                    _ => {
-                        ::core::result::Result::Err(
-                            <_ as ::core::convert::Into<
-                                _,
-                            >>::into("Could not decode `Error`, variant doesn't exist"),
-                        )
-                    }
-                }
-            }
-        }
-    };
-    #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
-    const _: () = {
-        impl<T> ::scale_info::TypeInfo for Error<T>
-        where
-            frame_support::sp_std::marker::PhantomData<
-                (T),
-            >: ::scale_info::TypeInfo + 'static,
-            T: 'static,
-        {
-            type Identity = Self;
-            fn type_info() -> ::scale_info::Type {
-                ::scale_info::Type::builder()
-                    .path(::scale_info::Path::new("Error", "pallet_nonfungible::pallet"))
-                    .type_params(
-                        <[_]>::into_vec(
-                            #[rustc_box]
-                            ::alloc::boxed::Box::new([
-                                ::scale_info::TypeParameter::new(
-                                    "T",
-                                    ::core::option::Option::None,
-                                ),
-                            ]),
-                        ),
-                    )
-                    .docs_always(
-                        &[
-                            "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t",
-                        ],
-                    )
-                    .variant(
-                        ::scale_info::build::Variants::new()
-                            .variant(
-                                "NotNonfungibleDataUsedToMintFungibleCollectionToken",
-                                |v| {
-                                    v
-                                        .index(0usize as ::core::primitive::u8)
-                                        .docs_always(
-                                            &[
-                                                "Not Nonfungible item data used to mint in Nonfungible collection.",
-                                            ],
-                                        )
-                                },
-                            )
-                            .variant(
-                                "NonfungibleItemsHaveNoAmount",
-                                |v| {
-                                    v
-                                        .index(1usize as ::core::primitive::u8)
-                                        .docs_always(&["Used amount > 1 with NFT"])
-                                },
-                            )
-                            .variant(
-                                "CantBurnNftWithChildren",
-                                |v| {
-                                    v
-                                        .index(2usize as ::core::primitive::u8)
-                                        .docs_always(&["Unable to burn NFT with children"])
-                                },
-                            ),
-                    )
-            }
-        }
-    };
-    const _: () = {
-        impl<T> frame_support::traits::PalletError for Error<T> {
-            const MAX_ENCODED_SIZE: usize = 1;
-        }
-    };
-    /**
-			Configuration trait of this pallet.
-
-			Implement this type for a runtime in order to customize this pallet.
-			*/
-    pub trait Config: frame_system::Config + pallet_common::Config + pallet_structure::Config + pallet_evm::Config {
-        type WeightInfo: WeightInfo;
-    }
-    const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
-    /**
-			The [pallet](https://docs.substrate.io/reference/frame-pallets/#pallets) implementing
-			the on-chain logic.
-			*/
-    pub struct Pallet<T>(frame_support::sp_std::marker::PhantomData<(T)>);
-    const _: () = {
-        impl<T> core::clone::Clone for Pallet<T> {
-            fn clone(&self) -> Self {
-                Self(core::clone::Clone::clone(&self.0))
-            }
-        }
-    };
-    const _: () = {
-        impl<T> core::cmp::Eq for Pallet<T> {}
-    };
-    const _: () = {
-        impl<T> core::cmp::PartialEq for Pallet<T> {
-            fn eq(&self, other: &Self) -> bool {
-                true && self.0 == other.0
-            }
-        }
-    };
-    const _: () = {
-        impl<T> core::fmt::Debug for Pallet<T> {
-            fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
-                fmt.debug_tuple("Pallet").field(&self.0).finish()
-            }
-        }
-    };
-    /// Total amount of minted tokens in a collection.
-    #[allow(type_alias_bounds)]
-    pub type TokensMinted<T: Config> = StorageMap<
-        _GeneratedPrefixForStorageTokensMinted<T>,
-        Twox64Concat,
-        CollectionId,
-        u32,
-        ValueQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Amount of burnt tokens in a collection.
-    #[allow(type_alias_bounds)]
-    pub type TokensBurnt<T: Config> = StorageMap<
-        _GeneratedPrefixForStorageTokensBurnt<T>,
-        Twox64Concat,
-        CollectionId,
-        u32,
-        ValueQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Token data, used to partially describe a token.
-    #[allow(type_alias_bounds)]
-    pub type TokenData<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageTokenData<T>,
-        (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
-        ItemData<T::CrossAccountId>,
-        OptionQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Map of key-value pairs, describing the metadata of a token.
-    #[allow(type_alias_bounds)]
-    pub type TokenProperties<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageTokenProperties<T>,
-        (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
-        Properties,
-        ValueQuery,
-        up_data_structs::TokenProperties,
-        frame_support::traits::GetDefault,
-    >;
-    /// Custom data of a token that is serialized to bytes,
-    /// primarily reserved for on-chain operations,
-    /// normally obscured from the external users.
-    ///
-    /// Auxiliary properties are slightly different from
-    /// usual [`TokenProperties`] due to an unlimited number
-    /// and separately stored and written-to key-value pairs.
-    ///
-    /// Currently used to store RMRK data.
-    #[allow(type_alias_bounds)]
-    pub type TokenAuxProperties<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageTokenAuxProperties<T>,
-        (
-            Key<Twox64Concat, CollectionId>,
-            Key<Twox64Concat, TokenId>,
-            Key<Twox64Concat, PropertyScope>,
-            Key<Twox64Concat, PropertyKey>,
-        ),
-        AuxPropertyValue,
-        OptionQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Used to enumerate tokens owned by account.
-    #[allow(type_alias_bounds)]
-    pub type Owned<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageOwned<T>,
-        (
-            Key<Twox64Concat, CollectionId>,
-            Key<Blake2_128Concat, T::CrossAccountId>,
-            Key<Twox64Concat, TokenId>,
-        ),
-        bool,
-        ValueQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Used to enumerate token's children.
-    #[allow(type_alias_bounds)]
-    pub type TokenChildren<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageTokenChildren<T>,
-        (
-            Key<Twox64Concat, CollectionId>,
-            Key<Twox64Concat, TokenId>,
-            Key<Twox64Concat, (CollectionId, TokenId)>,
-        ),
-        bool,
-        ValueQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Amount of tokens owned by an account in a collection.
-    #[allow(type_alias_bounds)]
-    pub type AccountBalance<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageAccountBalance<T>,
-        (Key<Twox64Concat, CollectionId>, Key<Blake2_128Concat, T::CrossAccountId>),
-        u32,
-        ValueQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Allowance set by a token owner for another user to perform one of certain transactions on a token.
-    #[allow(type_alias_bounds)]
-    pub type Allowance<T: Config> = StorageNMap<
-        _GeneratedPrefixForStorageAllowance<T>,
-        (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
-        T::CrossAccountId,
-        OptionQuery,
-        frame_support::traits::GetDefault,
-        frame_support::traits::GetDefault,
-    >;
-    /// Upgrade from the old schema to properties.
-    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
-        fn on_runtime_upgrade() -> Weight {
-            StorageVersion::new(1).put::<Pallet<T>>();
-            Weight::zero()
-        }
-    }
-    impl<T: Config> Pallet<T> {
-        #[doc(hidden)]
-        pub fn pallet_constants_metadata() -> frame_support::sp_std::vec::Vec<
-            frame_support::metadata::PalletConstantMetadata,
-        > {
-            ::alloc::vec::Vec::new()
-        }
-    }
-    impl<T: Config> Pallet<T> {
-        #[doc(hidden)]
-        pub fn error_metadata() -> Option<frame_support::metadata::PalletErrorMetadata> {
-            Some(frame_support::metadata::PalletErrorMetadata {
-                ty: frame_support::scale_info::meta_type::<Error<T>>(),
-            })
-        }
-    }
-    /// Type alias to `Pallet`, to be used by `construct_runtime`.
-    ///
-    /// Generated by `pallet` attribute macro.
-    #[deprecated(note = "use `Pallet` instead")]
-    #[allow(dead_code)]
-    pub type Module<T> = Pallet<T>;
-    impl<T: Config> frame_support::traits::GetStorageVersion for Pallet<T> {
-        fn current_storage_version() -> frame_support::traits::StorageVersion {
-            STORAGE_VERSION
-        }
-        fn on_chain_storage_version() -> frame_support::traits::StorageVersion {
-            frame_support::traits::StorageVersion::get::<Self>()
-        }
-    }
-    impl<T: Config> frame_support::traits::OnGenesis for Pallet<T> {
-        fn on_genesis() {
-            let storage_version = STORAGE_VERSION;
-            storage_version.put::<Self>();
-        }
-    }
-    impl<T: Config> frame_support::traits::PalletInfoAccess for Pallet<T> {
-        fn index() -> usize {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<
-                Self,
-            >()
-                .expect(
-                    "Pallet is part of the runtime because pallet `Config` trait is \
-						implemented by the runtime",
-                )
-        }
-        fn name() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Self,
-            >()
-                .expect(
-                    "Pallet is part of the runtime because pallet `Config` trait is \
-						implemented by the runtime",
-                )
-        }
-        fn module_name() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::module_name::<
-                Self,
-            >()
-                .expect(
-                    "Pallet is part of the runtime because pallet `Config` trait is \
-						implemented by the runtime",
-                )
-        }
-        fn crate_version() -> frame_support::traits::CrateVersion {
-            frame_support::traits::CrateVersion {
-                major: 0u16,
-                minor: 1u8,
-                patch: 5u8,
-            }
-        }
-    }
-    impl<T: Config> frame_support::traits::PalletsInfoAccess for Pallet<T> {
-        fn count() -> usize {
-            1
-        }
-        fn infos() -> frame_support::sp_std::vec::Vec<
-            frame_support::traits::PalletInfoData,
-        > {
-            use frame_support::traits::PalletInfoAccess;
-            let item = frame_support::traits::PalletInfoData {
-                index: Self::index(),
-                name: Self::name(),
-                module_name: Self::module_name(),
-                crate_version: Self::crate_version(),
-            };
-            <[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([item]))
-        }
-    }
-    impl<T: Config> frame_support::traits::StorageInfoTrait for Pallet<T> {
-        fn storage_info() -> frame_support::sp_std::vec::Vec<
-            frame_support::traits::StorageInfo,
-        > {
-            #[allow(unused_mut)]
-            let mut res = ::alloc::vec::Vec::new();
-            {
-                let mut storage_info = <TokensMinted<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <TokensBurnt<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <TokenData<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <TokenProperties<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <TokenAuxProperties<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <Owned<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <TokenChildren<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <AccountBalance<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            {
-                let mut storage_info = <Allowance<
-                    T,
-                > as frame_support::traits::StorageInfoTrait>::storage_info();
-                res.append(&mut storage_info);
-            }
-            res
-        }
-    }
-    #[doc(hidden)]
-    pub mod __substrate_call_check {
-        #[doc(hidden)]
-        pub use __is_call_part_defined_0 as is_call_part_defined;
-    }
-    ///Contains one variant per dispatchable that can be called by an extrinsic.
-    #[codec(encode_bound())]
-    #[codec(decode_bound())]
-    #[scale_info(skip_type_params(T), capture_docs = "always")]
-    #[allow(non_camel_case_types)]
-    pub enum Call<T: Config> {
-        #[doc(hidden)]
-        #[codec(skip)]
-        __Ignore(frame_support::sp_std::marker::PhantomData<(T,)>, frame_support::Never),
-    }
-    const _: () = {
-        impl<T: Config> core::fmt::Debug for Call<T> {
-            fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
-                match *self {
-                    Self::__Ignore(ref _0, ref _1) => {
-                        fmt.debug_tuple("Call::__Ignore").field(&_0).field(&_1).finish()
-                    }
-                }
-            }
-        }
-    };
-    const _: () = {
-        impl<T: Config> core::clone::Clone for Call<T> {
-            fn clone(&self) -> Self {
-                match self {
-                    Self::__Ignore(ref _0, ref _1) => {
-                        Self::__Ignore(
-                            core::clone::Clone::clone(_0),
-                            core::clone::Clone::clone(_1),
-                        )
-                    }
-                }
-            }
-        }
-    };
-    const _: () = {
-        impl<T: Config> core::cmp::Eq for Call<T> {}
-    };
-    const _: () = {
-        impl<T: Config> core::cmp::PartialEq for Call<T> {
-            fn eq(&self, other: &Self) -> bool {
-                match (self, other) {
-                    (Self::__Ignore(_0, _1), Self::__Ignore(_0_other, _1_other)) => {
-                        true && _0 == _0_other && _1 == _1_other
-                    }
-                }
-            }
-        }
-    };
-    #[allow(deprecated)]
-    const _: () = {
-        #[allow(non_camel_case_types)]
-        #[automatically_derived]
-        impl<T: Config> ::codec::Encode for Call<T> {}
-        #[automatically_derived]
-        impl<T: Config> ::codec::EncodeLike for Call<T> {}
-    };
-    #[allow(deprecated)]
-    const _: () = {
-        #[allow(non_camel_case_types)]
-        #[automatically_derived]
-        impl<T: Config> ::codec::Decode for Call<T> {
-            fn decode<__CodecInputEdqy: ::codec::Input>(
-                __codec_input_edqy: &mut __CodecInputEdqy,
-            ) -> ::core::result::Result<Self, ::codec::Error> {
-                match __codec_input_edqy
-                    .read_byte()
-                    .map_err(|e| {
-                        e.chain("Could not decode `Call`, failed to read variant byte")
-                    })?
-                {
-                    _ => {
-                        ::core::result::Result::Err(
-                            <_ as ::core::convert::Into<
-                                _,
-                            >>::into("Could not decode `Call`, variant doesn't exist"),
-                        )
-                    }
-                }
-            }
-        }
-    };
-    #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
-    const _: () = {
-        impl<T: Config> ::scale_info::TypeInfo for Call<T>
-        where
-            frame_support::sp_std::marker::PhantomData<
-                (T,),
-            >: ::scale_info::TypeInfo + 'static,
-            T: Config + 'static,
-        {
-            type Identity = Self;
-            fn type_info() -> ::scale_info::Type {
-                ::scale_info::Type::builder()
-                    .path(::scale_info::Path::new("Call", "pallet_nonfungible::pallet"))
-                    .type_params(
-                        <[_]>::into_vec(
-                            #[rustc_box]
-                            ::alloc::boxed::Box::new([
-                                ::scale_info::TypeParameter::new(
-                                    "T",
-                                    ::core::option::Option::None,
-                                ),
-                            ]),
-                        ),
-                    )
-                    .docs_always(
-                        &[
-                            "Contains one variant per dispatchable that can be called by an extrinsic.",
-                        ],
-                    )
-                    .variant(::scale_info::build::Variants::new())
-            }
-        }
-    };
-    impl<T: Config> Call<T> {}
-    impl<T: Config> frame_support::dispatch::GetDispatchInfo for Call<T> {
-        fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo {
-            match *self {
-                Self::__Ignore(_, _) => {
-                    ::core::panicking::panic_fmt(
-                        ::core::fmt::Arguments::new_v1(
-                            &["internal error: entered unreachable code: "],
-                            &[
-                                ::core::fmt::ArgumentV1::new_display(
-                                    &::core::fmt::Arguments::new_v1(
-                                        &["__Ignore cannot be used"],
-                                        &[],
-                                    ),
-                                ),
-                            ],
-                        ),
-                    )
-                }
-            }
-        }
-    }
-    impl<T: Config> frame_support::dispatch::GetCallName for Call<T> {
-        fn get_call_name(&self) -> &'static str {
-            match *self {
-                Self::__Ignore(_, _) => {
-                    ::core::panicking::panic_fmt(
-                        ::core::fmt::Arguments::new_v1(
-                            &["internal error: entered unreachable code: "],
-                            &[
-                                ::core::fmt::ArgumentV1::new_display(
-                                    &::core::fmt::Arguments::new_v1(
-                                        &["__PhantomItem cannot be used."],
-                                        &[],
-                                    ),
-                                ),
-                            ],
-                        ),
-                    )
-                }
-            }
-        }
-        fn get_call_names() -> &'static [&'static str] {
-            &[]
-        }
-    }
-    impl<T: Config> frame_support::traits::UnfilteredDispatchable for Call<T> {
-        type Origin = frame_system::pallet_prelude::OriginFor<T>;
-        fn dispatch_bypass_filter(
-            self,
-            origin: Self::Origin,
-        ) -> frame_support::dispatch::DispatchResultWithPostInfo {
-            match self {
-                Self::__Ignore(_, _) => {
-                    let _ = origin;
-                    ::core::panicking::panic_fmt(
-                        ::core::fmt::Arguments::new_v1(
-                            &["internal error: entered unreachable code: "],
-                            &[
-                                ::core::fmt::ArgumentV1::new_display(
-                                    &::core::fmt::Arguments::new_v1(
-                                        &["__PhantomItem cannot be used."],
-                                        &[],
-                                    ),
-                                ),
-                            ],
-                        ),
-                    );
-                }
-            }
-        }
-    }
-    impl<T: Config> frame_support::dispatch::Callable<T> for Pallet<T> {
-        type Call = Call<T>;
-    }
-    impl<T: Config> Pallet<T> {
-        #[doc(hidden)]
-        pub fn call_functions() -> frame_support::metadata::PalletCallMetadata {
-            frame_support::scale_info::meta_type::<Call<T>>().into()
-        }
-    }
-    impl<T: Config> frame_support::sp_std::fmt::Debug for Error<T> {
-        fn fmt(
-            &self,
-            f: &mut frame_support::sp_std::fmt::Formatter<'_>,
-        ) -> frame_support::sp_std::fmt::Result {
-            f.write_str(self.as_str())
-        }
-    }
-    impl<T: Config> Error<T> {
-        #[doc(hidden)]
-        pub fn as_str(&self) -> &'static str {
-            match &self {
-                Self::__Ignore(_, _) => {
-                    ::core::panicking::panic_fmt(
-                        ::core::fmt::Arguments::new_v1(
-                            &["internal error: entered unreachable code: "],
-                            &[
-                                ::core::fmt::ArgumentV1::new_display(
-                                    &::core::fmt::Arguments::new_v1(
-                                        &["`__Ignore` can never be constructed"],
-                                        &[],
-                                    ),
-                                ),
-                            ],
-                        ),
-                    )
-                }
-                Self::NotNonfungibleDataUsedToMintFungibleCollectionToken => {
-                    "NotNonfungibleDataUsedToMintFungibleCollectionToken"
-                }
-                Self::NonfungibleItemsHaveNoAmount => "NonfungibleItemsHaveNoAmount",
-                Self::CantBurnNftWithChildren => "CantBurnNftWithChildren",
-            }
-        }
-    }
-    impl<T: Config> From<Error<T>> for &'static str {
-        fn from(err: Error<T>) -> &'static str {
-            err.as_str()
-        }
-    }
-    impl<T: Config> From<Error<T>> for frame_support::sp_runtime::DispatchError {
-        fn from(err: Error<T>) -> Self {
-            use frame_support::codec::Encode;
-            let index = <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<
-                Pallet<T>,
-            >()
-                .expect("Every active module has an index in the runtime; qed") as u8;
-            let mut encoded = err.encode();
-            encoded.resize(frame_support::MAX_MODULE_ERROR_ENCODED_SIZE, 0);
-            frame_support::sp_runtime::DispatchError::Module(frame_support::sp_runtime::ModuleError {
-                index,
-                error: TryInto::try_into(encoded)
-                    .expect(
-                        "encoded error is resized to be equal to the maximum encoded error size; qed",
-                    ),
-                message: Some(err.as_str()),
-            })
-        }
-    }
-    pub use __tt_error_token_1 as tt_error_token;
-    #[doc(hidden)]
-    pub mod __substrate_event_check {
-        #[doc(hidden)]
-        pub use __is_event_part_defined_2 as is_event_part_defined;
-    }
-    impl<T: Config> Pallet<T> {
-        #[doc(hidden)]
-        pub fn storage_metadata() -> frame_support::metadata::PalletStorageMetadata {
-            frame_support::metadata::PalletStorageMetadata {
-                prefix: <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                    Pallet<T>,
-                >()
-                    .expect("Every active pallet has a name in the runtime; qed"),
-                entries: {
-                    #[allow(unused_mut)]
-                    let mut entries = ::alloc::vec::Vec::new();
-                    {
-                        <TokensMinted<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Total amount of minted tokens in a collection.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <TokensBurnt<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Amount of burnt tokens in a collection.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <TokenData<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Token data, used to partially describe a token.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <TokenProperties<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Map of key-value pairs, describing the metadata of a token.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <TokenAuxProperties<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Custom data of a token that is serialized to bytes,",
-                                    " primarily reserved for on-chain operations,",
-                                    " normally obscured from the external users.",
-                                    "",
-                                    " Auxiliary properties are slightly different from",
-                                    " usual [`TokenProperties`] due to an unlimited number",
-                                    " and separately stored and written-to key-value pairs.",
-                                    "",
-                                    " Currently used to store RMRK data.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <Owned<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Used to enumerate tokens owned by account.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <TokenChildren<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Used to enumerate token\'s children.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <AccountBalance<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Amount of tokens owned by an account in a collection.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    {
-                        <Allowance<
-                            T,
-                        > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
-                            <[_]>::into_vec(
-                                #[rustc_box]
-                                ::alloc::boxed::Box::new([
-                                    " Allowance set by a token owner for another user to perform one of certain transactions on a token.",
-                                ]),
-                            ),
-                            &mut entries,
-                        );
-                    }
-                    entries
-                },
-            }
-        }
-    }
-    impl<T: Config> Pallet<T> {
-        /// Map of key-value pairs, describing the metadata of a token.
-        pub fn token_properties<KArg>(key: KArg) -> Properties
-        where
-            KArg: frame_support::storage::types::EncodeLikeTuple<
-                    <(
-                        Key<Twox64Concat, CollectionId>,
-                        Key<Twox64Concat, TokenId>,
-                    ) as frame_support::storage::types::KeyGenerator>::KArg,
-                > + frame_support::storage::types::TupleToEncodedIter,
-        {
-            <TokenProperties<
-                T,
-            > as frame_support::storage::StorageNMap<
-                (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
-                Properties,
-            >>::get(key)
-        }
-    }
-    impl<T: Config> Pallet<T> {
-        /// Custom data of a token that is serialized to bytes,
-        /// primarily reserved for on-chain operations,
-        /// normally obscured from the external users.
-        ///
-        /// Auxiliary properties are slightly different from
-        /// usual [`TokenProperties`] due to an unlimited number
-        /// and separately stored and written-to key-value pairs.
-        ///
-        /// Currently used to store RMRK data.
-        pub fn token_aux_property<KArg>(key: KArg) -> Option<AuxPropertyValue>
-        where
-            KArg: frame_support::storage::types::EncodeLikeTuple<
-                    <(
-                        Key<Twox64Concat, CollectionId>,
-                        Key<Twox64Concat, TokenId>,
-                        Key<Twox64Concat, PropertyScope>,
-                        Key<Twox64Concat, PropertyKey>,
-                    ) as frame_support::storage::types::KeyGenerator>::KArg,
-                > + frame_support::storage::types::TupleToEncodedIter,
-        {
-            <TokenAuxProperties<
-                T,
-            > as frame_support::storage::StorageNMap<
-                (
-                    Key<Twox64Concat, CollectionId>,
-                    Key<Twox64Concat, TokenId>,
-                    Key<Twox64Concat, PropertyScope>,
-                    Key<Twox64Concat, PropertyKey>,
-                ),
-                AuxPropertyValue,
-            >>::get(key)
-        }
-    }
-    impl<T: Config> Pallet<T> {
-        /// Used to enumerate token's children.
-        pub fn token_children<KArg>(key: KArg) -> bool
-        where
-            KArg: frame_support::storage::types::EncodeLikeTuple<
-                    <(
-                        Key<Twox64Concat, CollectionId>,
-                        Key<Twox64Concat, TokenId>,
-                        Key<Twox64Concat, (CollectionId, TokenId)>,
-                    ) as frame_support::storage::types::KeyGenerator>::KArg,
-                > + frame_support::storage::types::TupleToEncodedIter,
-        {
-            <TokenChildren<
-                T,
-            > as frame_support::storage::StorageNMap<
-                (
-                    Key<Twox64Concat, CollectionId>,
-                    Key<Twox64Concat, TokenId>,
-                    Key<Twox64Concat, (CollectionId, TokenId)>,
-                ),
-                bool,
-            >>::get(key)
-        }
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageTokensMinted<T>(
-        core::marker::PhantomData<(T,)>,
-    );
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageTokensMinted<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "TokensMinted";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageTokensBurnt<T>(core::marker::PhantomData<(T,)>);
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageTokensBurnt<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "TokensBurnt";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageTokenData<T>(core::marker::PhantomData<(T,)>);
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageTokenData<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "TokenData";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageTokenProperties<T>(
-        core::marker::PhantomData<(T,)>,
-    );
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageTokenProperties<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "TokenProperties";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageTokenAuxProperties<T>(
-        core::marker::PhantomData<(T,)>,
-    );
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageTokenAuxProperties<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "TokenAuxProperties";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageOwned<T>(core::marker::PhantomData<(T,)>);
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageOwned<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "Owned";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageTokenChildren<T>(
-        core::marker::PhantomData<(T,)>,
-    );
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageTokenChildren<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "TokenChildren";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageAccountBalance<T>(
-        core::marker::PhantomData<(T,)>,
-    );
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageAccountBalance<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "AccountBalance";
-    }
-    #[doc(hidden)]
-    pub struct _GeneratedPrefixForStorageAllowance<T>(core::marker::PhantomData<(T,)>);
-    impl<T: Config> frame_support::traits::StorageInstance
-    for _GeneratedPrefixForStorageAllowance<T> {
-        fn pallet_prefix() -> &'static str {
-            <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Pallet<T>,
-            >()
-                .expect("Every active pallet has a name in the runtime; qed")
-        }
-        const STORAGE_PREFIX: &'static str = "Allowance";
-    }
-    #[doc(hidden)]
-    pub mod __substrate_inherent_check {
-        #[doc(hidden)]
-        pub use __is_inherent_part_defined_3 as is_inherent_part_defined;
-    }
-    /// Hidden instance generated to be internally used when module is used without
-    /// instance.
-    #[doc(hidden)]
-    pub type __InherentHiddenInstance = ();
-    pub(super) trait Store {
-        type TokensMinted;
-        type TokensBurnt;
-        type TokenData;
-        type TokenProperties;
-        type TokenAuxProperties;
-        type Owned;
-        type TokenChildren;
-        type AccountBalance;
-        type Allowance;
-    }
-    impl<T: Config> Store for Pallet<T> {
-        type TokensMinted = TokensMinted<T>;
-        type TokensBurnt = TokensBurnt<T>;
-        type TokenData = TokenData<T>;
-        type TokenProperties = TokenProperties<T>;
-        type TokenAuxProperties = TokenAuxProperties<T>;
-        type Owned = Owned<T>;
-        type TokenChildren = TokenChildren<T>;
-        type AccountBalance = AccountBalance<T>;
-        type Allowance = Allowance<T>;
-    }
-    impl<
-        T: Config,
-    > frame_support::traits::OnFinalize<<T as frame_system::Config>::BlockNumber>
-    for Pallet<T> {
-        fn on_finalize(n: <T as frame_system::Config>::BlockNumber) {
-            let __within_span__ = {
-                use ::tracing::__macro_support::Callsite as _;
-                static CALLSITE: ::tracing::callsite::DefaultCallsite = {
-                    static META: ::tracing::Metadata<'static> = {
-                        ::tracing_core::metadata::Metadata::new(
-                            "on_finalize",
-                            "pallet_nonfungible::pallet",
-                            ::tracing::Level::TRACE,
-                            Some("pallets/nonfungible/src/lib.rs"),
-                            Some(147u32),
-                            Some("pallet_nonfungible::pallet"),
-                            ::tracing_core::field::FieldSet::new(
-                                &[],
-                                ::tracing_core::callsite::Identifier(&CALLSITE),
-                            ),
-                            ::tracing::metadata::Kind::SPAN,
-                        )
-                    };
-                    ::tracing::callsite::DefaultCallsite::new(&META)
-                };
-                let mut interest = ::tracing::subscriber::Interest::never();
-                if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
-                    && ::tracing::Level::TRACE
-                        <= ::tracing::level_filters::LevelFilter::current()
-                    && {
-                        interest = CALLSITE.interest();
-                        !interest.is_never()
-                    }
-                    && ::tracing::__macro_support::__is_enabled(
-                        CALLSITE.metadata(),
-                        interest,
-                    )
-                {
-                    let meta = CALLSITE.metadata();
-                    ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })
-                } else {
-                    let span = ::tracing::__macro_support::__disabled_span(
-                        CALLSITE.metadata(),
-                    );
-                    {};
-                    span
-                }
-            };
-            let __tracing_guard__ = __within_span__.enter();
-            <Self as frame_support::traits::Hooks<
-                <T as frame_system::Config>::BlockNumber,
-            >>::on_finalize(n)
-        }
-    }
-    impl<
-        T: Config,
-    > frame_support::traits::OnIdle<<T as frame_system::Config>::BlockNumber>
-    for Pallet<T> {
-        fn on_idle(
-            n: <T as frame_system::Config>::BlockNumber,
-            remaining_weight: frame_support::weights::Weight,
-        ) -> frame_support::weights::Weight {
-            <Self as frame_support::traits::Hooks<
-                <T as frame_system::Config>::BlockNumber,
-            >>::on_idle(n, remaining_weight)
-        }
-    }
-    impl<
-        T: Config,
-    > frame_support::traits::OnInitialize<<T as frame_system::Config>::BlockNumber>
-    for Pallet<T> {
-        fn on_initialize(
-            n: <T as frame_system::Config>::BlockNumber,
-        ) -> frame_support::weights::Weight {
-            let __within_span__ = {
-                use ::tracing::__macro_support::Callsite as _;
-                static CALLSITE: ::tracing::callsite::DefaultCallsite = {
-                    static META: ::tracing::Metadata<'static> = {
-                        ::tracing_core::metadata::Metadata::new(
-                            "on_initialize",
-                            "pallet_nonfungible::pallet",
-                            ::tracing::Level::TRACE,
-                            Some("pallets/nonfungible/src/lib.rs"),
-                            Some(147u32),
-                            Some("pallet_nonfungible::pallet"),
-                            ::tracing_core::field::FieldSet::new(
-                                &[],
-                                ::tracing_core::callsite::Identifier(&CALLSITE),
-                            ),
-                            ::tracing::metadata::Kind::SPAN,
-                        )
-                    };
-                    ::tracing::callsite::DefaultCallsite::new(&META)
-                };
-                let mut interest = ::tracing::subscriber::Interest::never();
-                if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
-                    && ::tracing::Level::TRACE
-                        <= ::tracing::level_filters::LevelFilter::current()
-                    && {
-                        interest = CALLSITE.interest();
-                        !interest.is_never()
-                    }
-                    && ::tracing::__macro_support::__is_enabled(
-                        CALLSITE.metadata(),
-                        interest,
-                    )
-                {
-                    let meta = CALLSITE.metadata();
-                    ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })
-                } else {
-                    let span = ::tracing::__macro_support::__disabled_span(
-                        CALLSITE.metadata(),
-                    );
-                    {};
-                    span
-                }
-            };
-            let __tracing_guard__ = __within_span__.enter();
-            <Self as frame_support::traits::Hooks<
-                <T as frame_system::Config>::BlockNumber,
-            >>::on_initialize(n)
-        }
-    }
-    impl<T: Config> frame_support::traits::OnRuntimeUpgrade for Pallet<T> {
-        fn on_runtime_upgrade() -> frame_support::weights::Weight {
-            let __within_span__ = {
-                use ::tracing::__macro_support::Callsite as _;
-                static CALLSITE: ::tracing::callsite::DefaultCallsite = {
-                    static META: ::tracing::Metadata<'static> = {
-                        ::tracing_core::metadata::Metadata::new(
-                            "on_runtime_update",
-                            "pallet_nonfungible::pallet",
-                            ::tracing::Level::TRACE,
-                            Some("pallets/nonfungible/src/lib.rs"),
-                            Some(147u32),
-                            Some("pallet_nonfungible::pallet"),
-                            ::tracing_core::field::FieldSet::new(
-                                &[],
-                                ::tracing_core::callsite::Identifier(&CALLSITE),
-                            ),
-                            ::tracing::metadata::Kind::SPAN,
-                        )
-                    };
-                    ::tracing::callsite::DefaultCallsite::new(&META)
-                };
-                let mut interest = ::tracing::subscriber::Interest::never();
-                if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
-                    && ::tracing::Level::TRACE
-                        <= ::tracing::level_filters::LevelFilter::current()
-                    && {
-                        interest = CALLSITE.interest();
-                        !interest.is_never()
-                    }
-                    && ::tracing::__macro_support::__is_enabled(
-                        CALLSITE.metadata(),
-                        interest,
-                    )
-                {
-                    let meta = CALLSITE.metadata();
-                    ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })
-                } else {
-                    let span = ::tracing::__macro_support::__disabled_span(
-                        CALLSITE.metadata(),
-                    );
-                    {};
-                    span
-                }
-            };
-            let __tracing_guard__ = __within_span__.enter();
-            let pallet_name = <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
-                Self,
-            >()
-                .unwrap_or("<unknown pallet name>");
-            {
-                let lvl = ::log::Level::Info;
-                if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {
-                    ::log::__private_api_log(
-                        ::core::fmt::Arguments::new_v1(
-                            &[
-                                "\u{26a0}\u{fe0f} ",
-                                " declares internal migrations (which *might* execute). On-chain `",
-                                "` vs current storage version `",
-                                "`",
-                            ],
-                            &[
-                                ::core::fmt::ArgumentV1::new_display(&pallet_name),
-                                ::core::fmt::ArgumentV1::new_debug(
-                                    &<Self as frame_support::traits::GetStorageVersion>::on_chain_storage_version(),
-                                ),
-                                ::core::fmt::ArgumentV1::new_debug(
-                                    &<Self as frame_support::traits::GetStorageVersion>::current_storage_version(),
-                                ),
-                            ],
-                        ),
-                        lvl,
-                        &(
-                            frame_support::LOG_TARGET,
-                            "pallet_nonfungible::pallet",
-                            "pallets/nonfungible/src/lib.rs",
-                            147u32,
-                        ),
-                        ::log::__private_api::Option::None,
-                    );
-                }
-            };
-            <Self as frame_support::traits::Hooks<
-                <T as frame_system::Config>::BlockNumber,
-            >>::on_runtime_upgrade()
-        }
-    }
-    impl<
-        T: Config,
-    > frame_support::traits::OffchainWorker<<T as frame_system::Config>::BlockNumber>
-    for Pallet<T> {
-        fn offchain_worker(n: <T as frame_system::Config>::BlockNumber) {
-            <Self as frame_support::traits::Hooks<
-                <T as frame_system::Config>::BlockNumber,
-            >>::offchain_worker(n)
-        }
-    }
-    impl<T: Config> frame_support::traits::IntegrityTest for Pallet<T> {
-        fn integrity_test() {
-            <Self as frame_support::traits::Hooks<
-                <T as frame_system::Config>::BlockNumber,
-            >>::integrity_test()
-        }
-    }
-    #[doc(hidden)]
-    pub mod __substrate_genesis_config_check {
-        #[doc(hidden)]
-        pub use __is_genesis_config_defined_4 as is_genesis_config_defined;
-        #[doc(hidden)]
-        pub use __is_std_enabled_for_genesis_4 as is_std_enabled_for_genesis;
-    }
-    #[doc(hidden)]
-    pub mod __substrate_origin_check {
-        #[doc(hidden)]
-        pub use __is_origin_part_defined_5 as is_origin_part_defined;
-    }
-    #[doc(hidden)]
-    pub mod __substrate_validate_unsigned_check {
-        #[doc(hidden)]
-        pub use __is_validate_unsigned_part_defined_6 as is_validate_unsigned_part_defined;
-    }
-    pub use __tt_default_parts_7 as tt_default_parts;
-}
-pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
-impl<T: Config> NonfungibleHandle<T> {
-    pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {
-        Self(inner)
-    }
-    pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {
-        self.0
-    }
-    pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {
-        &mut self.0
-    }
-}
-impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {
-    fn recorder(&self) -> &SubstrateRecorder<T> {
-        self.0.recorder()
-    }
-    fn into_recorder(self) -> SubstrateRecorder<T> {
-        self.0.into_recorder()
-    }
-}
-impl<T: Config> Deref for NonfungibleHandle<T> {
-    type Target = pallet_common::CollectionHandle<T>;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-impl<T: Config> Pallet<T> {
-    /// Get number of NFT tokens in collection.
-    pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {
-        <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)
-    }
-    /// Check that NFT token exists.
-    ///
-    /// - `token`: Token ID.
-    pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {
-        <TokenData<T>>::contains_key((collection.id, token))
-    }
-    /// Set the token property with the scope.
-    ///
-    /// - `property`: Contains key-value pair.
-    pub fn set_scoped_token_property(
-        collection_id: CollectionId,
-        token_id: TokenId,
-        scope: PropertyScope,
-        property: Property,
-    ) -> DispatchResult {
-        TokenProperties::<
-            T,
-        >::try_mutate(
-                (collection_id, token_id),
-                |properties| {
-                    properties.try_scoped_set(scope, property.key, property.value)
-                },
-            )
-            .map_err(<CommonError<T>>::from)?;
-        Ok(())
-    }
-    /// Batch operation to set multiple properties with the same scope.
-    pub fn set_scoped_token_properties(
-        collection_id: CollectionId,
-        token_id: TokenId,
-        scope: PropertyScope,
-        properties: impl Iterator<Item = Property>,
-    ) -> DispatchResult {
-        TokenProperties::<
-            T,
-        >::try_mutate(
-                (collection_id, token_id),
-                |stored_properties| {
-                    stored_properties.try_scoped_set_from_iter(scope, properties)
-                },
-            )
-            .map_err(<CommonError<T>>::from)?;
-        Ok(())
-    }
-    /// Add or edit auxiliary data for the property.
-    ///
-    /// - `f`: function that adds or edits auxiliary data.
-    pub fn try_mutate_token_aux_property<R, E>(
-        collection_id: CollectionId,
-        token_id: TokenId,
-        scope: PropertyScope,
-        key: PropertyKey,
-        f: impl FnOnce(&mut Option<AuxPropertyValue>) -> Result<R, E>,
-    ) -> Result<R, E> {
-        <TokenAuxProperties<T>>::try_mutate((collection_id, token_id, scope, key), f)
-    }
-    /// Remove auxiliary data for the property.
-    pub fn remove_token_aux_property(
-        collection_id: CollectionId,
-        token_id: TokenId,
-        scope: PropertyScope,
-        key: PropertyKey,
-    ) {
-        <TokenAuxProperties<T>>::remove((collection_id, token_id, scope, key));
-    }
-    /// Get all auxiliary data in a given scope.
-    ///
-    /// Returns iterator over Property Key - Data pairs.
-    pub fn iterate_token_aux_properties(
-        collection_id: CollectionId,
-        token_id: TokenId,
-        scope: PropertyScope,
-    ) -> impl Iterator<Item = (PropertyKey, AuxPropertyValue)> {
-        <TokenAuxProperties<T>>::iter_prefix((collection_id, token_id, scope))
-    }
-    /// Get ID of the last minted token
-    pub fn current_token_id(collection_id: CollectionId) -> TokenId {
-        TokenId(<TokensMinted<T>>::get(collection_id))
-    }
-}
-impl<T: Config> Pallet<T> {
-    /// Create NFT collection
-    ///
-    /// `init_collection` will take non-refundable deposit for collection creation.
-    ///
-    /// - `data`: Contains settings for collection limits and permissions.
-    pub fn init_collection(
-        owner: T::CrossAccountId,
-        payer: T::CrossAccountId,
-        data: CreateCollectionData<T::AccountId>,
-        is_external: bool,
-    ) -> Result<CollectionId, DispatchError> {
-        <PalletCommon<
-            T,
-        >>::init_collection(
-            owner,
-            payer,
-            data,
-            CollectionFlags {
-                external: is_external,
-                ..Default::default()
-            },
-        )
-    }
-    /// Destroy NFT collection
-    ///
-    /// `destroy_collection` will throw error if collection contains any tokens.
-    /// Only owner can destroy collection.
-    pub fn destroy_collection(
-        collection: NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-    ) -> DispatchResult {
-        let id = collection.id;
-        if Self::collection_has_tokens(id) {
-            return Err(<CommonError<T>>::CantDestroyNotEmptyCollection.into());
-        }
-        PalletCommon::destroy_collection(collection.0, sender)?;
-        let _ = <TokenData<T>>::clear_prefix((id,), u32::MAX, None);
-        let _ = <TokenChildren<T>>::clear_prefix((id,), u32::MAX, None);
-        let _ = <Owned<T>>::clear_prefix((id,), u32::MAX, None);
-        <TokensMinted<T>>::remove(id);
-        <TokensBurnt<T>>::remove(id);
-        let _ = <Allowance<T>>::clear_prefix((id,), u32::MAX, None);
-        let _ = <AccountBalance<T>>::clear_prefix((id,), u32::MAX, None);
-        Ok(())
-    }
-    /// Burn NFT token
-    ///
-    /// `burn` removes `token` from the `collection`, from it's owner and from the parent token
-    /// if the token is nested.
-    /// Only the owner can `burn` the token. The `token` shouldn't have any nested tokens.
-    /// Also removes all corresponding properties and auxiliary properties.
-    ///
-    /// - `token`: Token that should be burned
-    /// - `collection`: Collection that contains the token
-    pub fn burn(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token: TokenId,
-    ) -> DispatchResult {
-        let token_data = <TokenData<T>>::get((collection.id, token))
-            .ok_or(<CommonError<T>>::TokenNotFound)?;
-        {
-            if !(&token_data.owner == sender) {
-                { return Err(<CommonError<T>>::NoPermission.into()) };
-            }
-        };
-        if collection.permissions.access() == AccessMode::AllowList {
-            collection.check_allowlist(sender)?;
-        }
-        if Self::token_has_children(collection.id, token) {
-            return Err(<Error<T>>::CantBurnNftWithChildren.into());
-        }
-        let burnt = <TokensBurnt<T>>::get(collection.id)
-            .checked_add(1)
-            .ok_or(ArithmeticError::Overflow)?;
-        let balance = <AccountBalance<T>>::get((collection.id, token_data.owner.clone()))
-            .checked_sub(1)
-            .ok_or(ArithmeticError::Overflow)?;
-        if balance == 0 {
-            <AccountBalance<T>>::remove((collection.id, token_data.owner.clone()));
-        } else {
-            <AccountBalance<
-                T,
-            >>::insert((collection.id, token_data.owner.clone()), balance);
-        }
-        <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);
-        <Owned<T>>::remove((collection.id, &token_data.owner, token));
-        <TokensBurnt<T>>::insert(collection.id, burnt);
-        <TokenData<T>>::remove((collection.id, token));
-        <TokenProperties<T>>::remove((collection.id, token));
-        let _ = <TokenAuxProperties<
-            T,
-        >>::clear_prefix((collection.id, token), u32::MAX, None);
-        let old_spender = <Allowance<T>>::take((collection.id, token));
-        if let Some(old_spender) = old_spender {
-            <PalletCommon<
-                T,
-            >>::deposit_event(
-                CommonEvent::Approved(
-                    collection.id,
-                    token,
-                    token_data.owner.clone(),
-                    old_spender,
-                    0,
-                ),
-            );
-        }
-        <PalletEvm<
-            T,
-        >>::deposit_log(
-            ERC721Events::Transfer {
-                from: *token_data.owner.as_eth(),
-                to: H160::default(),
-                token_id: token.into(),
-            }
-                .to_log(collection_id_to_address(collection.id)),
-        );
-        <PalletCommon<
-            T,
-        >>::deposit_event(
-            CommonEvent::ItemDestroyed(collection.id, token, token_data.owner, 1),
-        );
-        Ok(())
-    }
-    /// Same as [`burn`] but burns all the tokens that are nested in the token first
-    ///
-    /// - `self_budget`: Limit for searching children in depth.
-    /// - `breadth_budget`: Limit of breadth of searching children.
-    ///
-    /// [`burn`]: struct.Pallet.html#method.burn
-    pub fn burn_recursively(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token: TokenId,
-        self_budget: &dyn Budget,
-        breadth_budget: &dyn Budget,
-    ) -> DispatchResultWithPostInfo {
-        use frame_support::storage::{with_transaction, TransactionOutcome};
-        with_transaction(|| {
-            let r = (|| {
-                {
-                    {
-                        if !self_budget.consume() {
-                            { return Err(<StructureError<T>>::DepthLimit.into()) };
-                        }
-                    };
-                    let current_token_account = T::CrossTokenAddressMapping::token_to_address(
-                        collection.id,
-                        token,
-                    );
-                    let mut weight = Weight::zero();
-                    for ((collection, token), _) in <TokenChildren<
-                        T,
-                    >>::iter_prefix((collection.id, token)) {
-                        {
-                            if !breadth_budget.consume() {
-                                { return Err(<StructureError<T>>::BreadthLimit.into()) };
-                            }
-                        };
-                        let PostDispatchInfo { actual_weight, .. } = <PalletStructure<
-                            T,
-                        >>::burn_item_recursively(
-                            current_token_account.clone(),
-                            collection,
-                            token,
-                            self_budget,
-                            breadth_budget,
-                        )?;
-                        if let Some(actual_weight) = actual_weight {
-                            weight = weight.saturating_add(actual_weight);
-                        }
-                    }
-                    Self::burn(collection, sender, token)?;
-                    DispatchResultWithPostInfo::Ok(PostDispatchInfo {
-                        actual_weight: Some(weight + <SelfWeightOf<T>>::burn_item()),
-                        pays_fee: Pays::Yes,
-                    })
-                }
-            })();
-            if r.is_ok() {
-                TransactionOutcome::Commit(r)
-            } else {
-                TransactionOutcome::Rollback(r)
-            }
-        })
-    }
-    /// Batch operation to add, edit or remove properties for the token
-    ///
-    /// All affected properties should have mutable permission and sender should have
-    /// permission to edit those properties.
-    ///
-    /// - `nesting_budget`: Limit for searching parents in depth to check ownership.
-    /// - `is_token_create`: Indicates that method is called during token initialization.
-    ///   Allows to bypass ownership check.
-    fn modify_token_properties(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token_id: TokenId,
-        properties: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,
-        is_token_create: bool,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        use frame_support::storage::{with_transaction, TransactionOutcome};
-        with_transaction(|| {
-            let r = (|| {
-                {
-                    let mut collection_admin_status = None;
-                    let mut token_owner_result = None;
-                    let mut is_collection_admin = || {
-                        *collection_admin_status
-                            .get_or_insert_with(|| collection.is_owner_or_admin(sender))
-                    };
-                    let mut is_token_owner = || {
-                        *token_owner_result
-                            .get_or_insert_with(|| -> Result<bool, DispatchError> {
-                                let is_owned = <PalletStructure<
-                                    T,
-                                >>::check_indirectly_owned(
-                                    sender.clone(),
-                                    collection.id,
-                                    token_id,
-                                    None,
-                                    nesting_budget,
-                                )?;
-                                Ok(is_owned)
-                            })
-                    };
-                    for (key, value) in properties {
-                        let permission = <PalletCommon<
-                            T,
-                        >>::property_permissions(collection.id)
-                            .get(&key)
-                            .cloned()
-                            .unwrap_or_else(PropertyPermission::none);
-                        let is_property_exists = TokenProperties::<
-                            T,
-                        >::get((collection.id, token_id))
-                            .get(&key)
-                            .is_some();
-                        match permission {
-                            PropertyPermission {
-                                mutable: false,
-                                ..
-                            } if is_property_exists => {
-                                return Err(<CommonError<T>>::NoPermission.into());
-                            }
-                            PropertyPermission { collection_admin, token_owner, .. } => {
-                                if is_token_create && (collection_admin || token_owner)
-                                    && value.is_some()
-                                {} else if collection_admin && is_collection_admin()
-                                {} else if token_owner && is_token_owner()? {} else {
-                                    { return Err(<CommonError<T>>::NoPermission.into()) };
-                                }
-                            }
-                        }
-                        match value {
-                            Some(value) => {
-                                <TokenProperties<
-                                    T,
-                                >>::try_mutate(
-                                        (collection.id, token_id),
-                                        |properties| { properties.try_set(key.clone(), value) },
-                                    )
-                                    .map_err(<CommonError<T>>::from)?;
-                                <PalletCommon<
-                                    T,
-                                >>::deposit_event(
-                                    CommonEvent::TokenPropertySet(collection.id, token_id, key),
-                                );
-                            }
-                            None => {
-                                <TokenProperties<
-                                    T,
-                                >>::try_mutate(
-                                        (collection.id, token_id),
-                                        |properties| { properties.remove(&key) },
-                                    )
-                                    .map_err(<CommonError<T>>::from)?;
-                                <PalletCommon<
-                                    T,
-                                >>::deposit_event(
-                                    CommonEvent::TokenPropertyDeleted(
-                                        collection.id,
-                                        token_id,
-                                        key,
-                                    ),
-                                );
-                            }
-                        }
-                    }
-                    Ok(())
-                }
-            })();
-            if r.is_ok() {
-                TransactionOutcome::Commit(r)
-            } else {
-                TransactionOutcome::Rollback(r)
-            }
-        })
-    }
-    /// Batch operation to add or edit properties for the token
-    ///
-    /// Same as [`modify_token_properties`] but doesn't allow to remove properties
-    ///
-    /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties
-    pub fn set_token_properties(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token_id: TokenId,
-        properties: impl Iterator<Item = Property>,
-        is_token_create: bool,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        Self::modify_token_properties(
-            collection,
-            sender,
-            token_id,
-            properties.map(|p| (p.key, Some(p.value))),
-            is_token_create,
-            nesting_budget,
-        )
-    }
-    /// Add or edit single property for the token
-    ///
-    /// Calls [`set_token_properties`] internally
-    ///
-    /// [`set_token_properties`]: struct.Pallet.html#method.set_token_properties
-    pub fn set_token_property(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token_id: TokenId,
-        property: Property,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        let is_token_create = false;
-        Self::set_token_properties(
-            collection,
-            sender,
-            token_id,
-            [property].into_iter(),
-            is_token_create,
-            nesting_budget,
-        )
-    }
-    /// Batch operation to remove properties from the token
-    ///
-    /// Same as [`modify_token_properties`] but doesn't allow to add or edit properties
-    ///
-    /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties
-    pub fn delete_token_properties(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token_id: TokenId,
-        property_keys: impl Iterator<Item = PropertyKey>,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        let is_token_create = false;
-        Self::modify_token_properties(
-            collection,
-            sender,
-            token_id,
-            property_keys.into_iter().map(|key| (key, None)),
-            is_token_create,
-            nesting_budget,
-        )
-    }
-    /// Remove single property from the token
-    ///
-    /// Calls [`delete_token_properties`] internally
-    ///
-    /// [`delete_token_properties`]: struct.Pallet.html#method.delete_token_properties
-    pub fn delete_token_property(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token_id: TokenId,
-        property_key: PropertyKey,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        Self::delete_token_properties(
-            collection,
-            sender,
-            token_id,
-            [property_key].into_iter(),
-            nesting_budget,
-        )
-    }
-    /// Add or edit properties for the collection
-    pub fn set_collection_properties(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        properties: Vec<Property>,
-    ) -> DispatchResult {
-        <PalletCommon<T>>::set_collection_properties(collection, sender, properties)
-    }
-    /// Remove properties from the collection
-    pub fn delete_collection_properties(
-        collection: &CollectionHandle<T>,
-        sender: &T::CrossAccountId,
-        property_keys: Vec<PropertyKey>,
-    ) -> DispatchResult {
-        <PalletCommon<
-            T,
-        >>::delete_collection_properties(collection, sender, property_keys)
-    }
-    /// Set property permissions for the token.
-    ///
-    /// Sender should be the owner or admin of token's collection.
-    pub fn set_token_property_permissions(
-        collection: &CollectionHandle<T>,
-        sender: &T::CrossAccountId,
-        property_permissions: Vec<PropertyKeyPermission>,
-    ) -> DispatchResult {
-        <PalletCommon<
-            T,
-        >>::set_token_property_permissions(collection, sender, property_permissions)
-    }
-    /// Set property permissions for the token with scope.
-    ///
-    /// Sender should be the owner or admin of token's collection.
-    pub fn set_scoped_token_property_permissions(
-        collection: &CollectionHandle<T>,
-        sender: &T::CrossAccountId,
-        scope: PropertyScope,
-        property_permissions: Vec<PropertyKeyPermission>,
-    ) -> DispatchResult {
-        <PalletCommon<
-            T,
-        >>::set_scoped_token_property_permissions(
-            collection,
-            sender,
-            scope,
-            property_permissions,
-        )
-    }
-    /// Set property permissions for the collection.
-    ///
-    /// Sender should be the owner or admin of the collection.
-    pub fn set_property_permission(
-        collection: &CollectionHandle<T>,
-        sender: &T::CrossAccountId,
-        permission: PropertyKeyPermission,
-    ) -> DispatchResult {
-        <PalletCommon<T>>::set_property_permission(collection, sender, permission)
-    }
-    /// Transfer NFT token from one account to another.
-    ///
-    /// `from` account stops being the owner and `to` account becomes the owner of the token.
-    /// If `to` is token than `to` becomes owner of the token and the token become nested.
-    /// Unnests token from previous parent if it was nested before.
-    /// Removes allowance for the token if there was any.
-    /// Throws if transfers aren't allowed for collection or if receiver reached token ownership limit.
-    ///
-    /// - `nesting_budget`: Limit for token nesting depth
-    pub fn transfer(
-        collection: &NonfungibleHandle<T>,
-        from: &T::CrossAccountId,
-        to: &T::CrossAccountId,
-        token: TokenId,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        {
-            if !collection.limits.transfers_enabled() {
-                { return Err(<CommonError<T>>::TransferNotAllowed.into()) };
-            }
-        };
-        let token_data = <TokenData<T>>::get((collection.id, token))
-            .ok_or(<CommonError<T>>::TokenNotFound)?;
-        {
-            if !(&token_data.owner == from) {
-                { return Err(<CommonError<T>>::NoPermission.into()) };
-            }
-        };
-        if collection.permissions.access() == AccessMode::AllowList {
-            collection.check_allowlist(from)?;
-            collection.check_allowlist(to)?;
-        }
-        <PalletCommon<T>>::ensure_correct_receiver(to)?;
-        let balance_from = <AccountBalance<T>>::get((collection.id, from))
-            .checked_sub(1)
-            .ok_or(<CommonError<T>>::TokenValueTooLow)?;
-        let balance_to = if from != to {
-            let balance_to = <AccountBalance<T>>::get((collection.id, to))
-                .checked_add(1)
-                .ok_or(ArithmeticError::Overflow)?;
-            {
-                if !(balance_to < collection.limits.account_token_ownership_limit()) {
-                    { return Err(<CommonError<T>>::AccountTokenLimitExceeded.into()) };
-                }
-            };
-            Some(balance_to)
-        } else {
-            None
-        };
-        <PalletStructure<
-            T,
-        >>::nest_if_sent_to_token(
-            from.clone(),
-            to,
-            collection.id,
-            token,
-            nesting_budget,
-        )?;
-        <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);
-        <TokenData<
-            T,
-        >>::insert(
-            (collection.id, token),
-            ItemData {
-                owner: to.clone(),
-                ..token_data
-            },
-        );
-        if let Some(balance_to) = balance_to {
-            if balance_from == 0 {
-                <AccountBalance<T>>::remove((collection.id, from));
-            } else {
-                <AccountBalance<T>>::insert((collection.id, from), balance_from);
-            }
-            <AccountBalance<T>>::insert((collection.id, to), balance_to);
-            <Owned<T>>::remove((collection.id, from, token));
-            <Owned<T>>::insert((collection.id, to, token), true);
-        }
-        Self::set_allowance_unchecked(collection, from, token, None, true);
-        <PalletEvm<
-            T,
-        >>::deposit_log(
-            ERC721Events::Transfer {
-                from: *from.as_eth(),
-                to: *to.as_eth(),
-                token_id: token.into(),
-            }
-                .to_log(collection_id_to_address(collection.id)),
-        );
-        <PalletCommon<
-            T,
-        >>::deposit_event(
-            CommonEvent::Transfer(collection.id, token, from.clone(), to.clone(), 1),
-        );
-        Ok(())
-    }
-    /// Batch operation to mint multiple NFT tokens.
-    ///
-    /// The sender should be the owner/admin of the collection or collection should be configured
-    /// to allow public minting.
-    /// Throws if amount of tokens reached it's limit for the collection or if caller reached
-    /// token ownership limit.
-    ///
-    /// - `data`: Contains list of token properties and users who will become the owners of the
-    ///   corresponging tokens.
-    /// - `nesting_budget`: Limit for token nesting depth
-    pub fn create_multiple_items(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        data: Vec<CreateItemData<T>>,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        if !collection.is_owner_or_admin(sender) {
-            {
-                if !collection.permissions.mint_mode() {
-                    { return Err(<CommonError<T>>::PublicMintingNotAllowed.into()) };
-                }
-            };
-            collection.check_allowlist(sender)?;
-            for item in data.iter() {
-                collection.check_allowlist(&item.owner)?;
-            }
-        }
-        for data in data.iter() {
-            <PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;
-        }
-        let first_token = <TokensMinted<T>>::get(collection.id);
-        let tokens_minted = first_token
-            .checked_add(data.len() as u32)
-            .ok_or(ArithmeticError::Overflow)?;
-        {
-            if !(tokens_minted <= collection.limits.token_limit()) {
-                { return Err(<CommonError<T>>::CollectionTokenLimitExceeded.into()) };
-            }
-        };
-        let mut balances = BTreeMap::new();
-        for data in &data {
-            let balance = balances
-                .entry(&data.owner)
-                .or_insert_with(|| <AccountBalance<
-                    T,
-                >>::get((collection.id, &data.owner)));
-            *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;
-            {
-                if !(*balance <= collection.limits.account_token_ownership_limit()) {
-                    { return Err(<CommonError<T>>::AccountTokenLimitExceeded.into()) };
-                }
-            };
-        }
-        for (i, data) in data.iter().enumerate() {
-            let token = TokenId(first_token + i as u32 + 1);
-            <PalletStructure<
-                T,
-            >>::check_nesting(
-                sender.clone(),
-                &data.owner,
-                collection.id,
-                token,
-                nesting_budget,
-            )?;
-        }
-        with_transaction(|| {
-            for (i, data) in data.iter().enumerate() {
-                let token = first_token + i as u32 + 1;
-                <TokenData<
-                    T,
-                >>::insert(
-                    (collection.id, token),
-                    ItemData {
-                        owner: data.owner.clone(),
-                    },
-                );
-                <PalletStructure<
-                    T,
-                >>::nest_if_sent_to_token_unchecked(
-                    &data.owner,
-                    collection.id,
-                    TokenId(token),
-                );
-                if let Err(e)
-                    = Self::set_token_properties(
-                        collection,
-                        sender,
-                        TokenId(token),
-                        data.properties.clone().into_iter(),
-                        true,
-                        nesting_budget,
-                    ) {
-                    return TransactionOutcome::Rollback(Err(e));
-                }
-            }
-            TransactionOutcome::Commit(Ok(()))
-        })?;
-        <TokensMinted<T>>::insert(collection.id, tokens_minted);
-        for (account, balance) in balances {
-            <AccountBalance<T>>::insert((collection.id, account), balance);
-        }
-        for (i, data) in data.into_iter().enumerate() {
-            let token = first_token + i as u32 + 1;
-            <Owned<T>>::insert((collection.id, &data.owner, token), true);
-            <PalletEvm<
-                T,
-            >>::deposit_log(
-                ERC721Events::Transfer {
-                    from: H160::default(),
-                    to: *data.owner.as_eth(),
-                    token_id: token.into(),
-                }
-                    .to_log(collection_id_to_address(collection.id)),
-            );
-            <PalletCommon<
-                T,
-            >>::deposit_event(
-                CommonEvent::ItemCreated(
-                    collection.id,
-                    TokenId(token),
-                    data.owner.clone(),
-                    1,
-                ),
-            );
-        }
-        Ok(())
-    }
-    pub fn set_allowance_unchecked(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token: TokenId,
-        spender: Option<&T::CrossAccountId>,
-        assume_implicit_eth: bool,
-    ) {
-        if let Some(spender) = spender {
-            let old_spender = <Allowance<T>>::get((collection.id, token));
-            <Allowance<T>>::insert((collection.id, token), spender);
-            <PalletEvm<
-                T,
-            >>::deposit_log(
-                ERC721Events::Approval {
-                    owner: *sender.as_eth(),
-                    approved: *spender.as_eth(),
-                    token_id: token.into(),
-                }
-                    .to_log(collection_id_to_address(collection.id)),
-            );
-            if old_spender.as_ref() != Some(spender) {
-                if let Some(old_owner) = old_spender {
-                    <PalletCommon<
-                        T,
-                    >>::deposit_event(
-                        CommonEvent::Approved(
-                            collection.id,
-                            token,
-                            sender.clone(),
-                            old_owner,
-                            0,
-                        ),
-                    );
-                }
-                <PalletCommon<
-                    T,
-                >>::deposit_event(
-                    CommonEvent::Approved(
-                        collection.id,
-                        token,
-                        sender.clone(),
-                        spender.clone(),
-                        1,
-                    ),
-                );
-            }
-        } else {
-            let old_spender = <Allowance<T>>::take((collection.id, token));
-            if !assume_implicit_eth {
-                <PalletEvm<
-                    T,
-                >>::deposit_log(
-                    ERC721Events::Approval {
-                        owner: *sender.as_eth(),
-                        approved: H160::default(),
-                        token_id: token.into(),
-                    }
-                        .to_log(collection_id_to_address(collection.id)),
-                );
-            }
-            if let Some(old_spender) = old_spender {
-                <PalletCommon<
-                    T,
-                >>::deposit_event(
-                    CommonEvent::Approved(
-                        collection.id,
-                        token,
-                        sender.clone(),
-                        old_spender,
-                        0,
-                    ),
-                );
-            }
-        }
-    }
-    /// Set allowance for the spender to `transfer` or `burn` sender's token.
-    ///
-    /// - `token`: Token the spender is allowed to `transfer` or `burn`.
-    pub fn set_allowance(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        token: TokenId,
-        spender: Option<&T::CrossAccountId>,
-    ) -> DispatchResult {
-        if collection.permissions.access() == AccessMode::AllowList {
-            collection.check_allowlist(sender)?;
-            if let Some(spender) = spender {
-                collection.check_allowlist(spender)?;
-            }
-        }
-        if let Some(spender) = spender {
-            <PalletCommon<T>>::ensure_correct_receiver(spender)?;
-        }
-        let token_data = <TokenData<T>>::get((collection.id, token))
-            .ok_or(<CommonError<T>>::TokenNotFound)?;
-        if &token_data.owner != sender {
-            {
-                if !collection.ignores_owned_amount(sender) {
-                    { return Err(<CommonError<T>>::CantApproveMoreThanOwned.into()) };
-                }
-            };
-        }
-        Self::set_allowance_unchecked(collection, sender, token, spender, false);
-        Ok(())
-    }
-    /// Checks allowance for the spender to use the token.
-    fn check_allowed(
-        collection: &NonfungibleHandle<T>,
-        spender: &T::CrossAccountId,
-        from: &T::CrossAccountId,
-        token: TokenId,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        if spender.conv_eq(from) {
-            return Ok(());
-        }
-        if collection.permissions.access() == AccessMode::AllowList {
-            collection.check_allowlist(spender)?;
-        }
-        if collection.limits.owner_can_transfer()
-            && collection.is_owner_or_admin(spender)
-        {
-            return Ok(());
-        }
-        if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
-            {
-                if !<PalletStructure<
-                    T,
-                >>::check_indirectly_owned(
-                    spender.clone(),
-                    source.0,
-                    source.1,
-                    None,
-                    nesting_budget,
-                )? {
-                    { return Err(<CommonError<T>>::ApprovedValueTooLow.into()) };
-                }
-            };
-            return Ok(());
-        }
-        if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
-            return Ok(());
-        }
-        {
-            if !collection.ignores_allowance(spender) {
-                { return Err(<CommonError<T>>::ApprovedValueTooLow.into()) };
-            }
-        };
-        Ok(())
-    }
-    /// Transfer NFT token from one account to another.
-    ///
-    /// Same as the [`transfer`] but spender doesn't needs to be the owner of the token.
-    /// The owner should set allowance for the spender to transfer token.
-    ///
-    /// [`transfer`]: struct.Pallet.html#method.transfer
-    pub fn transfer_from(
-        collection: &NonfungibleHandle<T>,
-        spender: &T::CrossAccountId,
-        from: &T::CrossAccountId,
-        to: &T::CrossAccountId,
-        token: TokenId,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        Self::check_allowed(collection, spender, from, token, nesting_budget)?;
-        Self::transfer(collection, from, to, token, nesting_budget)
-    }
-    /// Burn NFT token for `from` account.
-    ///
-    /// Same as the [`burn`] but spender doesn't need to be an owner of the token. The owner should
-    /// set allowance for the spender to burn token.
-    ///
-    /// [`burn`]: struct.Pallet.html#method.burn
-    pub fn burn_from(
-        collection: &NonfungibleHandle<T>,
-        spender: &T::CrossAccountId,
-        from: &T::CrossAccountId,
-        token: TokenId,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        Self::check_allowed(collection, spender, from, token, nesting_budget)?;
-        Self::burn(collection, from, token)
-    }
-    /// Check that `from` token could be nested in `under` token.
-    ///
-    pub fn check_nesting(
-        handle: &NonfungibleHandle<T>,
-        sender: T::CrossAccountId,
-        from: (CollectionId, TokenId),
-        under: TokenId,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        let nesting = handle.permissions.nesting();
-        #[cfg(not(feature = "runtime-benchmarks"))]
-        let permissive = false;
-        if permissive {} else if nesting.token_owner
-            && <PalletStructure<
-                T,
-            >>::check_indirectly_owned(
-                sender.clone(),
-                handle.id,
-                under,
-                Some(from),
-                nesting_budget,
-            )?
-        {} else if nesting.collection_admin && handle.is_owner_or_admin(&sender)
-        {} else {
-            { return Err(<CommonError<T>>::UserIsNotAllowedToNest.into()) };
-        }
-        if let Some(whitelist) = &nesting.restricted {
-            {
-                if !whitelist.contains(&from.0) {
-                    {
-                        return Err(
-                            <CommonError<T>>::SourceCollectionIsNotAllowedToNest.into(),
-                        )
-                    };
-                }
-            };
-        }
-        Ok(())
-    }
-    fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {
-        <TokenChildren<T>>::insert((under.0, under.1, (to_nest.0, to_nest.1)), true);
-    }
-    fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {
-        <TokenChildren<T>>::remove((under.0, under.1, to_unnest));
-    }
-    fn collection_has_tokens(collection_id: CollectionId) -> bool {
-        <TokenData<T>>::iter_prefix((collection_id,)).next().is_some()
-    }
-    fn token_has_children(collection_id: CollectionId, token_id: TokenId) -> bool {
-        <TokenChildren<T>>::iter_prefix((collection_id, token_id)).next().is_some()
-    }
-    pub fn token_children_ids(
-        collection_id: CollectionId,
-        token_id: TokenId,
-    ) -> Vec<TokenChild> {
-        <TokenChildren<T>>::iter_prefix((collection_id, token_id))
-            .map(|((child_collection_id, child_id), _)| TokenChild {
-                collection: child_collection_id,
-                token: child_id,
-            })
-            .collect()
-    }
-    /// Mint single NFT token.
-    ///
-    /// Delegated to [`create_multiple_items`]
-    ///
-    /// [`create_multiple_items`]: struct.Pallet.html#method.create_multiple_items
-    pub fn create_item(
-        collection: &NonfungibleHandle<T>,
-        sender: &T::CrossAccountId,
-        data: CreateItemData<T>,
-        nesting_budget: &dyn Budget,
-    ) -> DispatchResult {
-        Self::create_multiple_items(
-            collection,
-            sender,
-            <[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([data])),
-            nesting_budget,
-        )
-    }
-}
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -20,7 +20,7 @@
 //! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
 
 extern crate alloc;
-use alloc::{format, string::ToString};
+use alloc::string::ToString;
 use core::{
 	char::{REPLACEMENT_CHARACTER, decode_utf16},
 	convert::TryInto,
@@ -31,7 +31,7 @@
 	generate_stubgen, solidity, solidity_interface,
 	types::*,
 	weight,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 };
 use frame_support::BoundedVec;
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -21,7 +21,7 @@
 
 extern crate alloc;
 
-use alloc::{format, string::ToString};
+use alloc::string::ToString;
 use core::{
 	char::{REPLACEMENT_CHARACTER, decode_utf16},
 	convert::TryInto,
@@ -32,7 +32,7 @@
 	generate_stubgen, solidity, solidity_interface,
 	types::*,
 	weight,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 };
 use frame_support::{BoundedBTreeMap, BoundedVec};
modifiedpallets/refungible/src/erc_token.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -35,7 +35,7 @@
 	generate_stubgen, solidity_interface,
 	types::*,
 	weight,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 };
 use pallet_common::{
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -22,7 +22,7 @@
 	execution::*,
 	generate_stubgen, solidity, solidity_interface,
 	types::*,
-	custom_signature::{FunctionName, FunctionSignature},
+	custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
 	make_signature,
 , weight};
 use frame_support::{traits::Get, storage::StorageNMap};