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

difftreelog

style fix clippy warnings

Yaroslav Bolyukin2021-11-26parent: #d1696cc.patch.diff
in: master

26 files changed

modified.maintain/frame-weight-template.hbsdiffbeforeafterboth
--- a/.maintain/frame-weight-template.hbs
+++ b/.maintain/frame-weight-template.hbs
@@ -14,6 +14,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
modifiedMakefilediffbeforeafterboth
--- a/Makefile
+++ b/Makefile
@@ -57,9 +57,5 @@
 bench-nonfungible:
 	make _bench PALLET=nonfungible
 
-.PHONY: bench-evm-coder-substrate
-bench-evm-coder-substrate:
-	make _bench PALLET=evm-coder-substrate
-
 .PHONY: bench
-bench: bench-evm-migration bench-nft bench-fungible bench-refungible bench-nonfungible bench-evm-coder-substrate
+bench: bench-evm-migration bench-nft bench-fungible bench-refungible bench-nonfungible
modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
before · crates/evm-coder-macros/src/solidity_interface.rs
1#![allow(dead_code)]23use quote::quote;4use darling::{FromMeta, ToTokens};5use inflector::cases;6use std::fmt::Write;7use syn::{8	Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,9	MetaNameValue, NestedMeta, PatType, Path, PathArguments, ReturnType, Type, spanned::Spanned,10};1112use crate::{13	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,14	parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,15	snake_ident_to_screaming,16};1718struct Is {19	name: Ident,20	pascal_call_name: Ident,21	snake_call_name: Ident,22}23impl Is {24	fn try_from(path: &Path) -> syn::Result<Self> {25		let name = parse_ident_from_path(path, false)?.clone();26		Ok(Self {27			pascal_call_name: pascal_ident_to_call(&name),28			snake_call_name: pascal_ident_to_snake_call(&name),29			name,30		})31	}3233	fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {34		let name = &self.name;35		let pascal_call_name = &self.pascal_call_name;36		quote! {37			#name(#pascal_call_name #gen_ref)38		}39	}4041	fn expand_interface_id(&self) -> proc_macro2::TokenStream {42		let pascal_call_name = &self.pascal_call_name;43		quote! {44			interface_id ^= #pascal_call_name::interface_id();45		}46	}4748	fn expand_supports_interface(49		&self,50		generics: &proc_macro2::TokenStream,51	) -> proc_macro2::TokenStream {52		let pascal_call_name = &self.pascal_call_name;53		quote! {54			<#pascal_call_name #generics>::supports_interface(interface_id)55		}56	}5758	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {59		let name = &self.name;60		quote! {61			Self::#name(call) => call.weight()62		}63	}6465	fn expand_variant_call(66		&self,67		call_name: &proc_macro2::Ident,68		generics: &proc_macro2::TokenStream,69	) -> proc_macro2::TokenStream {70		let name = &self.name;71		let pascal_call_name = &self.pascal_call_name;72		quote! {73			#call_name::#name(call) => return <Self as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self, Msg {74				call,75				caller: c.caller,76				value: c.value,77			})78		}79	}8081	fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {82		let name = &self.name;83		let pascal_call_name = &self.pascal_call_name;84		quote! {85			if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {86				return Ok(Some(Self::#name(parsed_call)))87			}88		}89	}9091	fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {92		let pascal_call_name = &self.pascal_call_name;93		quote! {94			<#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);95		}96	}9798	fn expand_event_generator(&self) -> proc_macro2::TokenStream {99		let name = &self.name;100		quote! {101			#name::generate_solidity_interface(tc, is_impl);102		}103	}104}105106#[derive(Default)]107struct IsList(Vec<Is>);108impl FromMeta for IsList {109	fn from_list(items: &[NestedMeta]) -> darling::Result<Self> {110		let mut out = Vec::new();111		for item in items {112			match item {113				NestedMeta::Meta(Meta::Path(path)) => out.push(Is::try_from(path)?),114				_ => return Err(syn::Error::new(item.span(), "expected path").into()),115			}116		}117		Ok(Self(out))118	}119}120121#[derive(FromMeta)]122pub struct InterfaceInfo {123	name: Ident,124	#[darling(default)]125	is: IsList,126	#[darling(default)]127	inline_is: IsList,128	#[darling(default)]129	events: IsList,130}131132#[derive(FromMeta)]133struct MethodInfo {134	#[darling(default)]135	rename_selector: Option<String>,136}137138enum AbiType {139	// type140	Plain(Ident),141	// (type1,type2)142	Tuple(Vec<AbiType>),143	// type[]144	Vec(Box<AbiType>),145	// type[20]146	Array(Box<AbiType>, usize),147}148impl AbiType {149	fn try_from(value: &Type) -> syn::Result<Self> {150		let value = Self::try_maybe_special_from(value)?;151		if value.is_special() {152			return Err(syn::Error::new(value.span(), "unexpected special type"));153		}154		Ok(value)155	}156	fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {157		match value {158			Type::Array(arr) => {159				let wrapped = AbiType::try_from(&arr.elem)?;160				match &arr.len {161					Expr::Lit(l) => match &l.lit {162						Lit::Int(i) => {163							let num = i.base10_parse::<usize>()?;164							Ok(AbiType::Array(Box::new(wrapped), num as usize))165						}166						_ => Err(syn::Error::new(arr.len.span(), "should be int literal")),167					},168					_ => Err(syn::Error::new(arr.len.span(), "should be literal")),169				}170			}171			Type::Path(_) => {172				let path = parse_path(value)?;173				let segment = parse_path_segment(path)?;174				if segment.ident == "Vec" {175					let args = match &segment.arguments {176						PathArguments::AngleBracketed(e) => e,177						_ => {178							return Err(syn::Error::new(179								segment.arguments.span(),180								"missing Vec generic",181							))182						}183					};184					let args = &args.args;185					if args.len() != 1 {186						return Err(syn::Error::new(187							args.span(),188							"expected only one generic for vec",189						));190					}191					let arg = args.first().unwrap();192193					let ty = match arg {194						GenericArgument::Type(ty) => ty,195						_ => {196							return Err(syn::Error::new(197								arg.span(),198								"expected first generic to be type",199							))200						}201					};202203					let wrapped = AbiType::try_from(ty)?;204					Ok(Self::Vec(Box::new(wrapped)))205				} else {206					if !segment.arguments.is_empty() {207						return Err(syn::Error::new(208							segment.arguments.span(),209							"unexpected generic arguments for non-vec type",210						));211					}212					Ok(Self::Plain(segment.ident.clone()))213				}214			}215			Type::Tuple(t) => {216				let mut out = Vec::with_capacity(t.elems.len());217				for el in t.elems.iter() {218					out.push(AbiType::try_from(el)?)219				}220				Ok(Self::Tuple(out))221			}222			_ => Err(syn::Error::new(223				value.span(),224				"unexpected type, only arrays, plain types and tuples are supported",225			)),226		}227	}228	fn is_value(&self) -> bool {229		match self {230			Self::Plain(v) if v == "value" => true,231			_ => false,232		}233	}234	fn is_caller(&self) -> bool {235		match self {236			Self::Plain(v) if v == "caller" => true,237			_ => false,238		}239	}240	fn is_special(&self) -> bool {241		self.is_caller() || self.is_value()242	}243	fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {244		match self {245			AbiType::Plain(t) => {246				write!(buf, "{}", t)247			}248			AbiType::Tuple(t) => {249				write!(buf, "(")?;250				for (i, t) in t.iter().enumerate() {251					if i != 0 {252						write!(buf, ",")?;253					}254					t.selector_ty_buf(buf)?;255				}256				write!(buf, ")")257			}258			AbiType::Vec(v) => {259				v.selector_ty_buf(buf)?;260				write!(buf, "[]")261			}262			AbiType::Array(v, len) => {263				v.selector_ty_buf(buf)?;264				write!(buf, "[{}]", len)265			}266		}267	}268	fn selector_ty(&self) -> String {269		let mut out = String::new();270		self.selector_ty_buf(&mut out).expect("no fmt error");271		out272	}273}274impl ToTokens for AbiType {275	fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {276		match self {277			AbiType::Plain(t) => tokens.extend(quote! {#t}),278			AbiType::Tuple(t) => {279				tokens.extend(quote! {(280					#(#t),*281				)});282			}283			AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),284			AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),285		}286	}287}288289struct MethodArg {290	name: Ident,291	camel_name: String,292	ty: AbiType,293}294impl MethodArg {295	fn try_from(value: &PatType) -> syn::Result<Self> {296		let name = parse_ident_from_pat(&value.pat)?.clone();297		Ok(Self {298			camel_name: cases::camelcase::to_camel_case(&name.to_string()),299			name,300			ty: AbiType::try_maybe_special_from(&value.ty)?,301		})302	}303	fn is_value(&self) -> bool {304		self.ty.is_value()305	}306	fn is_caller(&self) -> bool {307		self.ty.is_caller()308	}309	fn is_special(&self) -> bool {310		self.ty.is_special()311	}312	fn selector_ty(&self) -> String {313		assert!(!self.is_special());314		self.ty.selector_ty()315	}316317	fn expand_call_def(&self) -> proc_macro2::TokenStream {318		assert!(!self.is_special());319		let name = &self.name;320		let ty = &self.ty;321322		quote! {323			#name: #ty324		}325	}326327	fn expand_parse(&self) -> proc_macro2::TokenStream {328		assert!(!self.is_special());329		let name = &self.name;330		quote! {331			#name: reader.abi_read()?332		}333	}334335	fn expand_call_arg(&self) -> proc_macro2::TokenStream {336		if self.is_value() {337			quote! {338				c.value.clone()339			}340		} else if self.is_caller() {341			quote! {342				c.caller.clone()343			}344		} else {345			let name = &self.name;346			quote! {347				#name348			}349		}350	}351352	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {353		let camel_name = &self.camel_name.to_string();354		let ty = &self.ty;355		quote! {356			<NamedArgument<#ty>>::new(#camel_name)357		}358	}359}360361#[derive(PartialEq)]362enum Mutability {363	Mutable,364	View,365	Pure,366}367368pub struct WeightAttr(syn::Expr);369370mod keyword {371	syn::custom_keyword!(weight);372}373374impl syn::parse::Parse for WeightAttr {375	fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {376		input.parse::<syn::Token![#]>()?;377		let content;378		syn::bracketed!(content in input);379		content.parse::<keyword::weight>()?;380381		let weight_content;382		syn::parenthesized!(weight_content in content);383		Ok(WeightAttr(weight_content.parse::<syn::Expr>()?))384	}385}386387struct Method {388	name: Ident,389	camel_name: String,390	pascal_name: Ident,391	screaming_name: Ident,392	selector_str: String,393	selector: u32,394	args: Vec<MethodArg>,395	has_normal_args: bool,396	mutability: Mutability,397	result: Type,398	weight: Option<Expr>,399	docs: Vec<String>,400}401impl Method {402	fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {403		let mut info = MethodInfo {404			rename_selector: None,405		};406		let mut docs = Vec::new();407		let mut weight = None;408		for attr in &value.attrs {409			let ident = parse_ident_from_path(&attr.path, false)?;410			if ident == "solidity" {411				let args = attr.parse_meta().unwrap();412				info = MethodInfo::from_meta(&args).unwrap();413			} else if ident == "doc" {414				let args = attr.parse_meta().unwrap();415				let value = match args {416					Meta::NameValue(MetaNameValue {417						lit: Lit::Str(str), ..418					}) => str.value(),419					_ => unreachable!(),420				};421				docs.push(value);422			} else if ident == "weight" {423				weight = Some(syn::parse2::<WeightAttr>(attr.to_token_stream())?.0);424			}425		}426		let ident = &value.sig.ident;427		let ident_str = ident.to_string();428		if !cases::snakecase::is_snake_case(&ident_str) {429			return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));430		}431432		let mut mutability = Mutability::Pure;433434		if let Some(FnArg::Receiver(receiver)) = value435			.sig436			.inputs437			.iter()438			.find(|arg| matches!(arg, FnArg::Receiver(_)))439		{440			if receiver.reference.is_none() {441				return Err(syn::Error::new(442					receiver.span(),443					"receiver should be by ref",444				));445			}446			if receiver.mutability.is_some() {447				mutability = Mutability::Mutable;448			} else {449				mutability = Mutability::View;450			}451		}452		let mut args = Vec::new();453		for typ in value454			.sig455			.inputs456			.iter()457			.filter(|arg| matches!(arg, FnArg::Typed(_)))458		{459			let typ = match typ {460				FnArg::Typed(typ) => typ,461				_ => unreachable!(),462			};463			args.push(MethodArg::try_from(typ)?);464		}465466		if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {467			return Err(syn::Error::new(468				args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),469				"payable function should be mutable",470			));471		}472473		let result = match &value.sig.output {474			ReturnType::Type(_, ty) => ty,475			_ => 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)")),476		};477		let result = parse_result_ok(result)?;478479		let camel_name = info480			.rename_selector481			.unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));482		let mut selector_str = camel_name.clone();483		selector_str.push('(');484		let mut has_normal_args = false;485		for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {486			if i != 0 {487				selector_str.push(',');488			}489			write!(selector_str, "{}", arg.selector_ty()).unwrap();490			has_normal_args = true;491		}492		selector_str.push(')');493		let selector = fn_selector_str(&selector_str);494495		Ok(Self {496			name: ident.clone(),497			camel_name,498			pascal_name: snake_ident_to_pascal(ident),499			screaming_name: snake_ident_to_screaming(ident),500			selector_str,501			selector,502			args,503			has_normal_args,504			mutability,505			result: result.clone(),506			weight,507			docs,508		})509	}510	fn expand_call_def(&self) -> proc_macro2::TokenStream {511		let defs = self512			.args513			.iter()514			.filter(|a| !a.is_special())515			.map(|a| a.expand_call_def());516		let pascal_name = &self.pascal_name;517518		if self.has_normal_args {519			quote! {520				#pascal_name {521					#(522						#defs,523					)*524				}525			}526		} else {527			quote! {#pascal_name}528		}529	}530531	fn expand_const(&self) -> proc_macro2::TokenStream {532		let screaming_name = &self.screaming_name;533		let selector = self.selector;534		let selector_str = &self.selector_str;535		quote! {536			#[doc = #selector_str]537			const #screaming_name: u32 = #selector;538		}539	}540541	fn expand_interface_id(&self) -> proc_macro2::TokenStream {542		let screaming_name = &self.screaming_name;543		quote! {544			interface_id ^= Self::#screaming_name;545		}546	}547548	fn expand_parse(&self) -> proc_macro2::TokenStream {549		let pascal_name = &self.pascal_name;550		let screaming_name = &self.screaming_name;551		if self.has_normal_args {552			let parsers = self553				.args554				.iter()555				.filter(|a| !a.is_special())556				.map(|a| a.expand_parse());557			quote! {558				Self::#screaming_name => return Ok(Some(Self::#pascal_name {559					#(560						#parsers,561					)*562				}))563			}564		} else {565			quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }566		}567	}568569	fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {570		let pascal_name = &self.pascal_name;571		let name = &self.name;572573		let matcher = if self.has_normal_args {574			let names = self575				.args576				.iter()577				.filter(|a| !a.is_special())578				.map(|a| &a.name);579580			quote! {{581				#(582					#names,583				)*584			}}585		} else {586			quote! {}587		};588589		let receiver = match self.mutability {590			Mutability::Mutable | Mutability::View => quote! {self.},591			Mutability::Pure => quote! {Self::},592		};593		let args = self.args.iter().map(|a| a.expand_call_arg());594595		quote! {596			#call_name::#pascal_name #matcher => {597				let result = #receiver #name(598					#(599						#args,600					)*601				)?;602				(&result).into_result()603			}604		}605	}606607	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {608		let pascal_name = &self.pascal_name;609		if let Some(weight) = &self.weight {610			let matcher = if self.has_normal_args {611				let names = self612					.args613					.iter()614					.filter(|a| !a.is_special())615					.map(|a| &a.name);616617				quote! {{618					#(619						#names,620					)*621				}}622			} else {623				quote! {}624			};625			quote! {626				Self::#pascal_name #matcher => (#weight).into()627			}628		} else {629			let matcher = if self.has_normal_args {630				quote! {{..}}631			} else {632				quote! {}633			};634			quote! {635				Self::#pascal_name #matcher => ().into()636			}637		}638	}639640	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {641		let camel_name = &self.camel_name;642		let mutability = match self.mutability {643			Mutability::Mutable => quote! {SolidityMutability::Mutable},644			Mutability::View => quote! { SolidityMutability::View },645			Mutability::Pure => quote! {SolidityMutability::Pure},646		};647		let result = &self.result;648649		let args = self650			.args651			.iter()652			.filter(|a| !a.is_special())653			.map(MethodArg::expand_solidity_argument);654		let docs = self.docs.iter();655		let selector = format!("{} {:0>8x}", self.selector_str, self.selector);656657		quote! {658			SolidityFunction {659				docs: &[#(#docs),*],660				selector: #selector,661				name: #camel_name,662				mutability: #mutability,663				args: (664					#(665						#args,666					)*667				),668				result: <UnnamedArgument<#result>>::default(),669			}670		}671	}672}673674fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {675	if gen.params.is_empty() {676		return quote! {};677	}678	let params = gen.params.iter().map(|p| match p {679		syn::GenericParam::Type(id) => {680			let v = &id.ident;681			quote! {#v}682		}683		syn::GenericParam::Lifetime(lt) => {684			let v = &lt.lifetime;685			quote! {#v}686		}687		syn::GenericParam::Const(c) => {688			let i = &c.ident;689			quote! {#i}690		}691	});692	quote! { #(#params),* }693}694fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {695	if gen.params.is_empty() {696		return quote! {};697	}698	let list = generics_list(gen);699	quote! { <#list> }700}701fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {702	let list = generics_list(gen);703	if gen.params.len() == 1 {704		quote! {#list}705	} else {706		quote! { (#list) }707	}708}709710pub struct SolidityInterface {711	generics: Generics,712	name: Box<syn::Type>,713	info: InterfaceInfo,714	methods: Vec<Method>,715}716impl SolidityInterface {717	pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {718		let mut methods = Vec::new();719720		for item in &value.items {721			if let ImplItem::Method(method) = item {722				methods.push(Method::try_from(method)?)723			}724		}725		Ok(Self {726			generics: value.generics.clone(),727			name: value.self_ty.clone(),728			info,729			methods,730		})731	}732	pub fn expand(self) -> proc_macro2::TokenStream {733		let name = self.name;734735		let solidity_name = self.info.name.to_string();736		let call_name = pascal_ident_to_call(&self.info.name);737		let generics = self.generics;738		let gen_ref = generics_reference(&generics);739		let gen_data = generics_data(&generics);740741		let call_sub = self742			.info743			.inline_is744			.0745			.iter()746			.chain(self.info.is.0.iter())747			.map(|c| Is::expand_call_def(c, &gen_ref));748		let call_parse = self749			.info750			.inline_is751			.0752			.iter()753			.chain(self.info.is.0.iter())754			.map(|is| Is::expand_parse(is, &gen_ref));755		let call_variants = self756			.info757			.inline_is758			.0759			.iter()760			.chain(self.info.is.0.iter())761			.map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));762		let weight_variants = self763			.info764			.inline_is765			.0766			.iter()767			.chain(self.info.is.0.iter())768			.map(Is::expand_variant_weight);769770		let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);771		let supports_interface = self772			.info773			.is774			.0775			.iter()776			.map(|is| Is::expand_supports_interface(is, &gen_ref));777778		let calls = self.methods.iter().map(Method::expand_call_def);779		let consts = self.methods.iter().map(Method::expand_const);780		let interface_id = self.methods.iter().map(Method::expand_interface_id);781		let parsers = self.methods.iter().map(Method::expand_parse);782		let call_variants_this = self783			.methods784			.iter()785			.map(|m| Method::expand_variant_call(m, &call_name));786		let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);787		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);788789		// TODO: Inline inline_is790		let solidity_is = self791			.info792			.is793			.0794			.iter()795			.chain(self.info.inline_is.0.iter())796			.map(|is| is.name.to_string());797		let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());798		let solidity_generators = self799			.info800			.is801			.0802			.iter()803			.chain(self.info.inline_is.0.iter())804			.map(|is| Is::expand_generator(is, &gen_ref));805		let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);806807		// let methods = self.methods.iter().map(Method::solidity_def);808809		quote! {810			#[derive(Debug)]811			pub enum #call_name #gen_ref {812				ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),813				#(814					#calls,815				)*816				#(817					#call_sub,818				)*819			}820			impl #gen_ref #call_name #gen_ref {821				#(822					#consts823				)*824				pub fn interface_id() -> u32 {825					let mut interface_id = 0;826					#(#interface_id)*827					#(#inline_interface_id)*828					interface_id829				}830				pub fn supports_interface(interface_id: u32) -> bool {831					interface_id != 0xffffff && (832						interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||833						interface_id == Self::interface_id()834						#(835							|| #supports_interface836						)*837					)838				}839				pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {840					use evm_coder::solidity::*;841					use core::fmt::Write;842					let interface = SolidityInterface {843						name: #solidity_name,844						selector: Self::interface_id(),845						is: &["Dummy", "ERC165", #(846							#solidity_is,847						)* #(848							#solidity_events_is,849						)* ],850						functions: (#(851							#solidity_functions,852						)*),853					};854					if is_impl {855						tc.collect("// 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());856					} else {857						tc.collect("// Common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());858					}859					#(860						#solidity_generators861					)*862					#(863						#solidity_event_generators864					)*865866					let mut out = string::new();867					// In solidity interface usage (is) should be preceeded by interface definition868					// This comment helps to sort it in a set869					if #solidity_name.starts_with("Inline") {870						out.push_str("// Inline\n");871					}872					let _ = interface.format(is_impl, &mut out, tc);873					tc.collect(out);874				}875			}876			impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {877				fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {878					use ::evm_coder::abi::AbiRead;879					match method_id {880						::evm_coder::ERC165Call::INTERFACE_ID => return Ok(881							::evm_coder::ERC165Call::parse(method_id, reader)?882							.map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))883						),884						#(885							#parsers,886						)*887						_ => {},888					}889					#(890						#call_parse891					)else*892					return Ok(None);893				}894			}895			impl #generics ::evm_coder::Weighted for #call_name #gen_ref {896				#[allow(unused_variables)]897				fn weight(&self) -> ::evm_coder::execution::DispatchInfo {898					match self {899						#(900							#weight_variants,901						)*902						// TODO: It should be very cheap, but not free903						Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => 100u64.into(),904						#(905							#weight_variants_this,906						)*907					}908				}909			}910			impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name {911				#[allow(unreachable_code)] // In case of no inner calls912				fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {913					use ::evm_coder::abi::AbiWrite;914					match c.call {915						#(916							#call_variants,917						)*918						#call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {919							let mut writer = ::evm_coder::abi::AbiWriter::default();920							writer.bool(&<#call_name #gen_ref>::supports_interface(interface_id));921							return Ok(writer.into());922						}923						_ => {},924					}925					let mut writer = ::evm_coder::abi::AbiWriter::default();926					match c.call {927						#(928							#call_variants_this,929						)*930						_ => unreachable!()931					}932				}933			}934		}935	}936}
after · crates/evm-coder-macros/src/solidity_interface.rs
1#![allow(dead_code)]23use quote::quote;4use darling::{FromMeta, ToTokens};5use inflector::cases;6use std::fmt::Write;7use syn::{8	Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,9	MetaNameValue, NestedMeta, PatType, Path, PathArguments, ReturnType, Type, spanned::Spanned,10};1112use crate::{13	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,14	parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,15	snake_ident_to_screaming,16};1718struct Is {19	name: Ident,20	pascal_call_name: Ident,21	snake_call_name: Ident,22}23impl Is {24	fn try_from(path: &Path) -> syn::Result<Self> {25		let name = parse_ident_from_path(path, false)?.clone();26		Ok(Self {27			pascal_call_name: pascal_ident_to_call(&name),28			snake_call_name: pascal_ident_to_snake_call(&name),29			name,30		})31	}3233	fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {34		let name = &self.name;35		let pascal_call_name = &self.pascal_call_name;36		quote! {37			#name(#pascal_call_name #gen_ref)38		}39	}4041	fn expand_interface_id(&self) -> proc_macro2::TokenStream {42		let pascal_call_name = &self.pascal_call_name;43		quote! {44			interface_id ^= #pascal_call_name::interface_id();45		}46	}4748	fn expand_supports_interface(49		&self,50		generics: &proc_macro2::TokenStream,51	) -> proc_macro2::TokenStream {52		let pascal_call_name = &self.pascal_call_name;53		quote! {54			<#pascal_call_name #generics>::supports_interface(interface_id)55		}56	}5758	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {59		let name = &self.name;60		quote! {61			Self::#name(call) => call.weight()62		}63	}6465	fn expand_variant_call(66		&self,67		call_name: &proc_macro2::Ident,68		generics: &proc_macro2::TokenStream,69	) -> proc_macro2::TokenStream {70		let name = &self.name;71		let pascal_call_name = &self.pascal_call_name;72		quote! {73			#call_name::#name(call) => return <Self as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self, Msg {74				call,75				caller: c.caller,76				value: c.value,77			})78		}79	}8081	fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {82		let name = &self.name;83		let pascal_call_name = &self.pascal_call_name;84		quote! {85			if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {86				return Ok(Some(Self::#name(parsed_call)))87			}88		}89	}9091	fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {92		let pascal_call_name = &self.pascal_call_name;93		quote! {94			<#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);95		}96	}9798	fn expand_event_generator(&self) -> proc_macro2::TokenStream {99		let name = &self.name;100		quote! {101			#name::generate_solidity_interface(tc, is_impl);102		}103	}104}105106#[derive(Default)]107struct IsList(Vec<Is>);108impl FromMeta for IsList {109	fn from_list(items: &[NestedMeta]) -> darling::Result<Self> {110		let mut out = Vec::new();111		for item in items {112			match item {113				NestedMeta::Meta(Meta::Path(path)) => out.push(Is::try_from(path)?),114				_ => return Err(syn::Error::new(item.span(), "expected path").into()),115			}116		}117		Ok(Self(out))118	}119}120121#[derive(FromMeta)]122pub struct InterfaceInfo {123	name: Ident,124	#[darling(default)]125	is: IsList,126	#[darling(default)]127	inline_is: IsList,128	#[darling(default)]129	events: IsList,130}131132#[derive(FromMeta)]133struct MethodInfo {134	#[darling(default)]135	rename_selector: Option<String>,136}137138enum AbiType {139	// type140	Plain(Ident),141	// (type1,type2)142	Tuple(Vec<AbiType>),143	// type[]144	Vec(Box<AbiType>),145	// type[20]146	Array(Box<AbiType>, usize),147}148impl AbiType {149	fn try_from(value: &Type) -> syn::Result<Self> {150		let value = Self::try_maybe_special_from(value)?;151		if value.is_special() {152			return Err(syn::Error::new(value.span(), "unexpected special type"));153		}154		Ok(value)155	}156	fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {157		match value {158			Type::Array(arr) => {159				let wrapped = AbiType::try_from(&arr.elem)?;160				match &arr.len {161					Expr::Lit(l) => match &l.lit {162						Lit::Int(i) => {163							let num = i.base10_parse::<usize>()?;164							Ok(AbiType::Array(Box::new(wrapped), num as usize))165						}166						_ => Err(syn::Error::new(arr.len.span(), "should be int literal")),167					},168					_ => Err(syn::Error::new(arr.len.span(), "should be literal")),169				}170			}171			Type::Path(_) => {172				let path = parse_path(value)?;173				let segment = parse_path_segment(path)?;174				if segment.ident == "Vec" {175					let args = match &segment.arguments {176						PathArguments::AngleBracketed(e) => e,177						_ => {178							return Err(syn::Error::new(179								segment.arguments.span(),180								"missing Vec generic",181							))182						}183					};184					let args = &args.args;185					if args.len() != 1 {186						return Err(syn::Error::new(187							args.span(),188							"expected only one generic for vec",189						));190					}191					let arg = args.first().unwrap();192193					let ty = match arg {194						GenericArgument::Type(ty) => ty,195						_ => {196							return Err(syn::Error::new(197								arg.span(),198								"expected first generic to be type",199							))200						}201					};202203					let wrapped = AbiType::try_from(ty)?;204					Ok(Self::Vec(Box::new(wrapped)))205				} else {206					if !segment.arguments.is_empty() {207						return Err(syn::Error::new(208							segment.arguments.span(),209							"unexpected generic arguments for non-vec type",210						));211					}212					Ok(Self::Plain(segment.ident.clone()))213				}214			}215			Type::Tuple(t) => {216				let mut out = Vec::with_capacity(t.elems.len());217				for el in t.elems.iter() {218					out.push(AbiType::try_from(el)?)219				}220				Ok(Self::Tuple(out))221			}222			_ => Err(syn::Error::new(223				value.span(),224				"unexpected type, only arrays, plain types and tuples are supported",225			)),226		}227	}228	fn is_value(&self) -> bool {229		matches!(self, Self::Plain(v) if v == "value")230	}231	fn is_caller(&self) -> bool {232		matches!(self, Self::Plain(v) if v == "caller")233	}234	fn is_special(&self) -> bool {235		self.is_caller() || self.is_value()236	}237	fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {238		match self {239			AbiType::Plain(t) => {240				write!(buf, "{}", t)241			}242			AbiType::Tuple(t) => {243				write!(buf, "(")?;244				for (i, t) in t.iter().enumerate() {245					if i != 0 {246						write!(buf, ",")?;247					}248					t.selector_ty_buf(buf)?;249				}250				write!(buf, ")")251			}252			AbiType::Vec(v) => {253				v.selector_ty_buf(buf)?;254				write!(buf, "[]")255			}256			AbiType::Array(v, len) => {257				v.selector_ty_buf(buf)?;258				write!(buf, "[{}]", len)259			}260		}261	}262	fn selector_ty(&self) -> String {263		let mut out = String::new();264		self.selector_ty_buf(&mut out).expect("no fmt error");265		out266	}267}268impl ToTokens for AbiType {269	fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {270		match self {271			AbiType::Plain(t) => tokens.extend(quote! {#t}),272			AbiType::Tuple(t) => {273				tokens.extend(quote! {(274					#(#t),*275				)});276			}277			AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),278			AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),279		}280	}281}282283struct MethodArg {284	name: Ident,285	camel_name: String,286	ty: AbiType,287}288impl MethodArg {289	fn try_from(value: &PatType) -> syn::Result<Self> {290		let name = parse_ident_from_pat(&value.pat)?.clone();291		Ok(Self {292			camel_name: cases::camelcase::to_camel_case(&name.to_string()),293			name,294			ty: AbiType::try_maybe_special_from(&value.ty)?,295		})296	}297	fn is_value(&self) -> bool {298		self.ty.is_value()299	}300	fn is_caller(&self) -> bool {301		self.ty.is_caller()302	}303	fn is_special(&self) -> bool {304		self.ty.is_special()305	}306	fn selector_ty(&self) -> String {307		assert!(!self.is_special());308		self.ty.selector_ty()309	}310311	fn expand_call_def(&self) -> proc_macro2::TokenStream {312		assert!(!self.is_special());313		let name = &self.name;314		let ty = &self.ty;315316		quote! {317			#name: #ty318		}319	}320321	fn expand_parse(&self) -> proc_macro2::TokenStream {322		assert!(!self.is_special());323		let name = &self.name;324		quote! {325			#name: reader.abi_read()?326		}327	}328329	fn expand_call_arg(&self) -> proc_macro2::TokenStream {330		if self.is_value() {331			quote! {332				c.value.clone()333			}334		} else if self.is_caller() {335			quote! {336				c.caller.clone()337			}338		} else {339			let name = &self.name;340			quote! {341				#name342			}343		}344	}345346	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {347		let camel_name = &self.camel_name.to_string();348		let ty = &self.ty;349		quote! {350			<NamedArgument<#ty>>::new(#camel_name)351		}352	}353}354355#[derive(PartialEq)]356enum Mutability {357	Mutable,358	View,359	Pure,360}361362pub struct WeightAttr(syn::Expr);363364mod keyword {365	syn::custom_keyword!(weight);366}367368impl syn::parse::Parse for WeightAttr {369	fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {370		input.parse::<syn::Token![#]>()?;371		let content;372		syn::bracketed!(content in input);373		content.parse::<keyword::weight>()?;374375		let weight_content;376		syn::parenthesized!(weight_content in content);377		Ok(WeightAttr(weight_content.parse::<syn::Expr>()?))378	}379}380381struct Method {382	name: Ident,383	camel_name: String,384	pascal_name: Ident,385	screaming_name: Ident,386	selector_str: String,387	selector: u32,388	args: Vec<MethodArg>,389	has_normal_args: bool,390	mutability: Mutability,391	result: Type,392	weight: Option<Expr>,393	docs: Vec<String>,394}395impl Method {396	fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {397		let mut info = MethodInfo {398			rename_selector: None,399		};400		let mut docs = Vec::new();401		let mut weight = None;402		for attr in &value.attrs {403			let ident = parse_ident_from_path(&attr.path, false)?;404			if ident == "solidity" {405				let args = attr.parse_meta().unwrap();406				info = MethodInfo::from_meta(&args).unwrap();407			} else if ident == "doc" {408				let args = attr.parse_meta().unwrap();409				let value = match args {410					Meta::NameValue(MetaNameValue {411						lit: Lit::Str(str), ..412					}) => str.value(),413					_ => unreachable!(),414				};415				docs.push(value);416			} else if ident == "weight" {417				weight = Some(syn::parse2::<WeightAttr>(attr.to_token_stream())?.0);418			}419		}420		let ident = &value.sig.ident;421		let ident_str = ident.to_string();422		if !cases::snakecase::is_snake_case(&ident_str) {423			return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));424		}425426		let mut mutability = Mutability::Pure;427428		if let Some(FnArg::Receiver(receiver)) = value429			.sig430			.inputs431			.iter()432			.find(|arg| matches!(arg, FnArg::Receiver(_)))433		{434			if receiver.reference.is_none() {435				return Err(syn::Error::new(436					receiver.span(),437					"receiver should be by ref",438				));439			}440			if receiver.mutability.is_some() {441				mutability = Mutability::Mutable;442			} else {443				mutability = Mutability::View;444			}445		}446		let mut args = Vec::new();447		for typ in value448			.sig449			.inputs450			.iter()451			.filter(|arg| matches!(arg, FnArg::Typed(_)))452		{453			let typ = match typ {454				FnArg::Typed(typ) => typ,455				_ => unreachable!(),456			};457			args.push(MethodArg::try_from(typ)?);458		}459460		if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {461			return Err(syn::Error::new(462				args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),463				"payable function should be mutable",464			));465		}466467		let result = match &value.sig.output {468			ReturnType::Type(_, ty) => ty,469			_ => 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)")),470		};471		let result = parse_result_ok(result)?;472473		let camel_name = info474			.rename_selector475			.unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));476		let mut selector_str = camel_name.clone();477		selector_str.push('(');478		let mut has_normal_args = false;479		for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {480			if i != 0 {481				selector_str.push(',');482			}483			write!(selector_str, "{}", arg.selector_ty()).unwrap();484			has_normal_args = true;485		}486		selector_str.push(')');487		let selector = fn_selector_str(&selector_str);488489		Ok(Self {490			name: ident.clone(),491			camel_name,492			pascal_name: snake_ident_to_pascal(ident),493			screaming_name: snake_ident_to_screaming(ident),494			selector_str,495			selector,496			args,497			has_normal_args,498			mutability,499			result: result.clone(),500			weight,501			docs,502		})503	}504	fn expand_call_def(&self) -> proc_macro2::TokenStream {505		let defs = self506			.args507			.iter()508			.filter(|a| !a.is_special())509			.map(|a| a.expand_call_def());510		let pascal_name = &self.pascal_name;511512		if self.has_normal_args {513			quote! {514				#pascal_name {515					#(516						#defs,517					)*518				}519			}520		} else {521			quote! {#pascal_name}522		}523	}524525	fn expand_const(&self) -> proc_macro2::TokenStream {526		let screaming_name = &self.screaming_name;527		let selector = self.selector;528		let selector_str = &self.selector_str;529		quote! {530			#[doc = #selector_str]531			const #screaming_name: u32 = #selector;532		}533	}534535	fn expand_interface_id(&self) -> proc_macro2::TokenStream {536		let screaming_name = &self.screaming_name;537		quote! {538			interface_id ^= Self::#screaming_name;539		}540	}541542	fn expand_parse(&self) -> proc_macro2::TokenStream {543		let pascal_name = &self.pascal_name;544		let screaming_name = &self.screaming_name;545		if self.has_normal_args {546			let parsers = self547				.args548				.iter()549				.filter(|a| !a.is_special())550				.map(|a| a.expand_parse());551			quote! {552				Self::#screaming_name => return Ok(Some(Self::#pascal_name {553					#(554						#parsers,555					)*556				}))557			}558		} else {559			quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }560		}561	}562563	fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {564		let pascal_name = &self.pascal_name;565		let name = &self.name;566567		let matcher = if self.has_normal_args {568			let names = self569				.args570				.iter()571				.filter(|a| !a.is_special())572				.map(|a| &a.name);573574			quote! {{575				#(576					#names,577				)*578			}}579		} else {580			quote! {}581		};582583		let receiver = match self.mutability {584			Mutability::Mutable | Mutability::View => quote! {self.},585			Mutability::Pure => quote! {Self::},586		};587		let args = self.args.iter().map(|a| a.expand_call_arg());588589		quote! {590			#call_name::#pascal_name #matcher => {591				let result = #receiver #name(592					#(593						#args,594					)*595				)?;596				(&result).to_result()597			}598		}599	}600601	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {602		let pascal_name = &self.pascal_name;603		if let Some(weight) = &self.weight {604			let matcher = if self.has_normal_args {605				let names = self606					.args607					.iter()608					.filter(|a| !a.is_special())609					.map(|a| &a.name);610611				quote! {{612					#(613						#names,614					)*615				}}616			} else {617				quote! {}618			};619			quote! {620				Self::#pascal_name #matcher => (#weight).into()621			}622		} else {623			let matcher = if self.has_normal_args {624				quote! {{..}}625			} else {626				quote! {}627			};628			quote! {629				Self::#pascal_name #matcher => ().into()630			}631		}632	}633634	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {635		let camel_name = &self.camel_name;636		let mutability = match self.mutability {637			Mutability::Mutable => quote! {SolidityMutability::Mutable},638			Mutability::View => quote! { SolidityMutability::View },639			Mutability::Pure => quote! {SolidityMutability::Pure},640		};641		let result = &self.result;642643		let args = self644			.args645			.iter()646			.filter(|a| !a.is_special())647			.map(MethodArg::expand_solidity_argument);648		let docs = self.docs.iter();649		let selector = format!("{} {:0>8x}", self.selector_str, self.selector);650651		quote! {652			SolidityFunction {653				docs: &[#(#docs),*],654				selector: #selector,655				name: #camel_name,656				mutability: #mutability,657				args: (658					#(659						#args,660					)*661				),662				result: <UnnamedArgument<#result>>::default(),663			}664		}665	}666}667668fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {669	if gen.params.is_empty() {670		return quote! {};671	}672	let params = gen.params.iter().map(|p| match p {673		syn::GenericParam::Type(id) => {674			let v = &id.ident;675			quote! {#v}676		}677		syn::GenericParam::Lifetime(lt) => {678			let v = &lt.lifetime;679			quote! {#v}680		}681		syn::GenericParam::Const(c) => {682			let i = &c.ident;683			quote! {#i}684		}685	});686	quote! { #(#params),* }687}688fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {689	if gen.params.is_empty() {690		return quote! {};691	}692	let list = generics_list(gen);693	quote! { <#list> }694}695fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {696	let list = generics_list(gen);697	if gen.params.len() == 1 {698		quote! {#list}699	} else {700		quote! { (#list) }701	}702}703704pub struct SolidityInterface {705	generics: Generics,706	name: Box<syn::Type>,707	info: InterfaceInfo,708	methods: Vec<Method>,709}710impl SolidityInterface {711	pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {712		let mut methods = Vec::new();713714		for item in &value.items {715			if let ImplItem::Method(method) = item {716				methods.push(Method::try_from(method)?)717			}718		}719		Ok(Self {720			generics: value.generics.clone(),721			name: value.self_ty.clone(),722			info,723			methods,724		})725	}726	pub fn expand(self) -> proc_macro2::TokenStream {727		let name = self.name;728729		let solidity_name = self.info.name.to_string();730		let call_name = pascal_ident_to_call(&self.info.name);731		let generics = self.generics;732		let gen_ref = generics_reference(&generics);733		let gen_data = generics_data(&generics);734735		let call_sub = self736			.info737			.inline_is738			.0739			.iter()740			.chain(self.info.is.0.iter())741			.map(|c| Is::expand_call_def(c, &gen_ref));742		let call_parse = self743			.info744			.inline_is745			.0746			.iter()747			.chain(self.info.is.0.iter())748			.map(|is| Is::expand_parse(is, &gen_ref));749		let call_variants = self750			.info751			.inline_is752			.0753			.iter()754			.chain(self.info.is.0.iter())755			.map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));756		let weight_variants = self757			.info758			.inline_is759			.0760			.iter()761			.chain(self.info.is.0.iter())762			.map(Is::expand_variant_weight);763764		let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);765		let supports_interface = self766			.info767			.is768			.0769			.iter()770			.map(|is| Is::expand_supports_interface(is, &gen_ref));771772		let calls = self.methods.iter().map(Method::expand_call_def);773		let consts = self.methods.iter().map(Method::expand_const);774		let interface_id = self.methods.iter().map(Method::expand_interface_id);775		let parsers = self.methods.iter().map(Method::expand_parse);776		let call_variants_this = self777			.methods778			.iter()779			.map(|m| Method::expand_variant_call(m, &call_name));780		let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);781		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);782783		// TODO: Inline inline_is784		let solidity_is = self785			.info786			.is787			.0788			.iter()789			.chain(self.info.inline_is.0.iter())790			.map(|is| is.name.to_string());791		let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());792		let solidity_generators = self793			.info794			.is795			.0796			.iter()797			.chain(self.info.inline_is.0.iter())798			.map(|is| Is::expand_generator(is, &gen_ref));799		let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);800801		// let methods = self.methods.iter().map(Method::solidity_def);802803		quote! {804			#[derive(Debug)]805			pub enum #call_name #gen_ref {806				ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),807				#(808					#calls,809				)*810				#(811					#call_sub,812				)*813			}814			impl #gen_ref #call_name #gen_ref {815				#(816					#consts817				)*818				pub fn interface_id() -> u32 {819					let mut interface_id = 0;820					#(#interface_id)*821					#(#inline_interface_id)*822					interface_id823				}824				pub fn supports_interface(interface_id: u32) -> bool {825					interface_id != 0xffffff && (826						interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||827						interface_id == Self::interface_id()828						#(829							|| #supports_interface830						)*831					)832				}833				pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {834					use evm_coder::solidity::*;835					use core::fmt::Write;836					let interface = SolidityInterface {837						name: #solidity_name,838						selector: Self::interface_id(),839						is: &["Dummy", "ERC165", #(840							#solidity_is,841						)* #(842							#solidity_events_is,843						)* ],844						functions: (#(845							#solidity_functions,846						)*),847					};848					if is_impl {849						tc.collect("// 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());850					} else {851						tc.collect("// Common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());852					}853					#(854						#solidity_generators855					)*856					#(857						#solidity_event_generators858					)*859860					let mut out = string::new();861					// In solidity interface usage (is) should be preceeded by interface definition862					// This comment helps to sort it in a set863					if #solidity_name.starts_with("Inline") {864						out.push_str("// Inline\n");865					}866					let _ = interface.format(is_impl, &mut out, tc);867					tc.collect(out);868				}869			}870			impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {871				fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {872					use ::evm_coder::abi::AbiRead;873					match method_id {874						::evm_coder::ERC165Call::INTERFACE_ID => return Ok(875							::evm_coder::ERC165Call::parse(method_id, reader)?876							.map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))877						),878						#(879							#parsers,880						)*881						_ => {},882					}883					#(884						#call_parse885					)else*886					return Ok(None);887				}888			}889			impl #generics ::evm_coder::Weighted for #call_name #gen_ref {890				#[allow(unused_variables)]891				fn weight(&self) -> ::evm_coder::execution::DispatchInfo {892					match self {893						#(894							#weight_variants,895						)*896						// TODO: It should be very cheap, but not free897						Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => 100u64.into(),898						#(899							#weight_variants_this,900						)*901					}902				}903			}904			impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name {905				#[allow(unreachable_code)] // In case of no inner calls906				fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {907					use ::evm_coder::abi::AbiWrite;908					match c.call {909						#(910							#call_variants,911						)*912						#call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {913							let mut writer = ::evm_coder::abi::AbiWriter::default();914							writer.bool(&<#call_name #gen_ref>::supports_interface(interface_id));915							return Ok(writer.into());916						}917						_ => {},918					}919					let mut writer = ::evm_coder::abi::AbiWriter::default();920					match c.call {921						#(922							#call_variants_this,923						)*924						_ => unreachable!()925					}926				}927			}928		}929	}930}
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -310,7 +310,7 @@
 
 pub trait AbiWrite {
 	fn abi_write(&self, writer: &mut AbiWriter);
-	fn into_result(&self) -> ResultWithPostInfo<AbiWriter> {
+	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {
 		let mut writer = AbiWriter::new();
 		self.abi_write(&mut writer);
 		Ok(writer.into())
@@ -319,7 +319,7 @@
 
 impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {
 	// this particular AbiWrite implementation should be split to another trait,
-	// which only implements [`into_result`]
+	// which only implements [`to_result`]
 	//
 	// But due to lack of specialization feature in stable Rust, we can't have
 	// blanket impl of this trait `for T where T: AbiWrite`, so here we abusing
@@ -327,7 +327,7 @@
 	fn abi_write(&self, _writer: &mut AbiWriter) {
 		debug_assert!(false, "shouldn't be called, see comment")
 	}
-	fn into_result(&self) -> ResultWithPostInfo<AbiWriter> {
+	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {
 		match self {
 			Ok(v) => Ok(WithPostDispatchInfo {
 				post_info: v.post_info.clone(),
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -214,7 +214,7 @@
 			500_usize, // max stored filters
 			overrides.clone(),
 			max_past_logs,
-			block_data_cache.clone(),
+			block_data_cache,
 		)));
 	}
 
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -51,7 +51,7 @@
 		Self::new_with_gas_limit(id, u64::MAX)
 	}
 	pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {
-		Ok(Self::new(id).ok_or_else(|| <Error<T>>::CollectionNotFound)?)
+		Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)
 	}
 	pub fn log(&self, log: impl evm_coder::ToLog) {
 		self.recorder.log(log)
@@ -453,7 +453,7 @@
 			collection.limits.owner_can_destroy(),
 			<Error<T>>::NoPermission,
 		);
-		collection.check_is_owner(&sender)?;
+		collection.check_is_owner(sender)?;
 
 		let destroyed_collections = <DestroyedCollectionCount<T>>::get()
 			.0
@@ -476,7 +476,7 @@
 		user: &T::CrossAccountId,
 		allowed: bool,
 	) -> DispatchResult {
-		collection.check_is_owner_or_admin(&sender)?;
+		collection.check_is_owner_or_admin(sender)?;
 
 		// =========
 
@@ -495,7 +495,7 @@
 		user: &T::CrossAccountId,
 		admin: bool,
 	) -> DispatchResult {
-		collection.check_is_owner_or_admin(&sender)?;
+		collection.check_is_owner_or_admin(sender)?;
 
 		let was_admin = <IsAdmin<T>>::get((collection.id, user));
 		if was_admin == admin {
modifiedpallets/evm-contract-helpers/exp.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/exp.rs
+++ b/pallets/evm-contract-helpers/exp.rs
@@ -532,11 +532,11 @@
             match c.call {
                 InternalCall::ContractOwner { contract_address } => {
                     let result = self.contract_owner(contract_address)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::SponsoringEnabled { contract_address } => {
                     let result = self.sponsoring_enabled(contract_address)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::ToggleSponsoring {
                     contract_address,
@@ -544,7 +544,7 @@
                 } => {
                     let result =
                         self.toggle_sponsoring(c.caller.clone(), contract_address, enabled)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::SetSponsoringRateLimit {
                     contract_address,
@@ -555,22 +555,22 @@
                         contract_address,
                         rate_limit,
                     )?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::GetSponsoringRateLimit { contract_address } => {
                     let result = self.get_sponsoring_rate_limit(contract_address)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::Allowed {
                     contract_address,
                     user,
                 } => {
                     let result = self.allowed(contract_address, user)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::AllowlistEnabled { contract_address } => {
                     let result = self.allowlist_enabled(contract_address)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::ToggleAllowlist {
                     contract_address,
@@ -578,7 +578,7 @@
                 } => {
                     let result =
                         self.toggle_allowlist(c.caller.clone(), contract_address, enabled)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 InternalCall::ToggleAllowed {
                     contract_address,
@@ -587,7 +587,7 @@
                 } => {
                     let result =
                         self.toggle_allowed(c.caller.clone(), contract_address, user, allowed)?;
-                    (&result).into_result()
+                    (&result).to_result()
                 }
                 _ => ::core::panicking::panic("internal error: entered unreachable code"),
             }
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -1,10 +1,7 @@
 use core::marker::PhantomData;
 use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
 use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
-use pallet_evm::{
-	ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput, PrecompileResult,
-	PrecompileFailure,
-};
+use pallet_evm::{ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure};
 use sp_core::H160;
 use crate::{
 	AllowlistEnabled, Config, Owner, Pallet, SelfSponsoring, SponsorBasket, SponsoringRateLimit,
@@ -161,7 +158,7 @@
 		if let Some(last_tx_block) = <SponsorBasket<T>>::get(&call.0, who) {
 			let limit = <SponsoringRateLimit<T>>::get(&call.0);
 
-			let timeout = last_tx_block + limit.into();
+			let timeout = last_tx_block + limit;
 			if block_number < timeout {
 				return None;
 			}
modifiedpallets/evm-migration/src/weights.rsdiffbeforeafterboth
--- a/pallets/evm-migration/src/weights.rs
+++ b/pallets/evm-migration/src/weights.rs
@@ -25,6 +25,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
modifiedpallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-transaction-payment/src/lib.rs
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -128,7 +128,7 @@
 				let sponsor = frame_support::storage::with_transaction(|| {
 					TransactionOutcome::Rollback(T::EvmSponsorshipHandler::get_sponsor(
 						&who,
-						&(target.clone(), input.clone()),
+						&(*target, input.clone()),
 					))
 				})?;
 				let sponsor = T::EvmAddressMapping::into_account_id(sponsor);
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -116,7 +116,7 @@
 		);
 
 		with_weight(
-			<Pallet<T>>::transfer(&self, &from, &to, amount),
+			<Pallet<T>>::transfer(self, &from, &to, amount),
 			<CommonWeights<T>>::transfer(),
 		)
 	}
@@ -134,7 +134,7 @@
 		);
 
 		with_weight(
-			<Pallet<T>>::set_allowance(&self, &sender, &spender, amount),
+			<Pallet<T>>::set_allowance(self, &sender, &spender, amount),
 			<CommonWeights<T>>::approve(),
 		)
 	}
@@ -153,7 +153,7 @@
 		);
 
 		with_weight(
-			<Pallet<T>>::transfer_from(&self, &sender, &from, &to, amount),
+			<Pallet<T>>::transfer_from(self, &sender, &from, &to, amount),
 			<CommonWeights<T>>::transfer_from(),
 		)
 	}
@@ -171,7 +171,7 @@
 		);
 
 		with_weight(
-			<Pallet<T>>::burn_from(&self, &sender, &from, amount),
+			<Pallet<T>>::burn_from(self, &sender, &from, amount),
 			<CommonWeights<T>>::burn_from(),
 		)
 	}
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -6,7 +6,6 @@
 use sp_core::{H160, U256};
 use sp_std::vec::Vec;
 use pallet_common::account::CrossAccountId;
-use pallet_common::erc::PrecompileOutput;
 use pallet_evm_coder_substrate::{call, dispatch_to_evm};
 
 use crate::{
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -303,8 +303,8 @@
 		amount: u128,
 	) -> DispatchResult {
 		if collection.access == AccessMode::AllowList {
-			collection.check_allowlist(&owner)?;
-			collection.check_allowlist(&spender)?;
+			collection.check_allowlist(owner)?;
+			collection.check_allowlist(spender)?;
 		}
 
 		if <Balance<T>>::get((collection.id, owner)) < amount {
modifiedpallets/fungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/fungible/src/weights.rs
+++ b/pallets/fungible/src/weights.rs
@@ -25,6 +25,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
@@ -32,11 +33,11 @@
 /// Weight functions needed for pallet_fungible.
 pub trait WeightInfo {
 	fn create_item() -> Weight;
-	fn burn_from() -> Weight;
 	fn burn_item() -> Weight;
 	fn transfer() -> Weight;
 	fn approve() -> Weight;
 	fn transfer_from() -> Weight;
+	fn burn_from() -> Weight;
 }
 
 /// Weights for pallet_fungible using the Substrate node and recommended hardware.
modifiedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nft/src/benchmarking.rs
+++ b/pallets/nft/src/benchmarking.rs
@@ -158,6 +158,7 @@
 			sponsored_data_size: Some(0),
 			token_limit: Some(1),
 			sponsor_transfer_timeout: Some(0),
+			sponsor_approve_timeout: None,
 			owner_can_destroy: Some(true),
 			owner_can_transfer: Some(true),
 			sponsored_data_rate_limit: None,
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -195,7 +195,7 @@
 
 			// Create new collection
 			let new_collection = Collection {
-				owner: who.clone(),
+				owner: who,
 				name: collection_name,
 				mode: mode.clone(),
 				mint_mode: false,
modifiedpallets/nft/src/weights.rsdiffbeforeafterboth
--- a/pallets/nft/src/weights.rs
+++ b/pallets/nft/src/weights.rs
@@ -25,6 +25,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -100,7 +100,7 @@
 		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
 		if amount == 1 {
 			with_weight(
-				<Pallet<T>>::burn(&self, &sender, token),
+				<Pallet<T>>::burn(self, &sender, token),
 				<CommonWeights<T>>::burn_item(),
 			)
 		} else {
@@ -118,7 +118,7 @@
 		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
 		if amount == 1 {
 			with_weight(
-				<Pallet<T>>::transfer(&self, &from, &to, token),
+				<Pallet<T>>::transfer(self, &from, &to, token),
 				<CommonWeights<T>>::transfer(),
 			)
 		} else {
@@ -137,9 +137,9 @@
 
 		with_weight(
 			if amount == 1 {
-				<Pallet<T>>::set_allowance(&self, &sender, token, Some(&spender))
+				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))
 			} else {
-				<Pallet<T>>::set_allowance(&self, &sender, token, None)
+				<Pallet<T>>::set_allowance(self, &sender, token, None)
 			},
 			<CommonWeights<T>>::approve(),
 		)
@@ -157,7 +157,7 @@
 
 		if amount == 1 {
 			with_weight(
-				<Pallet<T>>::transfer_from(&self, &sender, &from, &to, token),
+				<Pallet<T>>::transfer_from(self, &sender, &from, &to, token),
 				<CommonWeights<T>>::transfer_from(),
 			)
 		} else {
@@ -176,7 +176,7 @@
 
 		if amount == 1 {
 			with_weight(
-				<Pallet<T>>::burn_from(&self, &sender, &from, token),
+				<Pallet<T>>::burn_from(self, &sender, &from, token),
 				<CommonWeights<T>>::burn_from(),
 			)
 		} else {
@@ -192,7 +192,7 @@
 	) -> DispatchResultWithPostInfo {
 		let len = data.len();
 		with_weight(
-			<Pallet<T>>::set_variable_metadata(&self, &sender, token, data),
+			<Pallet<T>>::set_variable_metadata(self, &sender, token, data),
 			<CommonWeights<T>>::set_variable_metadata(len as u32),
 		)
 	}
@@ -218,12 +218,12 @@
 	}
 	fn const_metadata(&self, token: TokenId) -> Vec<u8> {
 		<TokenData<T>>::get((self.id, token))
-			.map(|t| t.const_data.clone())
+			.map(|t| t.const_data)
 			.unwrap_or_default()
 	}
 	fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
 		<TokenData<T>>::get((self.id, token))
-			.map(|t| t.variable_data.clone())
+			.map(|t| t.variable_data)
 			.unwrap_or_default()
 	}
 
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -13,7 +13,6 @@
 	erc::{CommonEvmHandler, PrecompileResult},
 };
 use pallet_evm_coder_substrate::call;
-use pallet_common::erc::PrecompileOutput;
 
 use crate::{
 	AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -169,8 +169,8 @@
 		sender: &T::CrossAccountId,
 		token: TokenId,
 	) -> DispatchResult {
-		let token_data = <TokenData<T>>::get((collection.id, token))
-			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;
+		let token_data =
+			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
 		ensure!(
 			&token_data.owner == sender
 				|| (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(sender)),
@@ -197,7 +197,7 @@
 				collection.id,
 				token,
 				sender.clone(),
-				old_spender.clone(),
+				old_spender,
 				0,
 			));
 		}
@@ -213,7 +213,7 @@
 			token_data.owner,
 			1,
 		));
-		return Ok(());
+		Ok(())
 	}
 
 	pub fn transfer(
@@ -227,8 +227,8 @@
 			<CommonError<T>>::TransferNotAllowed
 		);
 
-		let token_data = <TokenData<T>>::get((collection.id, token))
-			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;
+		let token_data =
+			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
 		ensure!(
 			&token_data.owner == from
 				|| (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(from)),
@@ -399,7 +399,7 @@
 						collection.id,
 						token,
 						sender.clone(),
-						old_owner.clone(),
+						old_owner,
 						0,
 					));
 				}
@@ -429,7 +429,7 @@
 					collection.id,
 					token,
 					sender.clone(),
-					old_spender.clone(),
+					old_spender,
 					0,
 				));
 			}
@@ -443,9 +443,9 @@
 		spender: Option<&T::CrossAccountId>,
 	) -> DispatchResult {
 		if collection.access == AccessMode::AllowList {
-			collection.check_allowlist(&sender)?;
+			collection.check_allowlist(sender)?;
 			if let Some(spender) = spender {
-				collection.check_allowlist(&spender)?;
+				collection.check_allowlist(spender)?;
 			}
 		}
 
@@ -491,7 +491,7 @@
 
 		// =========
 
-		Self::transfer(collection, &from, to, token)?;
+		Self::transfer(collection, from, to, token)?;
 		// Allowance is reset in [`transfer`]
 		Ok(())
 	}
@@ -519,7 +519,7 @@
 
 		// =========
 
-		Self::burn(collection, &from, token)
+		Self::burn(collection, from, token)
 	}
 
 	pub fn set_variable_metadata(
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -25,6 +25,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
@@ -33,11 +34,11 @@
 pub trait WeightInfo {
 	fn create_item() -> Weight;
 	fn create_multiple_items(b: u32, ) -> Weight;
-	fn burn_from() -> Weight;
 	fn burn_item() -> Weight;
 	fn transfer() -> Weight;
 	fn approve() -> Weight;
 	fn transfer_from() -> Weight;
+	fn burn_from() -> Weight;
 	fn set_variable_metadata(b: u32, ) -> Weight;
 }
 
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -135,7 +135,7 @@
 		amount: u128,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
-			<Pallet<T>>::transfer(&self, &from, &to, token, amount),
+			<Pallet<T>>::transfer(self, &from, &to, token, amount),
 			<CommonWeights<T>>::transfer(),
 		)
 	}
@@ -148,7 +148,7 @@
 		amount: u128,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
-			<Pallet<T>>::set_allowance(&self, &sender, &spender, token, amount),
+			<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),
 			<CommonWeights<T>>::approve(),
 		)
 	}
@@ -162,7 +162,7 @@
 		amount: u128,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
-			<Pallet<T>>::transfer_from(&self, &sender, &from, &to, token, amount),
+			<Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount),
 			<CommonWeights<T>>::transfer_from(),
 		)
 	}
@@ -175,7 +175,7 @@
 		amount: u128,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
-			<Pallet<T>>::burn_from(&self, &sender, &from, token, amount),
+			<Pallet<T>>::burn_from(self, &sender, &from, token, amount),
 			<CommonWeights<T>>::burn_from(),
 		)
 	}
@@ -188,7 +188,7 @@
 	) -> DispatchResultWithPostInfo {
 		let len = data.len();
 		with_weight(
-			<Pallet<T>>::set_variable_metadata(&self, &sender, token, data),
+			<Pallet<T>>::set_variable_metadata(self, &sender, token, data),
 			<CommonWeights<T>>::set_variable_metadata(len as u32),
 		)
 	}
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -189,7 +189,7 @@
 		<Balance<T>>::remove_prefix((collection.id, token_id), None);
 		<Allowance<T>>::remove_prefix((collection.id, token_id), None);
 		// TODO: ERC721 transfer event
-		return Ok(());
+		Ok(())
 	}
 
 	pub fn burn(
@@ -367,8 +367,8 @@
 			collection.check_allowlist(sender)?;
 
 			for item in data.iter() {
-				for (user, _) in &item.users {
-					collection.check_allowlist(&user)?;
+				for user in item.users.keys() {
+					collection.check_allowlist(user)?;
 				}
 			}
 		}
@@ -409,7 +409,7 @@
 
 		let mut balances = BTreeMap::new();
 		for data in &data {
-			for (owner, _) in &data.users {
+			for owner in data.users.keys() {
 				let balance = balances
 					.entry(owner)
 					.or_insert_with(|| <AccountBalance<T>>::get((collection.id, owner)));
@@ -483,8 +483,8 @@
 		amount: u128,
 	) -> DispatchResult {
 		if collection.access == AccessMode::AllowList {
-			collection.check_allowlist(&sender)?;
-			collection.check_allowlist(&spender)?;
+			collection.check_allowlist(sender)?;
+			collection.check_allowlist(spender)?;
 		}
 
 		<PalletCommon<T>>::ensure_correct_receiver(spender)?;
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -25,6 +25,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
@@ -33,7 +34,6 @@
 pub trait WeightInfo {
 	fn create_item() -> Weight;
 	fn create_multiple_items(b: u32, ) -> Weight;
-	fn burn_from() -> Weight;
 	fn burn_item_partial() -> Weight;
 	fn burn_item_fully() -> Weight;
 	fn transfer_normal() -> Weight;
@@ -45,6 +45,7 @@
 	fn transfer_from_creating() -> Weight;
 	fn transfer_from_removing() -> Weight;
 	fn transfer_from_creating_removing() -> Weight;
+	fn burn_from() -> Weight;
 	fn set_variable_metadata(b: u32, ) -> Weight;
 }
 
modifiedprimitives/nft/src/lib.rsdiffbeforeafterboth
--- a/primitives/nft/src/lib.rs
+++ b/primitives/nft/src/lib.rs
@@ -327,8 +327,7 @@
 		D: ser::Serializer,
 		V: Serialize,
 	{
-		let vec: &Vec<_> = &value;
-		vec.serialize(serializer)
+		(value as &Vec<_>).serialize(serializer)
 	}
 
 	pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>
modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -1177,6 +1177,7 @@
 			EVM::account_storages(address, H256::from_slice(&tmp[..]))
 		}
 
+		#[allow(clippy::redundant_closure)]
 		fn call(
 			from: H160,
 			to: H160,
@@ -1207,6 +1208,7 @@
 			).map_err(|err| err.into())
 		}
 
+		#[allow(clippy::redundant_closure)]
 		fn create(
 			from: H160,
 			data: Vec<u8>,