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;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::*;434445 pub trait Config: frame_system::Config + 46 pallet_nft_transaction_payment::Config47 {4849 }5051 decl_storage! {52 trait Store for Module<T: Config> as NftTransactionPayment{5354 }55}5657decl_module! {5859 pub struct Module<T: Config> for enum Call 60 where 61 origin: T::Origin,62 {}63}6465type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;66676869#[derive(Encode, Decode, Clone, Eq, PartialEq)]70pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);7172impl<T: Config + Send + Sync> sp_std::fmt::Debug 73 for ChargeTransactionPayment<T>74{75 #[cfg(feature = "std")]76 fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {77 write!(f, "ChargeTransactionPayment<{:?}>", self.0)78 }79 #[cfg(not(feature = "std"))]80 fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {81 Ok(())82 }83}8485impl<T: Config> ChargeTransactionPayment<T>86where87 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,88 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,89 T::AccountId: AsRef<[u8]>,90 T::AccountId: UncheckedFrom<T::Hash>,91{92 fn traditional_fee(93 len: usize,94 info: &DispatchInfoOf<T::Call>,95 tip: BalanceOf<T>,96 ) -> BalanceOf<T>97 where98 T::Call: Dispatchable<Info = DispatchInfo>,99 {100 <pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)101 }102103 fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {104 let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);105 let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);106 let len_saturation = max_block_length as u64 / (len as u64).max(1);107 let coefficient: BalanceOf<T> = weight_saturation108 .min(len_saturation)109 .saturated_into::<BalanceOf<T>>();110 final_fee111 .saturating_mul(coefficient)112 .saturated_into::<TransactionPriority>()113 }114115 fn withdraw_fee(116 &self,117 who: &T::AccountId,118 call: &T::Call,119 info: &DispatchInfoOf<T::Call>,120 len: usize,121 ) -> Result<122 (123 BalanceOf<T>,124 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,125 ),126 TransactionValidityError,127 > {128 let tip = self.0;129130 let fee = Self::traditional_fee(len, info, tip);131132 133 if fee.is_zero() {134 return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)135 .map(|i| (fee, i));136 }137138 139 let error = <pallet_nft_transaction_payment::Module<T>>::check_error(who, call);140 match error {141 Err(error) => return Err(error),142 Ok(error) => {}143 };144145 146 147 let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);148149 let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());150151 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)152 .map(|i| (fee, i))153 }154}155156impl<T: Config + Send + Sync> SignedExtension157 for ChargeTransactionPayment<T>158where159 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,160 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,161 T::AccountId: AsRef<[u8]>,162 T::AccountId: UncheckedFrom<T::Hash>,163{164 const IDENTIFIER: &'static str = "ChargeTransactionPayment";165 type AccountId = T::AccountId;166 type Call = T::Call;167 type AdditionalSigned = ();168 type Pre = (169 170 BalanceOf<T>,171 172 Self::AccountId,173 174 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,175 );176 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {177 Ok(())178 }179180 fn validate(181 &self,182 who: &Self::AccountId,183 call: &Self::Call,184 info: &DispatchInfoOf<Self::Call>,185 len: usize,186 ) -> TransactionValidity {187 let (fee, _) = self.withdraw_fee(who, call, info, len)?;188 Ok(ValidTransaction {189 priority: Self::get_priority(len, info, fee),190 ..Default::default()191 })192 }193194 fn pre_dispatch(195 self,196 who: &Self::AccountId,197 call: &Self::Call,198 info: &DispatchInfoOf<Self::Call>,199 len: usize,200 ) -> Result<Self::Pre, TransactionValidityError> {201 let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;202 Ok((self.0, who.clone(), imbalance))203 }204205 fn post_dispatch(206 pre: Self::Pre,207 info: &DispatchInfoOf<Self::Call>,208 post_info: &PostDispatchInfoOf<Self::Call>,209 len: usize,210 _result: &DispatchResult,211 ) -> Result<(), TransactionValidityError> {212 let (tip, who, imbalance) = pre;213 let actual_fee = pallet_transaction_payment::Module::<T>::compute_actual_fee(214 len as u32,215 info,216 post_info,217 tip,218 );219 <T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;220 Ok(())221 }222}