git.delta.rocks / unique-network / refs/commits / 833ab943fbb5

difftreelog

source

pallets/balances-adapter/src/lib.rs5.9 KiBsourcehistory
1#![cfg_attr(not(feature = "std"), no_std)]23extern crate alloc;4use core::ops::Deref;56use frame_support::sp_runtime::DispatchResult;7use pallet_evm_coder_substrate::{WithRecorder, SubstrateRecorder};8pub use pallet::*;910pub mod common;11pub mod erc;1213pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;1415/// Handle for native fungible collection16pub struct NativeFungibleHandle<T: Config>(SubstrateRecorder<T>);17impl<T: Config> NativeFungibleHandle<T> {18	/// Creates a handle19	pub fn new() -> NativeFungibleHandle<T> {20		Self(SubstrateRecorder::new(u64::MAX))21	}2223	/// Creates a handle24	pub fn new_with_gas_limit(gas_limit: u64) -> NativeFungibleHandle<T> {25		Self(SubstrateRecorder::new(gas_limit))26	}2728	/// Check if the collection is internal29	pub fn check_is_internal(&self) -> DispatchResult {30		Ok(())31	}32}3334impl<T: Config> WithRecorder<T> for NativeFungibleHandle<T> {35	fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {36		&self.037	}38	fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {39		self.040	}41}4243impl<T: Config> Deref for NativeFungibleHandle<T> {44	type Target = SubstrateRecorder<T>;4546	fn deref(&self) -> &Self::Target {47		&self.048	}49}50#[frame_support::pallet]51pub mod pallet {52	use super::*;53	use alloc::string::String;54	use frame_support::{55		dispatch::PostDispatchInfo,56		ensure,57		pallet_prelude::{DispatchResultWithPostInfo, Pays},58		traits::{59			Get,60			fungible::{Inspect, Mutate},61			tokens::Preservation,62		},63	};64	use pallet_balances::WeightInfo;65	use pallet_common::{erc::CrossAccountId, Error as CommonError, Pallet as PalletCommon};66	use pallet_structure::Pallet as PalletStructure;67	use sp_core::U256;68	use sp_runtime::DispatchError;69	use up_data_structs::{budget::Budget, mapping::TokenAddressMapping};7071	#[pallet::config]72	pub trait Config:73		frame_system::Config74		+ pallet_evm_coder_substrate::Config75		+ pallet_common::Config76		+ pallet_structure::Config77	{78		/// Inspect from `pallet_balances`79		type Inspect: frame_support::traits::tokens::fungible::Inspect<80			Self::AccountId,81			Balance = Self::CurrencyBalance,82		>;8384		/// Mutate from `pallet_balances`85		type Mutate: frame_support::traits::tokens::fungible::Mutate<86			Self::AccountId,87			Balance = Self::CurrencyBalance,88		>;8990		/// Balance type of chain91		type CurrencyBalance: Into<U256> + TryFrom<U256> + TryFrom<u128> + Into<u128>;9293		/// Decimals of balance94		type Decimals: Get<u8>;95		/// Collection name96		type Name: Get<String>;97		/// Collection symbol98		type Symbol: Get<String>;99100		/// Weight information101		type WeightInfo: WeightInfo;102	}103	#[pallet::pallet]104	pub struct Pallet<T>(_);105106	impl<T: Config> Pallet<T> {107		pub fn balance_of(account: &T::CrossAccountId) -> u128 {108			T::Inspect::balance(account.as_sub()).into()109		}110111		pub fn total_balance(account: &T::CrossAccountId) -> u128 {112			T::Inspect::total_balance(account.as_sub()).into()113		}114115		pub fn total_issuance() -> u128 {116			T::Inspect::total_issuance().into()117		}118119		/// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.120		/// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.121		///122		/// - `spender`: CrossAccountId who has the allowance rights.123		/// - `from`: The owner of the tokens who sets the allowance.124		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.125		fn check_allowed(126			spender: &T::CrossAccountId,127			from: &T::CrossAccountId,128			nesting_budget: &dyn Budget,129		) -> Result<u128, DispatchError> {130			if let Some((collection_id, token_id)) =131				T::CrossTokenAddressMapping::address_to_token(from)132			{133				ensure!(134					<PalletStructure<T>>::check_indirectly_owned(135						spender.clone(),136						collection_id,137						token_id,138						None,139						nesting_budget140					)?,141					<CommonError<T>>::ApprovedValueTooLow,142				);143			} else if !spender.conv_eq(from) {144				return Ok(0);145			}146147			Ok(Self::balance_of(from))148		}149150		/// Transfers the specified amount of tokens. Will check that151		/// the transfer is allowed for the token.152		///153		/// - `collection`: Collection that contains the token.154		/// - `from`: Owner of tokens to transfer.155		/// - `to`: Recepient of transfered tokens.156		/// - `amount`: Amount of tokens to transfer.157		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.158		pub fn transfer(159			_collection: &NativeFungibleHandle<T>,160			from: &T::CrossAccountId,161			to: &T::CrossAccountId,162			amount: u128,163			_nesting_budget: &dyn Budget,164		) -> DispatchResultWithPostInfo {165			<PalletCommon<T>>::ensure_correct_receiver(to)?;166167			if from != to && amount != 0 {168				let amount = amount169					.try_into()170					.map_err(|_| sp_runtime::ArithmeticError::Overflow)?;171				T::Mutate::transfer(from.as_sub(), to.as_sub(), amount, Preservation::Expendable)?;172			};173174			Ok(PostDispatchInfo {175				actual_weight: Some(<SelfWeightOf<T>>::transfer_allow_death()),176				pays_fee: Pays::Yes,177			})178		}179180		/// Transfer NFT token from one account to another.181		///182		/// Same as the [`Self::transfer`] but spender doesn't needs to be the owner of the token.183		/// The owner should set allowance for the spender to transfer token.184		///185		/// - `collection`: Collection that contains the token.186		/// - `spender`: Account that spend the money.187		/// - `from`: Owner of tokens to transfer.188		/// - `to`: Recepient of transfered tokens.189		/// - `amount`: Amount of tokens to transfer.190		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.191		pub fn transfer_from(192			collection: &NativeFungibleHandle<T>,193			spender: &T::CrossAccountId,194			from: &T::CrossAccountId,195			to: &T::CrossAccountId,196			amount: u128,197			nesting_budget: &dyn Budget,198		) -> DispatchResultWithPostInfo {199			let allowance = Self::check_allowed(spender, from, nesting_budget)?;200			if allowance < amount {201				return Err(<CommonError<T>>::ApprovedValueTooLow.into());202			}203			Self::transfer(collection, from, to, amount, nesting_budget)204		}205	}206}