git.delta.rocks / unique-network / refs/commits / 5ef5e6b4aa6d

difftreelog

source

pallets/balances-adapter/src/lib.rs6.0 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> Default for NativeFungibleHandle<T> {35	fn default() -> Self {36		Self::new()37	}38}3940impl<T: Config> WithRecorder<T> for NativeFungibleHandle<T> {41	fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {42		&self.043	}44	fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {45		self.046	}47}4849impl<T: Config> Deref for NativeFungibleHandle<T> {50	type Target = SubstrateRecorder<T>;5152	fn deref(&self) -> &Self::Target {53		&self.054	}55}56#[frame_support::pallet]57pub mod pallet {58	use super::*;59	use alloc::string::String;60	use frame_support::{61		dispatch::PostDispatchInfo,62		ensure,63		pallet_prelude::{DispatchResultWithPostInfo, Pays},64		traits::{65			Get,66			fungible::{Inspect, Mutate},67			tokens::Preservation,68		},69	};70	use pallet_balances::WeightInfo;71	use pallet_common::{erc::CrossAccountId, Error as CommonError, Pallet as PalletCommon};72	use pallet_structure::Pallet as PalletStructure;73	use sp_core::U256;74	use sp_runtime::DispatchError;75	use up_data_structs::{budget::Budget, mapping::TokenAddressMapping};7677	#[pallet::config]78	pub trait Config:79		frame_system::Config80		+ pallet_evm_coder_substrate::Config81		+ pallet_common::Config82		+ pallet_structure::Config83	{84		/// Inspect from `pallet_balances`85		type Inspect: frame_support::traits::tokens::fungible::Inspect<86			Self::AccountId,87			Balance = Self::CurrencyBalance,88		>;8990		/// Mutate from `pallet_balances`91		type Mutate: frame_support::traits::tokens::fungible::Mutate<92			Self::AccountId,93			Balance = Self::CurrencyBalance,94		>;9596		/// Balance type of chain97		type CurrencyBalance: Into<U256> + TryFrom<U256> + TryFrom<u128> + Into<u128>;9899		/// Decimals of balance100		type Decimals: Get<u8>;101		/// Collection name102		type Name: Get<String>;103		/// Collection symbol104		type Symbol: Get<String>;105106		/// Weight information107		type WeightInfo: WeightInfo;108	}109	#[pallet::pallet]110	pub struct Pallet<T>(_);111112	impl<T: Config> Pallet<T> {113		pub fn balance_of(account: &T::CrossAccountId) -> u128 {114			T::Inspect::balance(account.as_sub()).into()115		}116117		pub fn total_balance(account: &T::CrossAccountId) -> u128 {118			T::Inspect::total_balance(account.as_sub()).into()119		}120121		pub fn total_issuance() -> u128 {122			T::Inspect::total_issuance().into()123		}124125		/// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.126		/// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.127		///128		/// - `spender`: CrossAccountId who has the allowance rights.129		/// - `from`: The owner of the tokens who sets the allowance.130		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.131		fn check_allowed(132			spender: &T::CrossAccountId,133			from: &T::CrossAccountId,134			nesting_budget: &dyn Budget,135		) -> Result<u128, DispatchError> {136			if let Some((collection_id, token_id)) =137				T::CrossTokenAddressMapping::address_to_token(from)138			{139				ensure!(140					<PalletStructure<T>>::check_indirectly_owned(141						spender.clone(),142						collection_id,143						token_id,144						None,145						nesting_budget146					)?,147					<CommonError<T>>::ApprovedValueTooLow,148				);149			} else if !spender.conv_eq(from) {150				return Ok(0);151			}152153			Ok(Self::balance_of(from))154		}155156		/// Transfers the specified amount of tokens. Will check that157		/// the transfer is allowed for the token.158		///159		/// - `collection`: Collection that contains the token.160		/// - `from`: Owner of tokens to transfer.161		/// - `to`: Recepient of transfered tokens.162		/// - `amount`: Amount of tokens to transfer.163		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.164		pub fn transfer(165			_collection: &NativeFungibleHandle<T>,166			from: &T::CrossAccountId,167			to: &T::CrossAccountId,168			amount: u128,169			_nesting_budget: &dyn Budget,170		) -> DispatchResultWithPostInfo {171			<PalletCommon<T>>::ensure_correct_receiver(to)?;172173			if from != to && amount != 0 {174				let amount = amount175					.try_into()176					.map_err(|_| sp_runtime::ArithmeticError::Overflow)?;177				T::Mutate::transfer(from.as_sub(), to.as_sub(), amount, Preservation::Expendable)?;178			};179180			Ok(PostDispatchInfo {181				actual_weight: Some(<SelfWeightOf<T>>::transfer_allow_death()),182				pays_fee: Pays::Yes,183			})184		}185186		/// Transfer NFT token from one account to another.187		///188		/// Same as the [`Self::transfer`] but spender doesn't needs to be the owner of the token.189		/// The owner should set allowance for the spender to transfer token.190		///191		/// - `collection`: Collection that contains the token.192		/// - `spender`: Account that spend the money.193		/// - `from`: Owner of tokens to transfer.194		/// - `to`: Recepient of transfered tokens.195		/// - `amount`: Amount of tokens to transfer.196		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.197		pub fn transfer_from(198			collection: &NativeFungibleHandle<T>,199			spender: &T::CrossAccountId,200			from: &T::CrossAccountId,201			to: &T::CrossAccountId,202			amount: u128,203			nesting_budget: &dyn Budget,204		) -> DispatchResultWithPostInfo {205			let allowance = Self::check_allowed(spender, from, nesting_budget)?;206			if allowance < amount {207				return Err(<CommonError<T>>::ApprovedValueTooLow.into());208			}209			Self::transfer(collection, from, to, amount, nesting_budget)210		}211	}212}