pallet_pgas_allowance/
benchmarking.rs1extern crate alloc;
22
23use super::*;
24use crate::{BenchmarkHelperTrait, Pallet};
25use frame_benchmarking::v2::*;
26use frame_support::{
27 dispatch::{DispatchClass, DispatchInfo, PostDispatchInfo},
28 pallet_prelude::Weight,
29 traits::tokens::fungibles,
30};
31use frame_system::RawOrigin;
32use sp_runtime::traits::{
33 AsSystemOriginSigner, AsTransactionAuthorizedOrigin, DispatchTransaction, Dispatchable,
34};
35
36#[benchmarks(where
37 T: Send + Sync,
38 T::RuntimeOrigin: AsTransactionAuthorizedOrigin,
39 T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
40 + From<frame_system::Call<T>>,
41 BalanceOf<T>: Send + Sync + From<u64>,
42 AssetIdOf<T>: Send + Sync,
43 <T::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<T::AccountId> + Clone,
44)]
45mod benchmarks {
46 use super::*;
47
48 #[benchmark]
51 fn charge_pgas() {
52 let caller: T::AccountId = account("caller", 0, 0);
53 let initial: BalanceOf<T> = u64::MAX.into();
54 <T as Config>::BenchmarkHelper::mint_pgas(&caller, T::PGASAssetId::get(), initial);
55
56 let ext: ChargePGAS<T, ()> = ChargePGAS::<T, ()>::default();
57 let call: T::RuntimeCall = frame_system::Call::<T>::remark { remark: alloc::vec![] }.into();
58 let info = DispatchInfo {
59 call_weight: Weight::from_parts(100, 0),
60 class: DispatchClass::Normal,
61 ..Default::default()
62 };
63 let post_info = PostDispatchInfo {
64 actual_weight: Some(Weight::from_parts(10, 0)),
65 pays_fee: Default::default(),
66 };
67
68 let result;
69 #[block]
70 {
71 result =
72 ext.test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 0, 0, |_| {
73 Ok(post_info)
74 });
75 }
76 assert!(result.unwrap().is_ok());
77 let remaining = <T::Assets as fungibles::Inspect<T::AccountId>>::balance(
78 T::PGASAssetId::get(),
79 &caller,
80 );
81 assert!(remaining < initial, "PGAS should be charged on the PGAS path");
82 }
83
84 #[benchmark]
88 fn charge_pgas_skip() {
89 let caller: T::AccountId = account("caller", 0, 0);
90 let min_balance =
94 <T::Assets as fungibles::Inspect<T::AccountId>>::minimum_balance(T::PGASAssetId::get());
95 <T as Config>::BenchmarkHelper::mint_pgas(&caller, T::PGASAssetId::get(), min_balance);
96
97 let ext: ChargePGAS<T, ()> = ChargePGAS::<T, ()>::default();
98 let call: T::RuntimeCall = frame_system::Call::<T>::remark { remark: alloc::vec![] }.into();
99 let info = DispatchInfo {
100 call_weight: Weight::from_parts(10, 0),
101 class: DispatchClass::Normal,
102 ..Default::default()
103 };
104 let post_info = PostDispatchInfo {
105 actual_weight: Some(Weight::from_parts(10, 0)),
106 pays_fee: Default::default(),
107 };
108
109 let fee = pallet_transaction_payment::Pallet::<T>::compute_fee(0, &info, Zero::zero());
110 assert!(!fee.is_zero(), "skip path requires fee > 0 to exercise `pgas < fee`");
111 let before = <T::Assets as fungibles::Inspect<T::AccountId>>::balance(
112 T::PGASAssetId::get(),
113 &caller,
114 );
115 assert!(before < fee, "caller must not hold enough PGAS to take the PGAS branch");
116 let result;
117 #[block]
118 {
119 result =
120 ext.test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 0, 0, |_| {
121 Ok(post_info)
122 });
123 }
124 assert!(result.unwrap().is_ok());
125 let after = <T::Assets as fungibles::Inspect<T::AccountId>>::balance(
126 T::PGASAssetId::get(),
127 &caller,
128 );
129 assert_eq!(before, after, "PGAS must not be charged on the skip path");
130 }
131
132 impl_benchmark_test_suite!(
133 Pallet,
134 crate::mock::ExtBuilder::default().build(),
135 crate::mock::Runtime
136 );
137}