123456#![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;1617use codec::{Decode, Encode};18use frame_support::traits::Get;19use frame_support::{20 decl_module, decl_storage,21 weights::{22 DispatchInfo, PostDispatchInfo, DispatchClass23 }24};25use sp_runtime::{26 traits::{ 27 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion, SignedExtension, Zero,28 },29 transaction_validity::{ 30 TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,31 },32 FixedPointOperand, DispatchResult33};34use pallet_transaction_payment::OnChargeTransaction;35use sp_std::prelude::*;363738pub trait Config: frame_system::Config + 39 pallet_nft_transaction_payment::Config40{4142}4344decl_storage! {45 trait Store for Module<T: Config> as NftTransactionPayment46 {}47}4849decl_module! {5051 pub struct Module<T: Config> for enum Call 52 where 53 origin: T::Origin,54 {}55}5657type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;58596061#[derive(Encode, Decode, Clone, Eq, PartialEq)]62pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);6364impl<T: Config + Send + Sync> sp_std::fmt::Debug 65 for ChargeTransactionPayment<T>66{67 #[cfg(feature = "std")]68 fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {69 write!(f, "ChargeTransactionPayment<{:?}>", self.0)70 }71 #[cfg(not(feature = "std"))]72 fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {73 Ok(())74 }75}7677impl<T: Config> ChargeTransactionPayment<T>78where79 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo>,80 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,81{82 fn traditional_fee(83 len: usize,84 info: &DispatchInfoOf<T::Call>,85 tip: BalanceOf<T>,86 ) -> BalanceOf<T>87 where88 T::Call: Dispatchable<Info = DispatchInfo>,89 {90 <pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)91 }9293 fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {94 let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);95 let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);96 let len_saturation = max_block_length as u64 / (len as u64).max(1);97 let coefficient: BalanceOf<T> = weight_saturation98 .min(len_saturation)99 .saturated_into::<BalanceOf<T>>();100 final_fee101 .saturating_mul(coefficient)102 .saturated_into::<TransactionPriority>()103 }104105 fn withdraw_fee(106 &self,107 who: &T::AccountId,108 call: &T::Call,109 info: &DispatchInfoOf<T::Call>,110 len: usize,111 ) -> Result<112 (113 BalanceOf<T>,114 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,115 ),116 TransactionValidityError,117 > {118 let tip = self.0;119120 let fee = Self::traditional_fee(len, info, tip);121122 123 if fee.is_zero() {124 return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)125 .map(|i| (fee, i));126 }127128 129 130 let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);131132 let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());133134 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)135 .map(|i| (fee, i))136 }137}138139impl<T: Config + Send + Sync> SignedExtension140 for ChargeTransactionPayment<T>141where142 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,143 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo>,144{145 const IDENTIFIER: &'static str = "ChargeTransactionPayment";146 type AccountId = T::AccountId;147 type Call = T::Call;148 type AdditionalSigned = ();149 type Pre = (150 151 BalanceOf<T>,152 153 Self::AccountId,154 155 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,156 );157 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {158 Ok(())159 }160161 fn validate(162 &self,163 who: &Self::AccountId,164 call: &Self::Call,165 info: &DispatchInfoOf<Self::Call>,166 len: usize,167 ) -> TransactionValidity {168 let (fee, _) = self.withdraw_fee(who, call, info, len)?;169 Ok(ValidTransaction {170 priority: Self::get_priority(len, info, fee),171 ..Default::default()172 })173 }174175 fn pre_dispatch(176 self,177 who: &Self::AccountId,178 call: &Self::Call,179 info: &DispatchInfoOf<Self::Call>,180 len: usize,181 ) -> Result<Self::Pre, TransactionValidityError> {182 let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;183 Ok((self.0, who.clone(), imbalance))184 }185186 fn post_dispatch(187 pre: Self::Pre,188 info: &DispatchInfoOf<Self::Call>,189 post_info: &PostDispatchInfoOf<Self::Call>,190 len: usize,191 _result: &DispatchResult,192 ) -> Result<(), TransactionValidityError> {193 let (tip, who, imbalance) = pre;194 let actual_fee = pallet_transaction_payment::Pallet::<T>::compute_actual_fee(195 len as u32,196 info,197 post_info,198 tip,199 );200 <T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;201 Ok(())202 }203}