--- a/crates/evm-coder/procedural/src/abi_derive.rs +++ b/crates/evm-coder/procedural/src/abi_derive.rs @@ -28,15 +28,25 @@ let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name); let abi_type = impl_abi_type(name, field_types.clone()); - let abi_read = impl_abi_read(name, is_named_fields, field_names.clone(), field_types); - let abi_write = impl_abi_write(name, is_named_fields, params_count, field_names); - // let solidity_tuple_type = + let abi_read = impl_abi_read( + name, + is_named_fields, + field_names.clone(), + field_types.clone(), + ); + let abi_write = impl_abi_write(name, is_named_fields, params_count, field_names.clone()); + let solidity_type = impl_solidity_type(name, field_types.clone(), params_count); + let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count); + let solidity_struct_collect = impl_solidity_struct_collect(name, field_names, field_types); Ok(quote! { #can_be_plcaed_in_vec #abi_type #abi_read #abi_write + #solidity_type + #solidity_type_name + #solidity_struct_collect }) } @@ -173,3 +183,112 @@ } ) } + +fn impl_solidity_type<'a>( + name: &syn::Ident, + field_types: impl Iterator + Clone, + params_count: usize, +) -> proc_macro2::TokenStream { + let len = proc_macro2::Literal::usize_suffixed(params_count); + quote! { + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::SolidityType for #name { + fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec { + let mut collected = + Vec::with_capacity(::len()); + #({ + let mut out = String::new(); + <#field_types as ::evm_coder::solidity::SolidityTypeName>::solidity_name(&mut out, tc) + .expect("no fmt error"); + collected.push(out); + })* + collected + } + + fn len() -> usize { + #len + } + } + } +} + +fn impl_solidity_type_name<'a>( + name: &syn::Ident, + field_types: impl Iterator + Clone, + params_count: usize, +) -> proc_macro2::TokenStream { + let arg_dafaults = field_types.enumerate().map(|(i, ty)| { + let mut defult_value = quote!(<#ty as ::evm_coder::solidity::SolidityTypeName + >::solidity_default(writer, tc)?;); + let last_item = params_count - 1; + if i != last_item { + defult_value.extend(quote! {write!(writer, ",")?;}) + } + defult_value + }); + + quote! { + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::SolidityTypeName for #name { + fn solidity_name( + writer: &mut impl ::core::fmt::Write, + tc: &::evm_coder::solidity::TypeCollector, + ) -> ::core::fmt::Result { + write!(writer, "{}", tc.collect_struct::()) + } + + fn is_simple() -> bool { + false + } + + fn solidity_default( + writer: &mut impl ::core::fmt::Write, + tc: &::evm_coder::solidity::TypeCollector, + ) -> ::core::fmt::Result { + write!(writer, "{}(", tc.collect_struct::())?; + + #(#arg_dafaults)* + + write!(writer, ")") + } + } + } +} + +fn impl_solidity_struct_collect<'a>( + name: &syn::Ident, + field_names: impl Iterator + Clone, + field_types: impl Iterator + Clone, +) -> proc_macro2::TokenStream { + let string_name = name.to_string(); + let name_type = field_names + .into_iter() + .zip(field_types.into_iter()) + .map(|(name, ty)| { + let name = format!("{}", name); + quote!( + write!(str, "\t{} ", <#ty as ::evm_coder::solidity::StructCollect>::name()).unwrap(); + write!(str, "{};", #name).unwrap(); + ) + }); + + quote! { + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::StructCollect for #name { + fn name() -> String { + #string_name.into() + } + + fn declaration() -> String { + use std::fmt::Write; + + let mut str = String::new(); + writeln!(str, "/// @dev Cross account struct").unwrap(); + writeln!(str, "struct {} {{", Self::name()).unwrap(); + #(#name_type)* + writeln!(str, "}}").unwrap(); + str + } + } + } +} --- a/crates/evm-coder/src/solidity/impls.rs +++ b/crates/evm-coder/src/solidity/impls.rs @@ -1,4 +1,4 @@ -use super::{TypeCollector, SolidityTypeName, SolidityType}; +use super::{TypeCollector, SolidityTypeName, SolidityType, StructCollect}; use crate::{sealed, types::*}; use core::fmt; @@ -16,6 +16,16 @@ write!(writer, $default) } } + + impl StructCollect for $ty { + fn name() -> String { + $name.to_string() + } + + fn declaration() -> String { + String::default() + } + } )* }; } --- a/pallets/common/src/eth.rs +++ b/pallets/common/src/eth.rs @@ -154,72 +154,3 @@ } } } - -#[cfg(feature = "stubgen")] -impl ::evm_coder::solidity::SolidityType for EthCrossAccount { - fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec { - let mut collected = - Vec::with_capacity(::len()); - { - let mut out = String::new(); -
::solidity_name(&mut out, tc) - .expect("no fmt error"); - collected.push(out); - } - { - let mut out = String::new(); - ::solidity_name(&mut out, tc) - .expect("no fmt error"); - collected.push(out); - } - collected - } - - fn len() -> usize { - 2 - } -} - -#[cfg(feature = "stubgen")] -impl ::evm_coder::solidity::SolidityTypeName for EthCrossAccount { - fn solidity_name( - writer: &mut impl ::core::fmt::Write, - tc: &::evm_coder::solidity::TypeCollector, - ) -> ::core::fmt::Result { - write!(writer, "{}", tc.collect_struct::()) - } - - fn is_simple() -> bool { - false - } - - fn solidity_default( - writer: &mut impl ::core::fmt::Write, - tc: &::evm_coder::solidity::TypeCollector, - ) -> ::core::fmt::Result { - write!(writer, "{}(", tc.collect_struct::())?; - address::solidity_default(writer, tc)?; - write!(writer, ",")?; - uint256::solidity_default(writer, tc)?; - write!(writer, ")") - } -} - -#[cfg(feature = "stubgen")] -impl ::evm_coder::solidity::StructCollect for EthCrossAccount { - fn name() -> String { - "EthCrossAccount".into() - } - - fn declaration() -> String { - use std::fmt::Write; - - let mut str = String::new(); - writeln!(str, "/// @dev Cross account struct").unwrap(); - writeln!(str, "struct {} {{", Self::name()).unwrap(); - writeln!(str, "\taddress eth;").unwrap(); - writeln!(str, "\tuint256 sub;").unwrap(); - writeln!(str, "}}").unwrap(); - str - } -}