git.delta.rocks / unique-network / refs/commits / d7a4e69fe08d

difftreelog

source

runtime/common/src/dispatch.rs5.8 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_std::{borrow::ToOwned, vec::Vec};21use pallet_common::{22	CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,23	eth::map_eth_to_id,24};25pub use pallet_common::dispatch::CollectionDispatch;26use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};27use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};28use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle, erc20::RefungibleTokenHandle};29use up_data_structs::{30	CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,31};3233pub enum CollectionDispatchT<T>34where35	T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,36{37	Fungible(FungibleHandle<T>),38	Nonfungible(NonfungibleHandle<T>),39	Refungible(RefungibleHandle<T>),40}41impl<T> CollectionDispatch<T> for CollectionDispatchT<T>42where43	T: pallet_common::Config44		+ pallet_unique::Config45		+ pallet_fungible::Config46		+ pallet_nonfungible::Config47		+ pallet_refungible::Config,48{49	fn create(50		sender: T::CrossAccountId,51		data: CreateCollectionData<T::AccountId>,52	) -> DispatchResult {53		let _id = match data.mode {54			CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,55			CollectionMode::Fungible(decimal_points) => {56				// check params57				ensure!(58					decimal_points <= MAX_DECIMAL_POINTS,59					pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded60				);61				<PalletFungible<T>>::init_collection(sender, data)?62			}63			CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,64		};65		Ok(())66	}6768	fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {69		match collection.mode {70			CollectionMode::ReFungible => {71				PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?72			}73			CollectionMode::Fungible(_) => {74				PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?75			}76			CollectionMode::NFT => {77				PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?78			}79		}80		Ok(())81	}8283	fn dispatch(handle: CollectionHandle<T>) -> Self {84		match handle.mode {85			CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),86			CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),87			CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),88		}89	}9091	fn into_inner(self) -> CollectionHandle<T> {92		match self {93			Self::Fungible(f) => f.into_inner(),94			Self::Nonfungible(f) => f.into_inner(),95			Self::Refungible(f) => f.into_inner(),96		}97	}9899	fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {100		match self {101			Self::Fungible(h) => h,102			Self::Nonfungible(h) => h,103			Self::Refungible(h) => h,104		}105	}106}107108impl<T> pallet_evm::OnMethodCall<T> for CollectionDispatchT<T>109where110	T: pallet_common::Config111		+ pallet_unique::Config112		+ pallet_fungible::Config113		+ pallet_nonfungible::Config114		+ pallet_refungible::Config,115	T::AccountId: From<[u8; 32]>,116{117	fn is_reserved(target: &H160) -> bool {118		map_eth_to_id(target).is_some()119	}120	fn is_used(target: &H160) -> bool {121		map_eth_to_id(target)122			.map(<CollectionById<T>>::contains_key)123			.unwrap_or(false)124	}125	fn get_code(target: &H160) -> Option<Vec<u8>> {126		if let Some(collection_id) = map_eth_to_id(target) {127			let collection = <CollectionById<T>>::get(collection_id)?;128			Some(129				match collection.mode {130					CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,131					CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,132					CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,133				}134				.to_owned(),135			)136		} else if let Some((collection_id, _token_id)) =137			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(target)138		{139			let collection = <CollectionById<T>>::get(collection_id)?;140			if collection.mode != CollectionMode::ReFungible {141				return None;142			}143			// TODO: check token existence144			Some(<RefungibleTokenHandle<T>>::CODE.to_owned())145		} else {146			None147		}148	}149	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {150		if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {151			let collection =152				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;153			let dispatched = Self::dispatch(collection);154155			match dispatched {156				Self::Fungible(h) => h.call(handle),157				Self::Nonfungible(h) => h.call(handle),158				Self::Refungible(h) => h.call(handle),159			}160		} else if let Some((collection_id, token_id)) =161			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(162				&handle.code_address(),163			) {164			let collection =165				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;166			if collection.mode != CollectionMode::ReFungible {167				return None;168			}169170			let h = RefungibleHandle::cast(collection);171			// TODO: check token existence172			RefungibleTokenHandle(h, token_id).call(handle)173		} else {174			None175		}176	}177}