pallet_lottery/
benchmarking.rs1#![cfg(feature = "runtime-benchmarks")]
21
22use super::*;
23
24use crate::Pallet as Lottery;
25use alloc::{boxed::Box, vec};
26use frame_benchmarking::{
27 v1::{account, whitelisted_caller, BenchmarkError},
28 v2::*,
29};
30use frame_support::{
31 storage::bounded_vec::BoundedVec,
32 traits::{EnsureOrigin, OnInitialize},
33};
34use frame_system::RawOrigin;
35use sp_runtime::traits::{Bounded, Zero};
36
37fn setup_lottery<T: Config>(repeat: bool) -> Result<(), &'static str> {
39 let price = T::Currency::minimum_balance();
40 let length = 10u32.into();
41 let delay = 5u32.into();
42 let mut calls = vec![
44 frame_system::Call::<T>::set_code { code: vec![] }.into();
45 T::MaxCalls::get().saturating_sub(1) as usize
46 ];
47 calls.push(frame_system::Call::<T>::remark { remark: vec![] }.into());
49 let origin = T::ManagerOrigin::try_successful_origin()
50 .expect("ManagerOrigin has no successful origin required for the benchmark");
51 Lottery::<T>::set_calls(origin.clone(), calls)?;
52 Lottery::<T>::start_lottery(origin, price, length, delay, repeat)?;
53 Ok(())
54}
55
56#[benchmarks]
57mod benchmarks {
58 use super::*;
59
60 #[benchmark]
61 fn buy_ticket() -> Result<(), BenchmarkError> {
62 let caller = whitelisted_caller();
63 T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
64 setup_lottery::<T>(false)?;
65 let set_code_index: CallIndex = Lottery::<T>::call_to_index(
67 &frame_system::Call::<T>::set_code { code: vec![] }.into(),
68 )?;
69 let already_called: (u32, BoundedVec<CallIndex, T::MaxCalls>) = (
70 LotteryIndex::<T>::get(),
71 BoundedVec::<CallIndex, T::MaxCalls>::try_from(vec![
72 set_code_index;
73 T::MaxCalls::get().saturating_sub(1)
74 as usize
75 ])
76 .unwrap(),
77 );
78 Participants::<T>::insert(&caller, already_called);
79
80 let call = frame_system::Call::<T>::remark { remark: vec![] };
81
82 #[extrinsic_call]
83 _(RawOrigin::Signed(caller), Box::new(call.into()));
84
85 assert_eq!(TicketsCount::<T>::get(), 1);
86
87 Ok(())
88 }
89
90 #[benchmark]
91 fn set_calls(n: Linear<0, { T::MaxCalls::get() }>) -> Result<(), BenchmarkError> {
92 let calls = vec![frame_system::Call::<T>::remark { remark: vec![] }.into(); n as usize];
93 let origin =
94 T::ManagerOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
95 assert!(CallIndices::<T>::get().is_empty());
96
97 #[extrinsic_call]
98 _(origin as T::RuntimeOrigin, calls);
99
100 if !n.is_zero() {
101 assert!(!CallIndices::<T>::get().is_empty());
102 }
103
104 Ok(())
105 }
106
107 #[benchmark]
108 fn start_lottery() -> Result<(), BenchmarkError> {
109 let price = BalanceOf::<T>::max_value();
110 let end = 10u32.into();
111 let payout = 5u32.into();
112 let origin =
113 T::ManagerOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
114
115 #[extrinsic_call]
116 _(origin as T::RuntimeOrigin, price, end, payout, true);
117
118 assert!(crate::Lottery::<T>::get().is_some());
119
120 Ok(())
121 }
122
123 #[benchmark]
124 fn stop_repeat() -> Result<(), BenchmarkError> {
125 setup_lottery::<T>(true)?;
126 assert_eq!(crate::Lottery::<T>::get().unwrap().repeat, true);
127 let origin =
128 T::ManagerOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
129
130 #[extrinsic_call]
131 _(origin as T::RuntimeOrigin);
132
133 assert_eq!(crate::Lottery::<T>::get().unwrap().repeat, false);
134
135 Ok(())
136 }
137
138 #[benchmark]
139 fn on_initialize_end() -> Result<(), BenchmarkError> {
140 setup_lottery::<T>(false)?;
141 let winner = account("winner", 0, 0);
142 T::Currency::make_free_balance_be(&winner, T::Currency::minimum_balance() * 10u32.into());
144 let lottery_account = Lottery::<T>::account_id();
146 T::Currency::make_free_balance_be(
147 &lottery_account,
148 T::Currency::minimum_balance() * 10u32.into(),
149 );
150 let call = frame_system::Call::<T>::remark { remark: vec![] };
152 Lottery::<T>::buy_ticket(RawOrigin::Signed(winner.clone()).into(), Box::new(call.into()))?;
153 T::Currency::make_free_balance_be(&winner, 0u32.into());
155 assert_eq!(TicketsCount::<T>::get(), 1);
157 assert!(!Lottery::<T>::pot().1.is_zero());
158
159 #[block]
160 {
161 for i in 0..T::MaxGenerateRandom::get() {
163 Lottery::<T>::generate_random_number(i);
164 }
165 Lottery::<T>::on_initialize(15u32.into());
167 }
168
169 assert!(crate::Lottery::<T>::get().is_none());
170 assert_eq!(TicketsCount::<T>::get(), 0);
171 assert_eq!(Lottery::<T>::pot().1, 0u32.into());
172 assert!(!T::Currency::free_balance(&winner).is_zero());
173
174 Ok(())
175 }
176
177 #[benchmark]
178 fn on_initialize_repeat() -> Result<(), BenchmarkError> {
179 setup_lottery::<T>(true)?;
180 let winner = account("winner", 0, 0);
181 T::Currency::make_free_balance_be(&winner, T::Currency::minimum_balance() * 10u32.into());
183 let lottery_account = Lottery::<T>::account_id();
185 T::Currency::make_free_balance_be(
186 &lottery_account,
187 T::Currency::minimum_balance() * 10u32.into(),
188 );
189 let call = frame_system::Call::<T>::remark { remark: vec![] };
191 Lottery::<T>::buy_ticket(RawOrigin::Signed(winner.clone()).into(), Box::new(call.into()))?;
192 T::Currency::make_free_balance_be(&winner, 0u32.into());
194 assert_eq!(TicketsCount::<T>::get(), 1);
196 assert!(!Lottery::<T>::pot().1.is_zero());
197
198 #[block]
199 {
200 for i in 0..T::MaxGenerateRandom::get() {
202 Lottery::<T>::generate_random_number(i);
203 }
204 Lottery::<T>::on_initialize(15u32.into());
206 }
207
208 assert!(crate::Lottery::<T>::get().is_some());
209 assert_eq!(LotteryIndex::<T>::get(), 2);
210 assert_eq!(TicketsCount::<T>::get(), 0);
211 assert_eq!(Lottery::<T>::pot().1, 0u32.into());
212 assert!(!T::Currency::free_balance(&winner).is_zero());
213
214 Ok(())
215 }
216
217 impl_benchmark_test_suite!(Lottery, crate::mock::new_test_ext(), crate::mock::Test);
218}