git.delta.rocks / unique-network / refs/commits / 7a2dbeac9ec6

difftreelog

source

runtime/common/src/dispatch.rs6.0 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,35};3637pub enum CollectionDispatchT<T>38where39	T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,40{41	Fungible(FungibleHandle<T>),42	Nonfungible(NonfungibleHandle<T>),43	Refungible(RefungibleHandle<T>),44}45impl<T> CollectionDispatch<T> for CollectionDispatchT<T>46where47	T: pallet_common::Config48		+ pallet_unique::Config49		+ pallet_fungible::Config50		+ pallet_nonfungible::Config51		+ pallet_refungible::Config,52{53	fn create(54		sender: T::CrossAccountId,55		data: CreateCollectionData<T::AccountId>,56	) -> Result<CollectionId, DispatchError> {57		let id = match data.mode {58			CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,59			CollectionMode::Fungible(decimal_points) => {60				// check params61				ensure!(62					decimal_points <= MAX_DECIMAL_POINTS,63					pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded64				);65				<PalletFungible<T>>::init_collection(sender, data)?66			}67			#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]68			CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,6970			CollectionMode::ReFungible => {71				return Err(DispatchError::Other("Refunginle pallet is not supported"))72			}73		};74		Ok(id)75	}7677	fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {78		match collection.mode {79			CollectionMode::ReFungible => {80				PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?81			}82			CollectionMode::Fungible(_) => {83				PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?84			}85			CollectionMode::NFT => {86				PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?87			}88		}89		Ok(())90	}9192	fn dispatch(handle: CollectionHandle<T>) -> Self {93		match handle.mode {94			CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),95			CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),96			CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),97		}98	}99100	fn into_inner(self) -> CollectionHandle<T> {101		match self {102			Self::Fungible(f) => f.into_inner(),103			Self::Nonfungible(f) => f.into_inner(),104			Self::Refungible(f) => f.into_inner(),105		}106	}107108	fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {109		match self {110			Self::Fungible(h) => h,111			Self::Nonfungible(h) => h,112			Self::Refungible(h) => h,113		}114	}115}116117impl<T> pallet_evm::OnMethodCall<T> for CollectionDispatchT<T>118where119	T: pallet_common::Config120		+ pallet_unique::Config121		+ pallet_fungible::Config122		+ pallet_nonfungible::Config123		+ pallet_refungible::Config,124	T::AccountId: From<[u8; 32]>,125{126	fn is_reserved(target: &H160) -> bool {127		map_eth_to_id(target).is_some()128	}129	fn is_used(target: &H160) -> bool {130		map_eth_to_id(target)131			.map(<CollectionById<T>>::contains_key)132			.unwrap_or(false)133	}134	fn get_code(target: &H160) -> Option<Vec<u8>> {135		if let Some(collection_id) = map_eth_to_id(target) {136			let collection = <CollectionById<T>>::get(collection_id)?;137			Some(138				match collection.mode {139					CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,140					CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,141					CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,142				}143				.to_owned(),144			)145		} else if let Some((collection_id, _token_id)) =146			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(target)147		{148			let collection = <CollectionById<T>>::get(collection_id)?;149			if collection.mode != CollectionMode::ReFungible {150				return None;151			}152			// TODO: check token existence153			Some(<RefungibleTokenHandle<T>>::CODE.to_owned())154		} else {155			None156		}157	}158	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {159		if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {160			let collection =161				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;162			let dispatched = Self::dispatch(collection);163164			match dispatched {165				Self::Fungible(h) => h.call(handle),166				Self::Nonfungible(h) => h.call(handle),167				Self::Refungible(h) => h.call(handle),168			}169		} else if let Some((collection_id, token_id)) =170			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(171				&handle.code_address(),172			) {173			let collection =174				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;175			if collection.mode != CollectionMode::ReFungible {176				return None;177			}178179			let h = RefungibleHandle::cast(collection);180			// TODO: check token existence181			RefungibleTokenHandle(h, token_id).call(handle)182		} else {183			None184		}185	}186}