Skip to content

Commit 63e82f2

Browse files
committed
fix: ⚡ fix charge_transaction_payment benchmark
1 parent 08a4a54 commit 63e82f2

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

substrate/frame/transaction-payment/src/benchmarking.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,29 @@
2020
extern crate alloc;
2121

2222
use super::*;
23-
use crate::Pallet;
2423
use frame_benchmarking::v2::*;
2524
use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
2625
use frame_system::{EventRecord, RawOrigin};
2726
use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction, Dispatchable};
2827

29-
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
28+
/// Re-export the pallet for benchmarking with custom Config trait.
29+
pub struct Pallet<T: Config>(crate::Pallet<T>);
30+
31+
/// Benchmark configuration trait.
32+
///
33+
/// This extends the pallet's Config trait to allow runtimes to set up any
34+
/// required state before running benchmarks. For example, runtimes that
35+
/// distribute fees to block authors may need to set the author before
36+
/// the benchmark runs.
37+
pub trait Config: crate::Config {
38+
/// Called at the start of each benchmark to set up any required state.
39+
///
40+
/// The default implementation is a no-op. Runtimes can override this
41+
/// to perform setup like setting the block author for fee distribution.
42+
fn setup_benchmark_environment() {}
43+
}
44+
45+
fn assert_last_event<T: crate::Config>(generic_event: <T as crate::Config>::RuntimeEvent) {
3046
let events = frame_system::Pallet::<T>::events();
3147
let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
3248
// compare to the last event record
@@ -44,19 +60,17 @@ mod benchmarks {
4460

4561
#[benchmark]
4662
fn charge_transaction_payment() {
63+
T::setup_benchmark_environment();
64+
4765
let caller: T::AccountId = account("caller", 0, 0);
4866
let existential_deposit =
4967
<T::OnChargeTransaction as OnChargeTransaction<T>>::minimum_balance();
5068

51-
let (amount_to_endow, tip) = if existential_deposit.is_zero() {
52-
let min_tip: <<T as pallet::Config>::OnChargeTransaction as payment::OnChargeTransaction<T>>::Balance = 1_000_000_000u32.into();
53-
(min_tip * 1000u32.into(), min_tip)
54-
} else {
55-
(existential_deposit * 1000u32.into(), existential_deposit)
56-
};
57-
58-
<T::OnChargeTransaction as OnChargeTransaction<T>>::endow_account(&caller, amount_to_endow);
69+
// Use a reasonable minimum tip that works for most runtimes
70+
let min_tip: BalanceOf<T> = 1_000_000_000u32.into();
71+
let tip = if existential_deposit.is_zero() { min_tip } else { existential_deposit };
5972

73+
// Build the call and dispatch info first so we can compute the actual fee
6074
let ext: ChargeTransactionPayment<T> = ChargeTransactionPayment::from(tip);
6175
let inner = frame_system::Call::remark { remark: alloc::vec![] };
6276
let call = T::RuntimeCall::from(inner);
@@ -72,18 +86,29 @@ mod benchmarks {
7286
pays_fee: Pays::Yes,
7387
};
7488

89+
// Calculate the actual fee that will be charged, then endow enough to cover it
90+
// with a 10x buffer to account for any fee multiplier variations.
91+
// Ensure we endow at least the existential deposit so the account can exist.
92+
let len: u32 = 10;
93+
let expected_fee = crate::Pallet::<T>::compute_fee(len, &info, tip);
94+
let amount_to_endow = expected_fee
95+
.saturating_mul(10u32.into())
96+
.max(existential_deposit);
97+
98+
<T::OnChargeTransaction as OnChargeTransaction<T>>::endow_account(&caller, amount_to_endow);
99+
75100
#[block]
76101
{
77102
assert!(ext
78-
.test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 10, 0, |_| Ok(
103+
.test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, len as usize, 0, |_| Ok(
79104
post_info
80105
))
81106
.unwrap()
82107
.is_ok());
83108
}
84109

85110
post_info.actual_weight.as_mut().map(|w| w.saturating_accrue(extension_weight));
86-
let actual_fee = Pallet::<T>::compute_actual_fee(10, &info, &post_info, tip);
111+
let actual_fee = crate::Pallet::<T>::compute_actual_fee(len, &info, &post_info, tip);
87112
assert_last_event::<T>(
88113
Event::<T>::TransactionFeePaid { who: caller, actual_fee, tip }.into(),
89114
);

substrate/frame/transaction-payment/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ mod mock;
7878
mod tests;
7979

8080
#[cfg(feature = "runtime-benchmarks")]
81-
mod benchmarking;
81+
pub mod benchmarking;
8282

8383
mod payment;
8484
mod types;

0 commit comments

Comments
 (0)