git.delta.rocks / unique-network / refs/commits / c12e121fed0b

difftreelog

source

pallets/nft-charge-transaction/src/lib.rs6.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::*;1314#[cfg(feature = "runtime-benchmarks")]15mod benchmarking;1617#[cfg(test)]18mod tests;1920use codec::{Decode, Encode};21use frame_support::traits::{ Get};22use frame_support::{23	decl_module, decl_storage,24	traits::{25		IsSubType, 26	},27	weights::{28		DispatchInfo, PostDispatchInfo, DispatchClass29	}30};31use sp_runtime::{32	traits::{ 33		DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion, SignedExtension, Zero,34	},35	transaction_validity::{ 36		TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,37	},38	FixedPointOperand, DispatchResult39};40use pallet_contracts::chain_extension::UncheckedFrom;41use pallet_transaction_payment::OnChargeTransaction;42use sp_std::prelude::*;434445pub trait Config: frame_system::Config + 46    pallet_nft_transaction_payment::Config47{4849}5051decl_storage! {52    trait Store for Module<T: Config> as NftTransactionPayment53    {}54}5556decl_module! {5758	pub struct Module<T: Config> for enum Call 59    where 60		origin: T::Origin,61    {}62}6364type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;6566/// Require the transactor pay for themselves and maybe include a tip to gain additional priority67/// in the queue.68#[derive(Encode, Decode, Clone, Eq, PartialEq)]69pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);7071impl<T: Config + Send + Sync> sp_std::fmt::Debug 72    for ChargeTransactionPayment<T>73{74	#[cfg(feature = "std")]75	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {76		write!(f, "ChargeTransactionPayment<{:?}>", self.0)77	}78	#[cfg(not(feature = "std"))]79	fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {80		Ok(())81	}82}8384impl<T: Config> ChargeTransactionPayment<T>85where86	T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,87    BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,88    T::AccountId: AsRef<[u8]>,89    T::AccountId: UncheckedFrom<T::Hash>,90{91    fn traditional_fee(92        len: usize,93        info: &DispatchInfoOf<T::Call>,94        tip: BalanceOf<T>,95    ) -> BalanceOf<T>96    where97        T::Call: Dispatchable<Info = DispatchInfo>,98    {99        <pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)100    }101102	fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {103        let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);104        let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);105        let len_saturation = max_block_length as u64 / (len as u64).max(1);106        let coefficient: BalanceOf<T> = weight_saturation107            .min(len_saturation)108            .saturated_into::<BalanceOf<T>>();109        final_fee110            .saturating_mul(coefficient)111            .saturated_into::<TransactionPriority>()112    }113114    fn withdraw_fee(115        &self,116        who: &T::AccountId,117        call: &T::Call,118        info: &DispatchInfoOf<T::Call>,119        len: usize,120	) -> Result<121		(122			BalanceOf<T>,123			<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,124		),125		TransactionValidityError,126	> {127        let tip = self.0;128129        let fee = Self::traditional_fee(len, info, tip);130131        // Only mess with balances if fee is not zero.132        if fee.is_zero() {133            return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)134			.map(|i| (fee, i));135        }136137        // check errors138        let _error = <pallet_nft_transaction_payment::Module<T>>::check_error(who, call);139        match _error {140            Err(_error) => return Err(_error),141            Ok(_error) => {}142        };143144        // Determine who is paying transaction fee based on ecnomic model145		// Parse call to extract collection ID and access collection sponsor	146		let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);147148        let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());149150		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)151			.map(|i| (fee, i))152    }153}154155impl<T: Config + Send + Sync> SignedExtension156    for ChargeTransactionPayment<T>157where158    BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,159	T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,160    T::AccountId: AsRef<[u8]>,161    T::AccountId: UncheckedFrom<T::Hash>,162{163    const IDENTIFIER: &'static str = "ChargeTransactionPayment";164    type AccountId = T::AccountId;165    type Call = T::Call;166    type AdditionalSigned = ();167    type Pre = (168        // tip169        BalanceOf<T>,170        // who pays fee171        Self::AccountId,172		// imbalance resulting from withdrawing the fee173		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,174    );175    fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {176        Ok(())177    }178179    fn validate(180        &self,181        who: &Self::AccountId,182        call: &Self::Call,183        info: &DispatchInfoOf<Self::Call>,184        len: usize,185    ) -> TransactionValidity {186		let (fee, _) = self.withdraw_fee(who, call, info, len)?;187		Ok(ValidTransaction {188			priority: Self::get_priority(len, info, fee),189			..Default::default()190		})191    }192193    fn pre_dispatch(194        self,195        who: &Self::AccountId,196        call: &Self::Call,197        info: &DispatchInfoOf<Self::Call>,198        len: usize,199    ) -> Result<Self::Pre, TransactionValidityError> {200        let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;201        Ok((self.0, who.clone(), imbalance))202    }203204    fn post_dispatch(205        pre: Self::Pre,206        info: &DispatchInfoOf<Self::Call>,207        post_info: &PostDispatchInfoOf<Self::Call>,208        len: usize,209        _result: &DispatchResult,210    ) -> Result<(), TransactionValidityError> {211		let (tip, who, imbalance) = pre;212		let actual_fee = pallet_transaction_payment::Module::<T>::compute_actual_fee(213			len as u32,214			info,215			post_info,216			tip,217		);218		<T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;219		Ok(())220    }221}