git.delta.rocks / unique-network / refs/commits / 2f442abbf92d

difftreelog

source

runtime/common/dispatch.rs6.2 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use frame_support::{dispatch::DispatchResult, ensure};18use pallet_evm::{PrecompileHandle, PrecompileResult};19use sp_core::H160;20use sp_runtime::DispatchError;21use sp_std::{borrow::ToOwned, vec::Vec};22use pallet_common::{23	CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,24	eth::map_eth_to_id,25};26pub use pallet_common::dispatch::CollectionDispatch;27use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};28use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};29use pallet_refungible::{30	Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,31};32use up_data_structs::{33	CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,34	CollectionId, CollectionFlags,35};3637#[cfg(not(feature = "refungible"))]38use pallet_common::unsupported;3940pub enum CollectionDispatchT<T>41where42	T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,43{44	Fungible(FungibleHandle<T>),45	Nonfungible(NonfungibleHandle<T>),46	Refungible(RefungibleHandle<T>),47}48impl<T> CollectionDispatch<T> for CollectionDispatchT<T>49where50	T: pallet_common::Config51		+ pallet_unique::Config52		+ pallet_fungible::Config53		+ pallet_nonfungible::Config54		+ pallet_refungible::Config,55{56	fn create(57		sender: T::CrossAccountId,58		payer: T::CrossAccountId,59		data: CreateCollectionData<T::AccountId>,60		flags: CollectionFlags,61	) -> Result<CollectionId, DispatchError> {62		let id = match data.mode {63			CollectionMode::NFT => {64				<PalletNonfungible<T>>::init_collection(sender, payer, data, flags)?65			}66			CollectionMode::Fungible(decimal_points) => {67				// check params68				ensure!(69					decimal_points <= MAX_DECIMAL_POINTS,70					pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded71				);72				<PalletFungible<T>>::init_collection(sender, payer, data, flags)?73			}7475			#[cfg(feature = "refungible")]76			CollectionMode::ReFungible => {77				<PalletRefungible<T>>::init_collection(sender, payer, data, flags)?78			}7980			#[cfg(not(feature = "refungible"))]81			CollectionMode::ReFungible => return unsupported!(T),82		};83		Ok(id)84	}8586	fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {87		match collection.mode {88			CollectionMode::ReFungible => {89				PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?90			}91			CollectionMode::Fungible(_) => {92				PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?93			}94			CollectionMode::NFT => {95				PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?96			}97		}98		Ok(())99	}100101	fn dispatch(handle: CollectionHandle<T>) -> Self {102		match handle.mode {103			CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),104			CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),105			CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),106		}107	}108109	fn into_inner(self) -> CollectionHandle<T> {110		match self {111			Self::Fungible(f) => f.into_inner(),112			Self::Nonfungible(f) => f.into_inner(),113			Self::Refungible(f) => f.into_inner(),114		}115	}116117	fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {118		match self {119			Self::Fungible(h) => h,120			Self::Nonfungible(h) => h,121			Self::Refungible(h) => h,122		}123	}124}125126impl<T> pallet_evm::OnMethodCall<T> for CollectionDispatchT<T>127where128	T: pallet_common::Config129		+ pallet_unique::Config130		+ pallet_fungible::Config131		+ pallet_nonfungible::Config132		+ pallet_refungible::Config,133	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,134{135	fn is_reserved(target: &H160) -> bool {136		map_eth_to_id(target).is_some()137	}138	fn is_used(target: &H160) -> bool {139		map_eth_to_id(target)140			.map(<CollectionById<T>>::contains_key)141			.unwrap_or(false)142	}143	fn get_code(target: &H160) -> Option<Vec<u8>> {144		if let Some(collection_id) = map_eth_to_id(target) {145			let collection = <CollectionById<T>>::get(collection_id)?;146			Some(147				match collection.mode {148					CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,149					CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,150					CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,151				}152				.to_owned(),153			)154		} else if let Some((collection_id, _token_id)) =155			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(target)156		{157			let collection = <CollectionById<T>>::get(collection_id)?;158			if collection.mode != CollectionMode::ReFungible {159				return None;160			}161			// TODO: check token existence162			Some(<RefungibleTokenHandle<T>>::CODE.to_owned())163		} else {164			None165		}166	}167	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {168		if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {169			let collection =170				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;171			let dispatched = Self::dispatch(collection);172173			match dispatched {174				Self::Fungible(h) => h.call(handle),175				Self::Nonfungible(h) => h.call(handle),176				Self::Refungible(h) => h.call(handle),177			}178		} else if let Some((collection_id, token_id)) =179			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(180				&handle.code_address(),181			) {182			let collection =183				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;184			if collection.mode != CollectionMode::ReFungible {185				return None;186			}187188			let h = RefungibleHandle::cast(collection);189			// TODO: check token existence190			RefungibleTokenHandle(h, token_id).call(handle)191		} else {192			None193		}194	}195}