git.delta.rocks / unique-network / refs/commits / 509c8280fa0c

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::{29	Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,30};31use up_data_structs::{32	CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,33};3435pub enum CollectionDispatchT<T>36where37	T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,38{39	Fungible(FungibleHandle<T>),40	Nonfungible(NonfungibleHandle<T>),41	Refungible(RefungibleHandle<T>),42}43impl<T> CollectionDispatch<T> for CollectionDispatchT<T>44where45	T: pallet_common::Config46		+ pallet_unique::Config47		+ pallet_fungible::Config48		+ pallet_nonfungible::Config49		+ pallet_refungible::Config,50{51	fn create(52		sender: T::CrossAccountId,53		data: CreateCollectionData<T::AccountId>,54	) -> DispatchResult {55		let _id = match data.mode {56			CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,57			CollectionMode::Fungible(decimal_points) => {58				// check params59				ensure!(60					decimal_points <= MAX_DECIMAL_POINTS,61					pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded62				);63				<PalletFungible<T>>::init_collection(sender, data)?64			}65			CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,66		};67		Ok(())68	}6970	fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {71		match collection.mode {72			CollectionMode::ReFungible => {73				PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?74			}75			CollectionMode::Fungible(_) => {76				PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?77			}78			CollectionMode::NFT => {79				PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?80			}81		}82		Ok(())83	}8485	fn dispatch(handle: CollectionHandle<T>) -> Self {86		match handle.mode {87			CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),88			CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),89			CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),90		}91	}9293	fn into_inner(self) -> CollectionHandle<T> {94		match self {95			Self::Fungible(f) => f.into_inner(),96			Self::Nonfungible(f) => f.into_inner(),97			Self::Refungible(f) => f.into_inner(),98		}99	}100101	fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {102		match self {103			Self::Fungible(h) => h,104			Self::Nonfungible(h) => h,105			Self::Refungible(h) => h,106		}107	}108}109110impl<T> pallet_evm::OnMethodCall<T> for CollectionDispatchT<T>111where112	T: pallet_common::Config113		+ pallet_unique::Config114		+ pallet_fungible::Config115		+ pallet_nonfungible::Config116		+ pallet_refungible::Config,117	T::AccountId: From<[u8; 32]>,118{119	fn is_reserved(target: &H160) -> bool {120		map_eth_to_id(target).is_some()121	}122	fn is_used(target: &H160) -> bool {123		map_eth_to_id(target)124			.map(<CollectionById<T>>::contains_key)125			.unwrap_or(false)126	}127	fn get_code(target: &H160) -> Option<Vec<u8>> {128		if let Some(collection_id) = map_eth_to_id(target) {129			let collection = <CollectionById<T>>::get(collection_id)?;130			Some(131				match collection.mode {132					CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,133					CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,134					CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,135				}136				.to_owned(),137			)138		} else if let Some((collection_id, _token_id)) =139			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(target)140		{141			let collection = <CollectionById<T>>::get(collection_id)?;142			if collection.mode != CollectionMode::ReFungible {143				return None;144			}145			// TODO: check token existence146			Some(<RefungibleTokenHandle<T>>::CODE.to_owned())147		} else {148			None149		}150	}151	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {152		if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {153			let collection =154				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;155			let dispatched = Self::dispatch(collection);156157			match dispatched {158				Self::Fungible(h) => h.call(handle),159				Self::Nonfungible(h) => h.call(handle),160				Self::Refungible(h) => h.call(handle),161			}162		} else if let Some((collection_id, token_id)) =163			<T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(164				&handle.code_address(),165			) {166			let collection =167				<CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;168			if collection.mode != CollectionMode::ReFungible {169				return None;170			}171172			let h = RefungibleHandle::cast(collection);173			// TODO: check token existence174			RefungibleTokenHandle(h, token_id).call(handle)175		} else {176			None177		}178	}179}