git.delta.rocks / unique-network / refs/commits / 549eb4c11dfd

difftreelog

source

pallets/nft-charge-transaction/src/lib.rs5.8 KiBsourcehistory
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56#![cfg_attr(not(feature = "std"), no_std)]78#[cfg(feature = "std")]9pub use std::*;1011use scale_info::TypeInfo;12#[cfg(feature = "std")]13pub use serde::*;1415use codec::{Decode, Encode};16use frame_support::traits::Get;17use frame_support::{18	decl_module, decl_storage,19	weights::{DispatchInfo, PostDispatchInfo, DispatchClass},20};21use sp_runtime::{22	traits::{23		DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion,24		SignedExtension, Zero,25	},26	transaction_validity::{27		TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,28	},29	FixedPointOperand, DispatchResult,30};31use pallet_transaction_payment::OnChargeTransaction;32use sp_std::prelude::*;3334pub trait Config: frame_system::Config + pallet_nft_transaction_payment::Config + TypeInfo {}3536decl_storage! {37	trait Store for Module<T: Config> as NftTransactionPayment38	{}39}4041decl_module! {4243	pub struct Module<T: Config> for enum Call44	where45		origin: T::Origin,46	{}47}4849type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;5051/// Require the transactor pay for themselves and maybe include a tip to gain additional priority52/// in the queue.53#[derive(Encode, Decode, Clone, Eq, PartialEq, scale_info::TypeInfo)]54pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);5556impl<T: Config + Send + Sync> sp_std::fmt::Debug for ChargeTransactionPayment<T> {57	#[cfg(feature = "std")]58	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {59		write!(f, "ChargeTransactionPayment<{:?}>", self.0)60	}61	#[cfg(not(feature = "std"))]62	fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {63		Ok(())64	}65}6667impl<T: Config> ChargeTransactionPayment<T>68where69	T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,70	BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,71{72	fn traditional_fee(73		len: usize,74		info: &DispatchInfoOf<T::Call>,75		tip: BalanceOf<T>,76	) -> BalanceOf<T>77	where78		T::Call: Dispatchable<Info = DispatchInfo>,79	{80		<pallet_transaction_payment::Pallet<T>>::compute_fee(len as u32, info, tip)81	}8283	fn get_priority(84		len: usize,85		info: &DispatchInfoOf<T::Call>,86		final_fee: BalanceOf<T>,87	) -> TransactionPriority {88		let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);89		let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);90		let len_saturation = max_block_length as u64 / (len as u64).max(1);91		let coefficient: BalanceOf<T> = weight_saturation92			.min(len_saturation)93			.saturated_into::<BalanceOf<T>>();94		final_fee95			.saturating_mul(coefficient)96			.saturated_into::<TransactionPriority>()97	}9899	#[allow(clippy::type_complexity)]100    fn withdraw_fee(101        &self,102        who: &T::AccountId,103        call: &T::Call,104        info: &DispatchInfoOf<T::Call>,105        len: usize,106	) -> Result<107		(108			BalanceOf<T>,109			<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,110		),111		TransactionValidityError,112	>{113		let tip = self.0;114115		let fee = Self::traditional_fee(len, info, tip);116117		// Only mess with balances if fee is not zero.118		if fee.is_zero() {119			return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)120			.map(|i| (fee, i));121		}122123		// Determine who is paying transaction fee based on ecnomic model124		// Parse call to extract collection ID and access collection sponsor125		let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);126127		let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());128129		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)130			.map(|i| (fee, i))131	}132}133134impl<T: Config + Send + Sync> SignedExtension for ChargeTransactionPayment<T>135where136	BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,137	T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,138{139	const IDENTIFIER: &'static str = "ChargeTransactionPayment";140	type AccountId = T::AccountId;141	type Call = T::Call;142	type AdditionalSigned = ();143	type Pre = (144        // tip145        BalanceOf<T>,146        // who pays fee147        Self::AccountId,148		// imbalance resulting from withdrawing the fee149		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,150    );151	fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {152		Ok(())153	}154155	fn validate(156		&self,157		who: &Self::AccountId,158		call: &Self::Call,159		info: &DispatchInfoOf<Self::Call>,160		len: usize,161	) -> TransactionValidity {162		let (fee, _) = self.withdraw_fee(who, call, info, len)?;163		Ok(ValidTransaction {164			priority: Self::get_priority(len, info, fee),165			..Default::default()166		})167	}168169	fn pre_dispatch(170		self,171		who: &Self::AccountId,172		call: &Self::Call,173		info: &DispatchInfoOf<Self::Call>,174		len: usize,175	) -> Result<Self::Pre, TransactionValidityError> {176		let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;177		Ok((self.0, who.clone(), imbalance))178	}179180	fn post_dispatch(181		pre: Self::Pre,182		info: &DispatchInfoOf<Self::Call>,183		post_info: &PostDispatchInfoOf<Self::Call>,184		len: usize,185		_result: &DispatchResult,186	) -> Result<(), TransactionValidityError> {187		let (tip, who, imbalance) = pre;188		let actual_fee = pallet_transaction_payment::Pallet::<T>::compute_actual_fee(189			len as u32, info, post_info, tip,190		);191		<T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(192			&who, info, post_info, actual_fee, tip, imbalance,193		)?;194		Ok(())195	}196}