git.delta.rocks / unique-network / refs/commits / 3fb62366cc89

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::*;1011#[cfg(feature = "std")]12pub use serde::*;1314use codec::{Decode, Encode};15use frame_support::traits::Get;16use frame_support::{17	decl_module, decl_storage,18	weights::{DispatchInfo, PostDispatchInfo, DispatchClass},19};20use sp_runtime::{21	traits::{22		DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion,23		SignedExtension, Zero,24	},25	transaction_validity::{26		TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,27	},28	FixedPointOperand, DispatchResult,29};30use pallet_transaction_payment::OnChargeTransaction;31use sp_std::prelude::*;3233pub trait Config: frame_system::Config + pallet_nft_transaction_payment::Config {}3435decl_storage! {36	trait Store for Module<T: Config> as NftTransactionPayment37	{}38}3940decl_module! {4142	pub struct Module<T: Config> for enum Call43	where44		origin: T::Origin,45	{}46}4748type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;4950/// Require the transactor pay for themselves and maybe include a tip to gain additional priority51/// in the queue.52#[derive(Encode, Decode, Clone, Eq, PartialEq)]53pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);5455impl<T: Config + Send + Sync> sp_std::fmt::Debug for ChargeTransactionPayment<T> {56	#[cfg(feature = "std")]57	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {58		write!(f, "ChargeTransactionPayment<{:?}>", self.0)59	}60	#[cfg(not(feature = "std"))]61	fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {62		Ok(())63	}64}6566impl<T: Config> ChargeTransactionPayment<T>67where68	T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,69	BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,70{71	fn traditional_fee(72		len: usize,73		info: &DispatchInfoOf<T::Call>,74		tip: BalanceOf<T>,75	) -> BalanceOf<T>76	where77		T::Call: Dispatchable<Info = DispatchInfo>,78	{79		<pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)80	}8182	fn get_priority(83		len: usize,84		info: &DispatchInfoOf<T::Call>,85		final_fee: BalanceOf<T>,86	) -> TransactionPriority {87		let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);88		let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);89		let len_saturation = max_block_length as u64 / (len as u64).max(1);90		let coefficient: BalanceOf<T> = weight_saturation91			.min(len_saturation)92			.saturated_into::<BalanceOf<T>>();93		final_fee94			.saturating_mul(coefficient)95			.saturated_into::<TransactionPriority>()96	}9798	#[allow(clippy::type_complexity)]99    fn withdraw_fee(100        &self,101        who: &T::AccountId,102        call: &T::Call,103        info: &DispatchInfoOf<T::Call>,104        len: usize,105	) -> Result<106		(107			BalanceOf<T>,108			<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,109		),110		TransactionValidityError,111	>{112		let tip = self.0;113114		let fee = Self::traditional_fee(len, info, tip);115116		// Only mess with balances if fee is not zero.117		if fee.is_zero() {118			return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)119			.map(|i| (fee, i));120		}121122		// Determine who is paying transaction fee based on ecnomic model123		// Parse call to extract collection ID and access collection sponsor124		let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);125126		let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());127128		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)129			.map(|i| (fee, i))130	}131}132133impl<T: Config + Send + Sync> SignedExtension for ChargeTransactionPayment<T>134where135	BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,136	T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,137{138	const IDENTIFIER: &'static str = "ChargeTransactionPayment";139	type AccountId = T::AccountId;140	type Call = T::Call;141	type AdditionalSigned = ();142	type Pre = (143        // tip144        BalanceOf<T>,145        // who pays fee146        Self::AccountId,147		// imbalance resulting from withdrawing the fee148		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,149    );150	fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {151		Ok(())152	}153154	fn validate(155		&self,156		who: &Self::AccountId,157		call: &Self::Call,158		info: &DispatchInfoOf<Self::Call>,159		len: usize,160	) -> TransactionValidity {161		let (fee, _) = self.withdraw_fee(who, call, info, len)?;162		Ok(ValidTransaction {163			priority: Self::get_priority(len, info, fee),164			..Default::default()165		})166	}167168	fn pre_dispatch(169		self,170		who: &Self::AccountId,171		call: &Self::Call,172		info: &DispatchInfoOf<Self::Call>,173		len: usize,174	) -> Result<Self::Pre, TransactionValidityError> {175		let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;176		Ok((self.0, who.clone(), imbalance))177	}178179	fn post_dispatch(180		pre: Self::Pre,181		info: &DispatchInfoOf<Self::Call>,182		post_info: &PostDispatchInfoOf<Self::Call>,183		len: usize,184		_result: &DispatchResult,185	) -> Result<(), TransactionValidityError> {186		let (tip, who, imbalance) = pre;187		let actual_fee = pallet_transaction_payment::Pallet::<T>::compute_actual_fee(188			len as u32, info, post_info, tip,189		);190		<T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(191			&who, info, post_info, actual_fee, tip, imbalance,192		)?;193		Ok(())194	}195}