git.delta.rocks / unique-network / refs/commits / 71be677911ce

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;7pub use pallet::*;8use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};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 alloc::string::String;5960	use frame_support::{61		dispatch::PostDispatchInfo,62		ensure,63		pallet_prelude::*,64		traits::{65			fungible::{Inspect, Mutate},66			tokens::Preservation,67			Get,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	use super::*;7879	#[pallet::config]80	pub trait Config:81		frame_system::Config82		+ pallet_evm_coder_substrate::Config83		+ pallet_common::Config84		+ pallet_structure::Config85	{86		/// Inspect from `pallet_balances`87		type Inspect: frame_support::traits::tokens::fungible::Inspect<88			Self::AccountId,89			Balance = Self::CurrencyBalance,90		>;9192		/// Mutate from `pallet_balances`93		type Mutate: frame_support::traits::tokens::fungible::Mutate<94			Self::AccountId,95			Balance = Self::CurrencyBalance,96		>;9798		/// Balance type of chain99		type CurrencyBalance: Into<U256> + TryFrom<U256> + TryFrom<u128> + Into<u128>;100101		/// Decimals of balance102		type Decimals: Get<u8>;103		/// Collection name104		type Name: Get<String>;105		/// Collection symbol106		type Symbol: Get<String>;107108		/// Weight information109		type WeightInfo: WeightInfo;110	}111	#[pallet::pallet]112	pub struct Pallet<T>(_);113114	impl<T: Config> Pallet<T> {115		pub fn balance_of(account: &T::CrossAccountId) -> u128 {116			T::Inspect::balance(account.as_sub()).into()117		}118119		pub fn total_balance(account: &T::CrossAccountId) -> u128 {120			T::Inspect::total_balance(account.as_sub()).into()121		}122123		pub fn total_issuance() -> u128 {124			T::Inspect::total_issuance().into()125		}126127		/// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.128		/// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.129		///130		/// - `spender`: CrossAccountId who has the allowance rights.131		/// - `from`: The owner of the tokens who sets the allowance.132		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.133		fn check_allowed(134			spender: &T::CrossAccountId,135			from: &T::CrossAccountId,136			nesting_budget: &dyn Budget,137		) -> Result<u128, DispatchError> {138			if let Some((collection_id, token_id)) =139				T::CrossTokenAddressMapping::address_to_token(from)140			{141				ensure!(142					<PalletStructure<T>>::check_indirectly_owned(143						spender.clone(),144						collection_id,145						token_id,146						None,147						nesting_budget148					)?,149					<CommonError<T>>::ApprovedValueTooLow,150				);151			} else if !spender.conv_eq(from) {152				return Ok(0);153			}154155			Ok(Self::balance_of(from))156		}157158		/// Transfers the specified amount of tokens. Will check that159		/// the transfer is allowed for the token.160		///161		/// - `collection`: Collection that contains the token.162		/// - `from`: Owner of tokens to transfer.163		/// - `to`: Recepient of transfered tokens.164		/// - `amount`: Amount of tokens to transfer.165		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.166		pub fn transfer(167			_collection: &NativeFungibleHandle<T>,168			from: &T::CrossAccountId,169			to: &T::CrossAccountId,170			amount: u128,171			_nesting_budget: &dyn Budget,172		) -> DispatchResultWithPostInfo {173			<PalletCommon<T>>::ensure_correct_receiver(to)?;174175			if from != to && amount != 0 {176				let amount = amount177					.try_into()178					.map_err(|_| sp_runtime::ArithmeticError::Overflow)?;179				T::Mutate::transfer(from.as_sub(), to.as_sub(), amount, Preservation::Expendable)?;180			};181182			Ok(PostDispatchInfo {183				actual_weight: Some(<SelfWeightOf<T>>::transfer_allow_death()),184				pays_fee: Pays::Yes,185			})186		}187188		/// Transfer NFT token from one account to another.189		///190		/// Same as the [`Self::transfer`] but spender doesn't needs to be the owner of the token.191		/// The owner should set allowance for the spender to transfer token.192		///193		/// - `collection`: Collection that contains the token.194		/// - `spender`: Account that spend the money.195		/// - `from`: Owner of tokens to transfer.196		/// - `to`: Recepient of transfered tokens.197		/// - `amount`: Amount of tokens to transfer.198		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.199		pub fn transfer_from(200			collection: &NativeFungibleHandle<T>,201			spender: &T::CrossAccountId,202			from: &T::CrossAccountId,203			to: &T::CrossAccountId,204			amount: u128,205			nesting_budget: &dyn Budget,206		) -> DispatchResultWithPostInfo {207			let allowance = Self::check_allowed(spender, from, nesting_budget)?;208			if allowance < amount {209				return Err(<CommonError<T>>::ApprovedValueTooLow.into());210			}211			Self::transfer(collection, from, to, amount, nesting_budget)212		}213	}214}