git.delta.rocks / unique-network / refs/commits / 2a441390261c

difftreelog

source

pallets/nft-charge-transaction/src/lib.rs6.7 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        // check errors139        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        // Determine who is paying transaction fee based on ecnomic model146		// Parse call to extract collection ID and access collection sponsor	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        // tip170        BalanceOf<T>,171        // who pays fee172        Self::AccountId,173		// imbalance resulting from withdrawing the fee174		<<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}