From edc04ac6ff0c4c3ca075a5731c848316de3a6ab9 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 12 May 2022 12:58:13 +0000 Subject: [PATCH] feat: delegate erc call to other struct --- --- a/crates/evm-coder-macros/src/solidity_interface.rs +++ b/crates/evm-coder-macros/src/solidity_interface.rs @@ -23,6 +23,7 @@ use syn::{ Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta, MetaNameValue, NestedMeta, PatType, Path, PathArguments, ReturnType, Type, spanned::Spanned, + parse_str, }; use crate::{ @@ -35,16 +36,21 @@ name: Ident, pascal_call_name: Ident, snake_call_name: Ident, + via: Option<(Type, Ident)>, } impl Is { - fn try_from(path: &Path) -> syn::Result { + fn new_via(path: &Path, via: Option<(Type, Ident)>) -> syn::Result { let name = parse_ident_from_path(path, false)?.clone(); Ok(Self { pascal_call_name: pascal_ident_to_call(&name), snake_call_name: pascal_ident_to_snake_call(&name), name, + via, }) } + fn new(path: &Path) -> syn::Result { + Self::new_via(path, None) + } fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream { let name = &self.name; @@ -85,8 +91,18 @@ ) -> proc_macro2::TokenStream { let name = &self.name; let pascal_call_name = &self.pascal_call_name; + let via_typ = self + .via + .as_ref() + .map(|(t, _)| quote! {#t}) + .unwrap_or_else(|| quote! {Self}); + let via_map = self + .via + .as_ref() + .map(|(_, i)| quote! {.#i()}) + .unwrap_or_default(); quote! { - #call_name::#name(call) => return >::call(self, Msg { + #call_name::#name(call) => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg { call, caller: c.caller, value: c.value, @@ -126,8 +142,46 @@ let mut out = Vec::new(); for item in items { match item { - NestedMeta::Meta(Meta::Path(path)) => out.push(Is::try_from(path)?), - _ => return Err(syn::Error::new(item.span(), "expected path").into()), + NestedMeta::Meta(Meta::Path(path)) => out.push(Is::new(path)?), + // TODO: replace meta parsing with manual + NestedMeta::Meta(Meta::List(list)) + if list.path.is_ident("via") && list.nested.len() == 3 => + { + let mut data = list.nested.iter(); + let typ = match data.next().expect("len == 3") { + NestedMeta::Lit(Lit::Str(s)) => { + let v = s.value(); + let typ: Type = parse_str(&v)?; + typ + } + _ => { + return Err(syn::Error::new( + item.span(), + "via typ should be type in string", + ) + .into()) + } + }; + let via = match data.next().expect("len == 3") { + NestedMeta::Meta(Meta::Path(path)) => path + .get_ident() + .ok_or_else(|| syn::Error::new(item.span(), "via should be ident"))?, + _ => return Err(syn::Error::new(item.span(), "via should be ident").into()), + }; + let path = match data.next().expect("len == 3") { + NestedMeta::Meta(Meta::Path(path)) => path, + _ => return Err(syn::Error::new(item.span(), "path should be path").into()), + }; + + out.push(Is::new_via(path, Some((typ, via.clone())))?) + } + _ => { + return Err(syn::Error::new( + item.span(), + "expected either Name or via(\"Type\", getter, Name)", + ) + .into()) + } } } Ok(Self(out)) --- a/pallets/common/src/erc.rs +++ b/pallets/common/src/erc.rs @@ -14,9 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -pub use pallet_evm::PrecompileOutput; -pub use pallet_evm::PrecompileResult; +use evm_coder::{solidity_interface, types::*, execution::Result}; +pub use pallet_evm::{PrecompileOutput, PrecompileResult, account::CrossAccountId}; +use pallet_evm_coder_substrate::dispatch_to_evm; use sp_core::{H160, U256}; +use sp_std::vec::Vec; +use up_data_structs::Property; + +use crate::{Pallet, CollectionHandle, Config}; /// Does not always represent a full collection, for RFT it is either /// collection (Implementing ERC721), or specific collection token (Implementing ERC20) @@ -25,3 +30,27 @@ fn call(self, source: &H160, input: &[u8], value: U256) -> Option; } + +#[solidity_interface(name = "CollectionProperties")] +impl CollectionHandle { + fn set_property(&mut self, caller: caller, key: string, value: string) -> Result<()> { + >::set_collection_property( + self, + &T::CrossAccountId::from_eth(caller), + Property { + key: >::from(key) + .try_into() + .map_err(|_| "key too large")?, + value: >::from(value) + .try_into() + .map_err(|_| "value too large")?, + }, + ) + .map_err(dispatch_to_evm::)?; + Ok(()) + } + + fn delete_property(&mut self, caller: caller, key: string) -> Result<()> { + self.set_property(caller, key, string::new()) + } +} --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -595,7 +595,7 @@ .iter() .map(|(key, value)| Property { key: key.clone(), - value: value.clone() + value: value.clone(), }) .collect(); @@ -680,19 +680,20 @@ }; let mut collection_properties = up_data_structs::CollectionProperties::get(); - collection_properties.try_set_from_iter( - data.properties.into_iter() - .map(|p| (p.key, p.value)) - ).map_err(|e| -> Error { e.into() })?; + collection_properties + .try_set_from_iter(data.properties.into_iter().map(|p| (p.key, p.value))) + .map_err(|e| -> Error { e.into() })?; CollectionProperties::::insert(id, collection_properties); let mut token_props_permissions = PropertiesPermissionMap::new(); - token_props_permissions.try_set_from_iter( - data.token_property_permissions - .into_iter() - .map(|property| (property.key, property.permission)) - ).map_err(|e| -> Error { e.into() })?; + token_props_permissions + .try_set_from_iter( + data.token_property_permissions + .into_iter() + .map(|property| (property.key, property.permission)), + ) + .map_err(|e| -> Error { e.into() })?; CollectionPropertyPermissions::::insert(id, token_props_permissions); @@ -806,7 +807,8 @@ CollectionProperties::::try_mutate(collection.id, |properties| { properties.remove(&property_key) - }).map_err(|e| -> Error { e.into() })?; + }) + .map_err(|e| -> Error { e.into() })?; Self::deposit_event(Event::CollectionPropertyDeleted( collection.id, @@ -903,11 +905,10 @@ let properties = keys .into_iter() .filter_map(|key| { - properties.get(&key) - .map(|value| Property { - key, - value: value.clone(), - }) + properties.get(&key).map(|value| Property { + key, + value: value.clone(), + }) }) .collect(); --- a/pallets/fungible/src/erc.rs +++ b/pallets/fungible/src/erc.rs @@ -24,6 +24,7 @@ use pallet_evm::account::CrossAccountId; use pallet_evm_coder_substrate::{call, dispatch_to_evm}; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; +use pallet_common::{CollectionHandle, erc::CollectionPropertiesCall}; use crate::{ Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply, @@ -144,7 +145,14 @@ } } -#[solidity_interface(name = "UniqueFungible", is(ERC20))] +#[solidity_interface( + name = "UniqueFungible", + is( + ERC20, + ERC20UniqueExtensions, + via("CollectionHandle", common_mut, CollectionProperties) + ) +)] impl FungibleHandle {} generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true); --- a/pallets/fungible/src/lib.rs +++ b/pallets/fungible/src/lib.rs @@ -110,6 +110,9 @@ pub fn into_inner(self) -> pallet_common::CollectionHandle { self.0 } + pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle { + &mut self.0 + } } impl WithRecorder for FungibleHandle { fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder { --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -391,11 +391,10 @@ keys.into_iter() .filter_map(|key| { - properties.get(&key) - .map(|value| Property { - key, - value: value.clone(), - }) + properties.get(&key).map(|value| Property { + key, + value: value.clone(), + }) }) .collect() } --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -26,7 +26,8 @@ use sp_core::{H160, U256}; use sp_std::{vec::Vec, vec}; use pallet_common::{ - erc::{CommonEvmHandler, PrecompileResult}, + erc::{CommonEvmHandler, PrecompileResult, CollectionPropertiesCall}, + CollectionHandle, }; use pallet_evm::account::CrossAccountId; use pallet_evm_coder_substrate::call; @@ -504,6 +505,7 @@ ERC721UniqueExtensions, ERC721Mintable, ERC721Burnable, + via("CollectionHandle", common_mut, CollectionProperties) ) )] impl NonfungibleHandle {} --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -142,6 +142,9 @@ pub fn into_inner(self) -> pallet_common::CollectionHandle { self.0 } + pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle { + &mut self.0 + } } impl WithRecorder for NonfungibleHandle { fn recorder(&self) -> &SubstrateRecorder { @@ -302,7 +305,8 @@ >::try_mutate((collection.id, token_id), |properties| { properties.remove(&property_key) - }).map_err(|e| -> CommonError { e.into() })?; + }) + .map_err(|e| -> CommonError { e.into() })?; >::deposit_event(CommonEvent::TokenPropertyDeleted( collection.id, --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -699,7 +699,7 @@ fn try_set_from_iter(&mut self, iter: I) -> Result<(), PropertiesError> where - I: Iterator + I: Iterator, { for (key, value) in iter { self.try_set(key, value)?; @@ -711,7 +711,9 @@ #[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)] #[derivative(Default(bound = ""))] -pub struct PropertiesMap(BoundedBTreeMap>); +pub struct PropertiesMap( + BoundedBTreeMap>, +); impl PropertiesMap { pub fn new() -> Self { -- gitstuff