pallet_meta_tx/
benchmarking.rs1#![cfg(feature = "runtime-benchmarks")]
19
20use super::*;
21use frame_benchmarking::v2::*;
22use frame_support::traits::UnfilteredDispatchable;
23use sp_runtime::impl_tx_ext_default;
24
25pub mod types {
26 use super::*;
27 use frame_support::traits::OriginTrait;
28 use sp_runtime::traits::DispatchInfoOf;
29
30 type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
31
32 #[derive(TypeInfo, Eq, PartialEq, Clone, Encode, Decode, DecodeWithMemTracking)]
34 #[scale_info(skip_type_params(T))]
35 pub struct WeightlessExtension<T>(core::marker::PhantomData<T>);
36 impl<T: Config + Send + Sync> core::fmt::Debug for WeightlessExtension<T> {
37 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
38 write!(f, "WeightlessExtension")
39 }
40 }
41 impl<T: Config + Send + Sync> Default for WeightlessExtension<T> {
42 fn default() -> Self {
43 WeightlessExtension(Default::default())
44 }
45 }
46 impl<T: Config + Send + Sync> TransactionExtension<CallOf<T>> for WeightlessExtension<T> {
47 const IDENTIFIER: &'static str = "WeightlessExtension";
48 type Implicit = ();
49 type Pre = ();
50 type Val = ();
51 fn weight(&self, _call: &CallOf<T>) -> Weight {
52 Weight::from_all(0)
53 }
54 fn validate(
55 &self,
56 mut origin: <CallOf<T> as Dispatchable>::RuntimeOrigin,
57 _: &CallOf<T>,
58 _: &DispatchInfoOf<CallOf<T>>,
59 _: usize,
60 _: (),
61 _: &impl Encode,
62 _: TransactionSource,
63 ) -> Result<
64 (ValidTransaction, Self::Val, <CallOf<T> as Dispatchable>::RuntimeOrigin),
65 TransactionValidityError,
66 > {
67 origin.set_caller_from_signed(whitelisted_caller());
68 Ok((ValidTransaction::default(), (), origin))
69 }
70
71 impl_tx_ext_default!(CallOf<T>; prepare);
72 }
73}
74
75fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
76 frame_system::Pallet::<T>::assert_last_event(generic_event.into());
77}
78
79#[benchmarks(
80 where
81 T: Config,
82 <T as Config>::Extension: Default,
83 )]
84mod benchmarks {
85 use super::*;
86
87 #[benchmark]
88 fn bare_dispatch() {
89 let meta_call = frame_system::Call::<T>::remark { remark: vec![] }.into();
90 let meta_ext = T::Extension::default();
91 let meta_ext_weight = meta_ext.weight(&meta_call);
92
93 #[cfg(not(test))]
94 assert!(
95 meta_ext_weight.is_zero(),
96 "meta tx extension weight for the benchmarks must be zero. \
97 use `pallet_meta_tx::WeightlessExtension` as `pallet_meta_tx::Config::Extension` \
98 with the `runtime-benchmarks` feature enabled.",
99 );
100
101 let meta_tx = MetaTxFor::<T>::new(meta_call.clone(), 0u8, meta_ext.clone());
102
103 let caller = whitelisted_caller();
104 let origin: <T as frame_system::Config>::RuntimeOrigin =
105 frame_system::RawOrigin::Signed(caller).into();
106 let call = Call::<T>::dispatch { meta_tx: Box::new(meta_tx) };
107
108 #[block]
109 {
110 let _ = call.dispatch_bypass_filter(origin);
111 }
112
113 let info = meta_call.get_dispatch_info();
114 assert_last_event::<T>(
115 Event::Dispatched {
116 result: Ok(PostDispatchInfo {
117 actual_weight: Some(info.call_weight + meta_ext_weight),
118 pays_fee: Pays::Yes,
119 }),
120 }
121 .into(),
122 );
123 }
124
125 impl_benchmark_test_suite! {
126 Pallet,
127 crate::mock::new_test_ext(),
128 crate::mock::Runtime,
129 }
130}