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

difftreelog

source

pallets/nft-charge-transaction/src/lib.rs6.5 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::*;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;6667/// Require the transactor pay for themselves and maybe include a tip to gain additional priority68/// in the queue.69#[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        // Only mess with balances if fee is not zero.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        // Determine who is paying transaction fee based on ecnomic model139		// Parse call to extract collection ID and access collection sponsor	140		let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);141142        let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());143144		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)145			.map(|i| (fee, i))146    }147}148149impl<T: Config + Send + Sync> SignedExtension150    for ChargeTransactionPayment<T>151where152    BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,153	T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,154    T::AccountId: AsRef<[u8]>,155    T::AccountId: UncheckedFrom<T::Hash>,156{157    const IDENTIFIER: &'static str = "ChargeTransactionPayment";158    type AccountId = T::AccountId;159    type Call = T::Call;160    type AdditionalSigned = ();161    type Pre = (162        // tip163        BalanceOf<T>,164        // who pays fee165        Self::AccountId,166		// imbalance resulting from withdrawing the fee167		<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,168    );169    fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {170        Ok(())171    }172173    fn validate(174        &self,175        who: &Self::AccountId,176        call: &Self::Call,177        info: &DispatchInfoOf<Self::Call>,178        len: usize,179    ) -> TransactionValidity {180		let (fee, _) = self.withdraw_fee(who, call, info, len)?;181		Ok(ValidTransaction {182			priority: Self::get_priority(len, info, fee),183			..Default::default()184		})185    }186187    fn pre_dispatch(188        self,189        who: &Self::AccountId,190        call: &Self::Call,191        info: &DispatchInfoOf<Self::Call>,192        len: usize,193    ) -> Result<Self::Pre, TransactionValidityError> {194        let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;195        Ok((self.0, who.clone(), imbalance))196    }197198    fn post_dispatch(199        pre: Self::Pre,200        info: &DispatchInfoOf<Self::Call>,201        post_info: &PostDispatchInfoOf<Self::Call>,202        len: usize,203        _result: &DispatchResult,204    ) -> Result<(), TransactionValidityError> {205		let (tip, who, imbalance) = pre;206		let actual_fee = pallet_transaction_payment::Module::<T>::compute_actual_fee(207			len as u32,208			info,209			post_info,210			tip,211		);212		<T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;213		Ok(())214    }215}