29
29
//! - A means of updating the fee for the next block, via defining a multiplier, based on the
30
30
//! final state of the chain at the end of the previous block. This can be configured via
31
31
//! [`Trait::FeeMultiplierUpdate`]
32
+ //! - How the fees are paid via [`Trait::OnChargeTransaction`].
32
33
33
34
#![ cfg_attr( not( feature = "std" ) , no_std) ]
34
35
35
36
use sp_std:: prelude:: * ;
36
37
use codec:: { Encode , Decode } ;
37
38
use frame_support:: {
38
39
decl_storage, decl_module,
39
- traits:: { Currency , Get , OnUnbalanced , ExistenceRequirement , WithdrawReasons , Imbalance } ,
40
+ traits:: Get ,
40
41
weights:: {
41
42
Weight , DispatchInfo , PostDispatchInfo , GetDispatchInfo , Pays , WeightToFeePolynomial ,
42
43
WeightToFeeCoefficient ,
@@ -46,23 +47,23 @@ use frame_support::{
46
47
use sp_runtime:: {
47
48
FixedU128 , FixedPointNumber , FixedPointOperand , Perquintill , RuntimeDebug ,
48
49
transaction_validity:: {
49
- TransactionPriority , ValidTransaction , InvalidTransaction , TransactionValidityError ,
50
- TransactionValidity ,
50
+ TransactionPriority , ValidTransaction , TransactionValidityError , TransactionValidity ,
51
51
} ,
52
52
traits:: {
53
- Zero , Saturating , SignedExtension , SaturatedConversion , Convert , Dispatchable ,
53
+ Saturating , SignedExtension , SaturatedConversion , Convert , Dispatchable ,
54
54
DispatchInfoOf , PostDispatchInfoOf ,
55
55
} ,
56
56
} ;
57
57
use pallet_transaction_payment_rpc_runtime_api:: RuntimeDispatchInfo ;
58
58
59
+ mod payment;
60
+ pub use payment:: * ;
61
+
59
62
/// Fee multiplier.
60
63
pub type Multiplier = FixedU128 ;
61
64
62
65
type BalanceOf < T > =
63
- <<T as Trait >:: Currency as Currency < <T as frame_system:: Trait >:: AccountId > >:: Balance ;
64
- type NegativeImbalanceOf < T > =
65
- <<T as Trait >:: Currency as Currency < <T as frame_system:: Trait >:: AccountId > >:: NegativeImbalance ;
66
+ <<T as Trait >:: OnChargeTransaction as OnChargeTransaction < T > >:: Balance ;
66
67
67
68
/// A struct to update the weight multiplier per block. It implements `Convert<Multiplier,
68
69
/// Multiplier>`, meaning that it can convert the previous multiplier to the next one. This should
@@ -213,13 +214,13 @@ impl Default for Releases {
213
214
}
214
215
215
216
pub trait Trait : frame_system:: Trait {
216
- /// The currency type in which fees will be paid .
217
- type Currency : Currency < Self :: AccountId > + Send + Sync ;
218
-
219
- /// Handler for the unbalanced reduction when taking transaction fees. This is either one or
220
- /// two separate imbalances, the first is the transaction fee paid, the second is the tip paid,
221
- /// if any .
222
- type OnTransactionPayment : OnUnbalanced < NegativeImbalanceOf < Self > > ;
217
+ /// Handler for withdrawing, refunding and depositing the transaction fee .
218
+ /// Transaction fees are withdrawn before the transaction is executed.
219
+ /// After the transaction was executed the transaction weight can be
220
+ /// adjusted, depending on the used resources by the transaction. If the
221
+ /// transaction weight is lower than expected, parts of the transaction fee
222
+ /// might be refunded. In the end the fees can be deposited .
223
+ type OnChargeTransaction : OnChargeTransaction < Self > ;
223
224
224
225
/// The fee to be paid for making a transaction; the per-byte portion.
225
226
type TransactionByteFee : Get < BalanceOf < Self > > ;
@@ -442,30 +443,21 @@ impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> where
442
443
fn withdraw_fee (
443
444
& self ,
444
445
who : & T :: AccountId ,
446
+ call : & T :: Call ,
445
447
info : & DispatchInfoOf < T :: Call > ,
446
448
len : usize ,
447
- ) -> Result < ( BalanceOf < T > , Option < NegativeImbalanceOf < T > > ) , TransactionValidityError > {
449
+ ) -> Result <
450
+ (
451
+ BalanceOf < T > ,
452
+ <<T as Trait >:: OnChargeTransaction as OnChargeTransaction < T > >:: LiquidityInfo ,
453
+ ) ,
454
+ TransactionValidityError ,
455
+ > {
448
456
let tip = self . 0 ;
449
457
let fee = Module :: < T > :: compute_fee ( len as u32 , info, tip) ;
450
458
451
- // Only mess with balances if fee is not zero.
452
- if fee. is_zero ( ) {
453
- return Ok ( ( fee, None ) ) ;
454
- }
455
-
456
- match T :: Currency :: withdraw (
457
- who,
458
- fee,
459
- if tip. is_zero ( ) {
460
- WithdrawReasons :: TRANSACTION_PAYMENT
461
- } else {
462
- WithdrawReasons :: TRANSACTION_PAYMENT | WithdrawReasons :: TIP
463
- } ,
464
- ExistenceRequirement :: KeepAlive ,
465
- ) {
466
- Ok ( imbalance) => Ok ( ( fee, Some ( imbalance) ) ) ,
467
- Err ( _) => Err ( InvalidTransaction :: Payment . into ( ) ) ,
468
- }
459
+ <<T as Trait >:: OnChargeTransaction as OnChargeTransaction < T > >:: withdraw_fee ( who, call, info, fee, tip)
460
+ . map ( |i| ( fee, i) )
469
461
}
470
462
471
463
/// Get an appropriate priority for a transaction with the given length and info.
@@ -505,17 +497,24 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> whe
505
497
type AccountId = T :: AccountId ;
506
498
type Call = T :: Call ;
507
499
type AdditionalSigned = ( ) ;
508
- type Pre = ( BalanceOf < T > , Self :: AccountId , Option < NegativeImbalanceOf < T > > , BalanceOf < T > ) ;
500
+ type Pre = (
501
+ // tip
502
+ BalanceOf < T > ,
503
+ // who paid the fee
504
+ Self :: AccountId ,
505
+ // imbalance resulting from withdrawing the fee
506
+ <<T as Trait >:: OnChargeTransaction as OnChargeTransaction < T > >:: LiquidityInfo ,
507
+ ) ;
509
508
fn additional_signed ( & self ) -> sp_std:: result:: Result < ( ) , TransactionValidityError > { Ok ( ( ) ) }
510
509
511
510
fn validate (
512
511
& self ,
513
512
who : & Self :: AccountId ,
514
- _call : & Self :: Call ,
513
+ call : & Self :: Call ,
515
514
info : & DispatchInfoOf < Self :: Call > ,
516
515
len : usize ,
517
516
) -> TransactionValidity {
518
- let ( fee, _) = self . withdraw_fee ( who, info, len) ?;
517
+ let ( fee, _) = self . withdraw_fee ( who, call , info, len) ?;
519
518
Ok ( ValidTransaction {
520
519
priority : Self :: get_priority ( len, info, fee) ,
521
520
..Default :: default ( )
@@ -525,12 +524,12 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> whe
525
524
fn pre_dispatch (
526
525
self ,
527
526
who : & Self :: AccountId ,
528
- _call : & Self :: Call ,
527
+ call : & Self :: Call ,
529
528
info : & DispatchInfoOf < Self :: Call > ,
530
529
len : usize
531
530
) -> Result < Self :: Pre , TransactionValidityError > {
532
- let ( fee , imbalance) = self . withdraw_fee ( who, info, len) ?;
533
- Ok ( ( self . 0 , who. clone ( ) , imbalance, fee ) )
531
+ let ( _fee , imbalance) = self . withdraw_fee ( who, call , info, len) ?;
532
+ Ok ( ( self . 0 , who. clone ( ) , imbalance) )
534
533
}
535
534
536
535
fn post_dispatch (
@@ -540,32 +539,14 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> whe
540
539
len : usize ,
541
540
_result : & DispatchResult ,
542
541
) -> Result < ( ) , TransactionValidityError > {
543
- let ( tip, who, imbalance, fee) = pre;
544
- if let Some ( payed) = imbalance {
545
- let actual_fee = Module :: < T > :: compute_actual_fee (
546
- len as u32 ,
547
- info,
548
- post_info,
549
- tip,
550
- ) ;
551
- let refund = fee. saturating_sub ( actual_fee) ;
552
- let actual_payment = match T :: Currency :: deposit_into_existing ( & who, refund) {
553
- Ok ( refund_imbalance) => {
554
- // The refund cannot be larger than the up front payed max weight.
555
- // `PostDispatchInfo::calc_unspent` guards against such a case.
556
- match payed. offset ( refund_imbalance) {
557
- Ok ( actual_payment) => actual_payment,
558
- Err ( _) => return Err ( InvalidTransaction :: Payment . into ( ) ) ,
559
- }
560
- }
561
- // We do not recreate the account using the refund. The up front payment
562
- // is gone in that case.
563
- Err ( _) => payed,
564
- } ;
565
- let imbalances = actual_payment. split ( tip) ;
566
- T :: OnTransactionPayment :: on_unbalanceds ( Some ( imbalances. 0 ) . into_iter ( )
567
- . chain ( Some ( imbalances. 1 ) ) ) ;
568
- }
542
+ let ( tip, who, imbalance) = pre;
543
+ let actual_fee = Module :: < T > :: compute_actual_fee (
544
+ len as u32 ,
545
+ info,
546
+ post_info,
547
+ tip,
548
+ ) ;
549
+ T :: OnChargeTransaction :: correct_and_deposit_fee ( & who, info, post_info, actual_fee, tip, imbalance) ?;
569
550
Ok ( ( ) )
570
551
}
571
552
}
@@ -580,6 +561,7 @@ mod tests {
580
561
DispatchClass , DispatchInfo , PostDispatchInfo , GetDispatchInfo , Weight ,
581
562
WeightToFeePolynomial , WeightToFeeCoefficients , WeightToFeeCoefficient ,
582
563
} ,
564
+ traits:: Currency ,
583
565
} ;
584
566
use pallet_balances:: Call as BalancesCall ;
585
567
use pallet_transaction_payment_rpc_runtime_api:: RuntimeDispatchInfo ;
@@ -699,8 +681,7 @@ mod tests {
699
681
}
700
682
701
683
impl Trait for Runtime {
702
- type Currency = pallet_balances:: Module < Runtime > ;
703
- type OnTransactionPayment = ( ) ;
684
+ type OnChargeTransaction = CurrencyAdapter < Balances , ( ) > ;
704
685
type TransactionByteFee = TransactionByteFee ;
705
686
type WeightToFee = WeightToFee ;
706
687
type FeeMultiplierUpdate = ( ) ;
0 commit comments