--- /dev/null +++ b/pallets/common/src/dispatch.rs @@ -0,0 +1,68 @@ +use frame_support::{ + dispatch::{ + DispatchResultWithPostInfo, PostDispatchInfo, Weight, DispatchErrorWithPostInfo, + DispatchResult, + }, + weights::Pays, + traits::Get, +}; +use up_data_structs::{CollectionId, CreateCollectionData}; + +use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle}; + +// TODO: move to benchmarking +/// Price of [`dispatch_call`] call with noop `call` argument +pub fn dispatch_weight() -> Weight { + // Read collection + ::DbWeight::get().reads(1) + // Dynamic dispatch? + + 6_000_000 + // submit_logs is measured as part of collection pallets +} + +/// Helper function to implement substrate calls for common collection methods +pub fn dispatch_call< + T: Config, + C: FnOnce(&dyn CommonCollectionOperations) -> DispatchResultWithPostInfo, +>( + collection: CollectionId, + call: C, +) -> DispatchResultWithPostInfo { + let handle = + CollectionHandle::try_get(collection).map_err(|error| DispatchErrorWithPostInfo { + post_info: PostDispatchInfo { + actual_weight: Some(dispatch_weight::()), + pays_fee: Pays::Yes, + }, + error, + })?; + let dispatched = T::CollectionDispatch::dispatch(handle); + let mut result = call(dispatched.as_dyn()); + match &mut result { + Ok(PostDispatchInfo { + actual_weight: Some(weight), + .. + }) + | Err(DispatchErrorWithPostInfo { + post_info: PostDispatchInfo { + actual_weight: Some(weight), + .. + }, + .. + }) => *weight += dispatch_weight::(), + _ => {} + } + + dispatched.into_inner().submit_logs(); + result +} + +pub trait CollectionDispatch { + fn create(sender: T::AccountId, data: CreateCollectionData) -> DispatchResult; + fn destroy(sender: T::CrossAccountId, handle: CollectionHandle) -> DispatchResult; + + fn dispatch(handle: CollectionHandle) -> Self; + fn into_inner(self) -> CollectionHandle; + + fn as_dyn(&self) -> &dyn CommonCollectionOperations; +} --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -21,17 +21,17 @@ use sp_std::vec::Vec; use pallet_evm::account::CrossAccountId; use frame_support::{ - dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo}, + dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo}, ensure, fail, - traits::{Imbalance, Get, Currency}, + traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement}, BoundedVec, + weights::Pays, }; use pallet_evm::GasWeightMapping; use up_data_structs::{ - COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement, - MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo, - TokenId, Weight, WithdrawReasons, CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode, - NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, + COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, MAX_TOKEN_PREFIX_LENGTH, + COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId, CollectionStats, MAX_TOKEN_OWNERSHIP, + CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits, CustomDataLimit, CreateCollectionData, SponsorshipState, CreateItemExData, SponsoringRateLimit, }; @@ -40,6 +40,7 @@ use sp_runtime::{ArithmeticError, DispatchError, DispatchResult}; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; +pub mod dispatch; pub mod erc; pub mod eth; @@ -163,9 +164,11 @@ use super::*; use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key}; use pallet_evm::account; + use dispatch::CollectionDispatch; use frame_support::traits::Currency; use up_data_structs::TokenId; use scale_info::TypeInfo; + use up_evm_mapping::CrossAccountId; #[pallet::config] pub trait Config: @@ -179,6 +182,7 @@ type CollectionCreationPrice: Get< <::Currency as Currency>::Balance, >; + type CollectionDispatch: CollectionDispatch; type TreasuryAccountId: Get; } --- a/pallets/unique/src/common.rs +++ b/pallets/unique/src/common.rs @@ -16,14 +16,14 @@ use core::marker::PhantomData; use frame_support::{weights::Weight}; -use pallet_common::{CommonWeightInfo}; +use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight}; use pallet_fungible::{common::CommonWeights as FungibleWeights}; use pallet_nonfungible::{common::CommonWeights as NonfungibleWeights}; use pallet_refungible::{common::CommonWeights as RefungibleWeights}; use up_data_structs::CreateItemExData; -use crate::{Config, dispatch::dispatch_weight}; +use crate::Config; macro_rules! max_weight_of { ($method:ident ( $($args:tt)* )) => { @@ -35,7 +35,7 @@ pub struct CommonWeights(PhantomData); impl CommonWeightInfo for CommonWeights { - fn create_item() -> up_data_structs::Weight { + fn create_item() -> Weight { dispatch_weight::() + max_weight_of!(create_item()) } @@ -51,19 +51,19 @@ dispatch_weight::() + max_weight_of!(burn_item()) } - fn transfer() -> up_data_structs::Weight { + fn transfer() -> Weight { dispatch_weight::() + max_weight_of!(transfer()) } - fn approve() -> up_data_structs::Weight { + fn approve() -> Weight { dispatch_weight::() + max_weight_of!(approve()) } - fn transfer_from() -> up_data_structs::Weight { + fn transfer_from() -> Weight { dispatch_weight::() + max_weight_of!(transfer_from()) } - fn set_variable_metadata(bytes: u32) -> up_data_structs::Weight { + fn set_variable_metadata(bytes: u32) -> Weight { dispatch_weight::() + max_weight_of!(set_variable_metadata(bytes)) } --- a/pallets/unique/src/dispatch.rs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -use frame_support::{ - dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo}, - traits::Get, - weights::Weight, -}; -use up_data_structs::{CollectionId, CollectionMode, Pays, PostDispatchInfo}; -use pallet_common::{CollectionHandle, CommonCollectionOperations}; -use pallet_fungible::FungibleHandle; -use pallet_nonfungible::NonfungibleHandle; -use pallet_refungible::RefungibleHandle; - -use crate::Config; - -// TODO: move to benchmarking -/// Price of [`dispatch_call`] call with noop `call` argument -pub fn dispatch_weight() -> Weight { - // Read collection - ::DbWeight::get().reads(1) - // Dynamic dispatch? - + 6_000_000 - // submit_logs is measured as part of collection pallets -} - -pub enum Dispatched { - Fungible(FungibleHandle), - Nonfungible(NonfungibleHandle), - Refungible(RefungibleHandle), -} -impl Dispatched { - pub fn dispatch(handle: CollectionHandle) -> Self { - match handle.mode { - CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)), - CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)), - CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)), - } - } - fn into_inner(self) -> CollectionHandle { - match self { - Dispatched::Fungible(f) => f.into_inner(), - Dispatched::Nonfungible(f) => f.into_inner(), - Dispatched::Refungible(f) => f.into_inner(), - } - } - pub fn as_dyn(&self) -> &dyn CommonCollectionOperations { - match self { - Dispatched::Fungible(h) => h, - Dispatched::Nonfungible(h) => h, - Dispatched::Refungible(h) => h, - } - } -} - -/// Helper function to implement substrate calls for common collection methods -pub fn dispatch_call< - T: Config, - C: FnOnce(&dyn pallet_common::CommonCollectionOperations) -> DispatchResultWithPostInfo, ->( - collection: CollectionId, - call: C, -) -> DispatchResultWithPostInfo { - let handle = - CollectionHandle::try_get(collection).map_err(|error| DispatchErrorWithPostInfo { - post_info: PostDispatchInfo { - actual_weight: Some(dispatch_weight::()), - pays_fee: Pays::Yes, - }, - error, - })?; - let dispatched = Dispatched::dispatch(handle); - let mut result = call(dispatched.as_dyn()); - match &mut result { - Ok(PostDispatchInfo { - actual_weight: Some(weight), - .. - }) - | Err(DispatchErrorWithPostInfo { - post_info: PostDispatchInfo { - actual_weight: Some(weight), - .. - }, - .. - }) => *weight += dispatch_weight::(), - _ => {} - } - - dispatched.into_inner().submit_logs(); - result -} --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -15,82 +15,3 @@ // along with Unique Network. If not, see . pub mod sponsoring; - -use fp_evm::PrecompileResult; -use pallet_common::{ - CollectionById, - erc::CommonEvmHandler, - eth::{map_eth_to_id, map_eth_to_token_id}, -}; -use pallet_fungible::FungibleHandle; -use pallet_nonfungible::NonfungibleHandle; -use pallet_refungible::{RefungibleHandle, erc::RefungibleTokenHandle}; -use sp_std::borrow::ToOwned; -use sp_std::vec::Vec; -use sp_core::{H160, U256}; -use crate::{CollectionMode, Config, dispatch::Dispatched}; -use pallet_common::CollectionHandle; - -pub struct UniqueErcSupport(core::marker::PhantomData); - -impl pallet_evm::OnMethodCall for UniqueErcSupport { - fn is_reserved(target: &H160) -> bool { - map_eth_to_id(target).is_some() - } - fn is_used(target: &H160) -> bool { - map_eth_to_id(target) - .map(>::contains_key) - .unwrap_or(false) - } - fn get_code(target: &H160) -> Option> { - if let Some(collection_id) = map_eth_to_id(target) { - let collection = >::get(collection_id)?; - Some( - match collection.mode { - CollectionMode::NFT => >::CODE, - CollectionMode::Fungible(_) => >::CODE, - CollectionMode::ReFungible => >::CODE, - } - .to_owned(), - ) - } else if let Some((collection_id, _token_id)) = map_eth_to_token_id(target) { - let collection = >::get(collection_id)?; - if collection.mode != CollectionMode::ReFungible { - return None; - } - // TODO: check token existence - Some(>::CODE.to_owned()) - } else { - None - } - } - fn call( - source: &H160, - target: &H160, - gas_limit: u64, - input: &[u8], - value: U256, - ) -> Option { - if let Some(collection_id) = map_eth_to_id(target) { - let collection = >::new_with_gas_limit(collection_id, gas_limit)?; - let dispatched = Dispatched::dispatch(collection); - - match dispatched { - Dispatched::Fungible(h) => h.call(source, input, value), - Dispatched::Nonfungible(h) => h.call(source, input, value), - Dispatched::Refungible(h) => h.call(source, input, value), - } - } else if let Some((collection_id, token_id)) = map_eth_to_token_id(target) { - let collection = >::new_with_gas_limit(collection_id, gas_limit)?; - if collection.mode != CollectionMode::ReFungible { - return None; - } - - let handle = RefungibleHandle::cast(collection); - // TODO: check token existence - RefungibleTokenHandle(handle, token_id).call(source, input, value) - } else { - None - } - } -} --- a/pallets/unique/src/eth/sponsoring.rs +++ b/pallets/unique/src/eth/sponsoring.rs @@ -25,6 +25,7 @@ use core::marker::PhantomData; use core::convert::TryInto; use pallet_evm::account::CrossAccountId; +use up_data_structs::{TokenId, CreateItemData, CreateNftData}; use pallet_nonfungible::erc::{ UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call, --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -26,20 +26,12 @@ pub use serde::{Serialize, Deserialize}; -pub use frame_support::{ - construct_runtime, decl_module, decl_storage, decl_error, decl_event, +use frame_support::{ + decl_module, decl_storage, decl_error, decl_event, dispatch::DispatchResult, - ensure, fail, parameter_types, - traits::{ - ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness, - IsSubType, WithdrawReasons, - }, - weights::{ - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, - DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight, - WeightToFeePolynomial, DispatchClass, - }, - StorageValue, transactional, + ensure, + weights::{Weight}, + transactional, pallet_prelude::{DispatchResultWithPostInfo, ConstU32}, BoundedVec, }; @@ -47,17 +39,17 @@ use frame_system::{self as system, ensure_signed}; use sp_runtime::{sp_std::prelude::Vec}; use up_data_structs::{ - MAX_DECIMAL_POINTS, VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, - OFFCHAIN_SCHEMA_LIMIT, MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, - MAX_TOKEN_PREFIX_LENGTH, AccessMode, CreateItemData, CollectionLimits, CollectionId, - CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission, - CreateCollectionData, CustomDataLimit, CreateItemExData, + VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT, + MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, + AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId, + SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData, CustomDataLimit, + CreateItemExData, }; -use pallet_common::{CollectionHandle, Pallet as PalletCommon, Error as CommonError, CommonWeightInfo}; use pallet_evm::account::CrossAccountId; -use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle}; -use pallet_fungible::{Pallet as PalletFungible, FungibleHandle}; -use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle}; +use pallet_common::{ + CollectionHandle, Pallet as PalletCommon, Error as CommonError, CommonWeightInfo, + dispatch::dispatch_call, dispatch::CollectionDispatch, +}; #[cfg(test)] mod mock; @@ -70,12 +62,8 @@ pub use sponsorship::{UniqueSponsorshipHandler, UniqueSponsorshipPredict}; pub use eth::sponsoring::UniqueEthSponsorshipHandler; -pub use eth::UniqueErcSupport; - pub mod common; use common::CommonWeights; -pub mod dispatch; -use dispatch::dispatch_call; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; @@ -352,19 +340,11 @@ #[weight = >::create_collection()] #[transactional] pub fn create_collection_ex(origin, data: CreateCollectionData) -> DispatchResult { - let owner = ensure_signed(origin)?; + let sender = ensure_signed(origin)?; + + // ========= - let _id = match data.mode { - CollectionMode::NFT => {>::init_collection(owner, data)?}, - CollectionMode::Fungible(decimal_points) => { - // check params - ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::::CollectionDecimalPointLimitExceeded); - >::init_collection(owner, data)? - } - CollectionMode::ReFungible => { - >::init_collection(owner, data)? - } - }; + T::CollectionDispatch::create(sender, data)?; Ok(()) } @@ -382,17 +362,11 @@ #[transactional] pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult { let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); - let collection = >::try_get(collection_id)?; - collection.check_is_owner(&sender)?; // ========= - match collection.mode { - CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?, - CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?, - CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?, - } + T::CollectionDispatch::destroy(sender, collection)?; >::remove_prefix(collection_id, None); >::remove_prefix(collection_id, None); --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -12,12 +12,19 @@ default = ['std'] std = [ 'sp-core/std', + 'sp-std/std', 'sp-runtime/std', 'codec/std', 'frame-support/std', 'frame-system/std', 'sp-consensus-aura/std', 'pallet-common/std', + 'pallet-unique/std', + 'pallet-fungible/std', + 'pallet-nonfungible/std', + 'pallet-refungible/std', + 'up-data-structs/std', + 'pallet-evm/std', 'fp-rpc/std', ] runtime-benchmarks = [ @@ -31,6 +38,11 @@ git = "https://github.com/paritytech/substrate" branch = "polkadot-v0.9.20" +[dependencies.sp-std] +default-features = false +git = 'https://github.com/paritytech/substrate.git' +branch = 'polkadot-v0.9.17' + [dependencies.sp-runtime] default-features = false git = "https://github.com/paritytech/substrate" @@ -61,6 +73,31 @@ default-features = false path = "../../pallets/common" +[dependencies.pallet-unique] +default-features = false +path = "../../pallets/unique" + +[dependencies.pallet-fungible] +default-features = false +path = "../../pallets/fungible" + +[dependencies.pallet-nonfungible] +default-features = false +path = "../../pallets/nonfungible" + +[dependencies.pallet-refungible] +default-features = false +path = "../../pallets/refungible" + +[dependencies.up-data-structs] +default-features = false +path = "../../primitives/data-structs" + +[dependencies.pallet-evm] +default-features = false +git = "https://github.com/uniquenetwork/frontier.git" +branch = "unique-polkadot-v0.9.17" + [dependencies.sp-consensus-aura] default-features = false git = "https://github.com/paritytech/substrate" --- /dev/null +++ b/runtime/common/src/dispatch.rs @@ -0,0 +1,160 @@ +use frame_support::{dispatch::DispatchResult, ensure}; +use pallet_evm::PrecompileResult; +use sp_core::{H160, U256}; +use sp_std::{borrow::ToOwned, vec::Vec}; +use pallet_common::{ + CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler, + eth::map_eth_to_id, +}; +pub use pallet_common::dispatch::CollectionDispatch; +use pallet_fungible::{Pallet as PalletFungible, FungibleHandle}; +use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle}; +use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle, erc::RefungibleTokenHandle}; +use up_data_structs::{ + CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping, +}; + +pub enum CollectionDispatchT +where + T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config, +{ + Fungible(FungibleHandle), + Nonfungible(NonfungibleHandle), + Refungible(RefungibleHandle), +} +impl CollectionDispatch for CollectionDispatchT +where + T: pallet_common::Config + + pallet_unique::Config + + pallet_fungible::Config + + pallet_nonfungible::Config + + pallet_refungible::Config, +{ + fn create(sender: T::AccountId, data: CreateCollectionData) -> DispatchResult { + let _id = match data.mode { + CollectionMode::NFT => >::init_collection(sender, data)?, + CollectionMode::Fungible(decimal_points) => { + // check params + ensure!( + decimal_points <= MAX_DECIMAL_POINTS, + pallet_unique::Error::::CollectionDecimalPointLimitExceeded + ); + >::init_collection(sender, data)? + } + CollectionMode::ReFungible => >::init_collection(sender, data)?, + }; + Ok(()) + } + + fn destroy(sender: T::CrossAccountId, collection: CollectionHandle) -> DispatchResult { + match collection.mode { + CollectionMode::ReFungible => { + PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)? + } + CollectionMode::Fungible(_) => { + PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)? + } + CollectionMode::NFT => { + PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)? + } + } + Ok(()) + } + + fn dispatch(handle: CollectionHandle) -> Self { + match handle.mode { + CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)), + CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)), + CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)), + } + } + + fn into_inner(self) -> CollectionHandle { + match self { + Self::Fungible(f) => f.into_inner(), + Self::Nonfungible(f) => f.into_inner(), + Self::Refungible(f) => f.into_inner(), + } + } + + fn as_dyn(&self) -> &dyn CommonCollectionOperations { + match self { + Self::Fungible(h) => h, + Self::Nonfungible(h) => h, + Self::Refungible(h) => h, + } + } +} + +impl pallet_evm::OnMethodCall for CollectionDispatchT +where + T: pallet_common::Config + + pallet_unique::Config + + pallet_fungible::Config + + pallet_nonfungible::Config + + pallet_refungible::Config, +{ + fn is_reserved(target: &H160) -> bool { + map_eth_to_id(target).is_some() + } + fn is_used(target: &H160) -> bool { + map_eth_to_id(target) + .map(>::contains_key) + .unwrap_or(false) + } + fn get_code(target: &H160) -> Option> { + if let Some(collection_id) = map_eth_to_id(target) { + let collection = >::get(collection_id)?; + Some( + match collection.mode { + CollectionMode::NFT => >::CODE, + CollectionMode::Fungible(_) => >::CODE, + CollectionMode::ReFungible => >::CODE, + } + .to_owned(), + ) + } else if let Some((collection_id, _token_id)) = + ::EvmTokenAddressMapping::address_to_token(target) + { + let collection = >::get(collection_id)?; + if collection.mode != CollectionMode::ReFungible { + return None; + } + // TODO: check token existence + Some(>::CODE.to_owned()) + } else { + None + } + } + fn call( + source: &H160, + target: &H160, + gas_limit: u64, + input: &[u8], + value: U256, + ) -> Option { + if let Some(collection_id) = map_eth_to_id(target) { + let collection = >::new_with_gas_limit(collection_id, gas_limit)?; + let dispatched = Self::dispatch(collection); + + match dispatched { + Self::Fungible(h) => h.call(source, input, value), + Self::Nonfungible(h) => h.call(source, input, value), + Self::Refungible(h) => h.call(source, input, value), + } + } else if let Some((collection_id, token_id)) = + ::EvmTokenAddressMapping::address_to_token(target) + { + let collection = >::new_with_gas_limit(collection_id, gas_limit)?; + if collection.mode != CollectionMode::ReFungible { + return None; + } + + let handle = RefungibleHandle::cast(collection); + // TODO: check token existence + RefungibleTokenHandle(handle, token_id).call(source, input, value) + } else { + None + } + } +} --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod constants; +pub mod dispatch; pub mod runtime_apis; pub mod types; --- a/runtime/opal/src/lib.rs +++ b/runtime/opal/src/lib.rs @@ -58,7 +58,7 @@ traits::{ tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier, - OnUnbalanced, Randomness, FindAuthor, + OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -66,7 +66,7 @@ WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier, }, }; -use up_data_structs::*; +use up_data_structs::{CollectionId, TokenId, CollectionStats, Collection}; // use pallet_contracts::weights::WeightInfo; // #[cfg(any(feature = "std", test))] use frame_system::{ @@ -114,7 +114,12 @@ //use xcm_executor::traits::MatchesFungible; use sp_runtime::traits::CheckedConversion; -use unique_runtime_common::{impl_common_runtime_apis, types::*, constants::*}; +use unique_runtime_common::{ + impl_common_runtime_apis, + types::*, + constants::*, + dispatch::{CollectionDispatchT, CollectionDispatch}, +}; pub const RUNTIME_NAME: &str = "opal"; pub const TOKEN_SYMBOL: &str = "OPL"; @@ -295,8 +300,8 @@ type Event = Event; type OnMethodCall = ( pallet_evm_migration::OnMethodCall, - pallet_unique::UniqueErcSupport, pallet_evm_contract_helpers::HelpersOnMethodCall, + CollectionDispatchT, ); type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate; type ChainId = ChainId; @@ -871,8 +876,18 @@ type Currency = Balances; type CollectionCreationPrice = CollectionCreationPrice; type TreasuryAccountId = TreasuryAccountId; + type CollectionDispatch = CollectionDispatchT; + + type EvmTokenAddressMapping = EvmTokenAddressMapping; + type CrossTokenAddressMapping = CrossTokenAddressMapping; } +impl pallet_structure::Config for Runtime { + type Event = Event; + type Call = Call; + type WeightInfo = pallet_structure::weights::SubstrateWeight; +} + impl pallet_fungible::Config for Runtime { type WeightInfo = pallet_fungible::weights::SubstrateWeight; } @@ -1119,9 +1134,7 @@ macro_rules! dispatch_unique_runtime { ($collection:ident.$method:ident($($name:ident),*)) => {{ - use pallet_unique::dispatch::Dispatched; - - let collection = Dispatched::dispatch(>::try_get($collection)?); + let collection = ::CollectionDispatch::dispatch(>::try_get($collection)?); let dispatch = collection.as_dyn(); Ok(dispatch.$method($($name),*)) --- a/runtime/quartz/src/lib.rs +++ b/runtime/quartz/src/lib.rs @@ -58,7 +58,7 @@ traits::{ tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier, - OnUnbalanced, Randomness, FindAuthor, + OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -66,6 +66,7 @@ WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier, }, }; +use unique_runtime_common::dispatch::{CollectionDispatchT, CollectionDispatch}; use up_data_structs::*; // use pallet_contracts::weights::WeightInfo; // #[cfg(any(feature = "std", test))] @@ -92,6 +93,7 @@ // Polkadot imports use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; +use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping}; use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*}; use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, @@ -274,8 +276,8 @@ type Event = Event; type OnMethodCall = ( pallet_evm_migration::OnMethodCall, - pallet_unique::UniqueErcSupport, pallet_evm_contract_helpers::HelpersOnMethodCall, + CollectionDispatchT, ); type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate; type ChainId = ChainId; @@ -851,8 +853,18 @@ type Currency = Balances; type CollectionCreationPrice = CollectionCreationPrice; type TreasuryAccountId = TreasuryAccountId; + type CollectionDispatch = CollectionDispatchT; + + type EvmTokenAddressMapping = EvmTokenAddressMapping; + type CrossTokenAddressMapping = CrossTokenAddressMapping; } +impl pallet_structure::Config for Runtime { + type Event = Event; + type Call = Call; + type WeightInfo = pallet_structure::weights::SubstrateWeight; +} + impl pallet_evm::account::Config for Runtime { type CrossAccountId = pallet_evm::account::BasicCrossAccountId; type EvmAddressMapping = HashedAddressMapping; @@ -979,6 +991,7 @@ Fungible: pallet_fungible::{Pallet, Storage} = 67, Refungible: pallet_refungible::{Pallet, Storage} = 68, Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69, + Structure: pallet_structure::{Pallet, Call, Storage, Event} = 70, // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, @@ -1105,9 +1118,7 @@ macro_rules! dispatch_unique_runtime { ($collection:ident.$method:ident($($name:ident),*)) => {{ - use pallet_unique::dispatch::Dispatched; - - let collection = Dispatched::dispatch(>::try_get($collection)?); + let collection = ::CollectionDispatch::dispatch(>::try_get($collection)?); let dispatch = collection.as_dyn(); Ok(dispatch.$method($($name),*)) --- a/runtime/unique/src/lib.rs +++ b/runtime/unique/src/lib.rs @@ -58,7 +58,7 @@ traits::{ tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier, - OnUnbalanced, Randomness, FindAuthor, + OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -66,6 +66,7 @@ WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier, }, }; +use unique_runtime_common::dispatch::{CollectionDispatchT, CollectionDispatch}; use up_data_structs::*; // use pallet_contracts::weights::WeightInfo; // #[cfg(any(feature = "std", test))] @@ -91,6 +92,7 @@ // Polkadot imports use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; +use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping}; use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*}; use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, @@ -273,8 +275,8 @@ type Event = Event; type OnMethodCall = ( pallet_evm_migration::OnMethodCall, - pallet_unique::UniqueErcSupport, pallet_evm_contract_helpers::HelpersOnMethodCall, + CollectionDispatchT, ); type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate; type ChainId = ChainId; @@ -849,8 +851,18 @@ type Currency = Balances; type CollectionCreationPrice = CollectionCreationPrice; type TreasuryAccountId = TreasuryAccountId; + type CollectionDispatch = CollectionDispatchT; + + type EvmTokenAddressMapping = EvmTokenAddressMapping; + type CrossTokenAddressMapping = CrossTokenAddressMapping; } +impl pallet_structure::Config for Runtime { + type Event = Event; + type Call = Call; + type WeightInfo = pallet_structure::weights::SubstrateWeight; +} + impl pallet_evm::account::Config for Runtime { type CrossAccountId = pallet_evm::account::BasicCrossAccountId; type EvmAddressMapping = HashedAddressMapping; @@ -977,6 +989,7 @@ Fungible: pallet_fungible::{Pallet, Storage} = 67, Refungible: pallet_refungible::{Pallet, Storage} = 68, Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69, + Structure: pallet_structure::{Pallet, Call, Storage, Event} = 70, // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, @@ -1103,9 +1116,7 @@ macro_rules! dispatch_unique_runtime { ($collection:ident.$method:ident($($name:ident),*)) => {{ - use pallet_unique::dispatch::Dispatched; - - let collection = Dispatched::dispatch(>::try_get($collection)?); + let collection = ::CollectionDispatch::dispatch(>::try_get($collection)?); let dispatch = collection.as_dyn(); Ok(dispatch.$method($($name),*))