1#![cfg(feature = "runtime-benchmarks")]
21
22use frame_benchmarking::v1::{
23 account, benchmarks_instance_pallet, whitelisted_caller, BenchmarkError,
24};
25use frame_support::ensure;
26use frame_system::RawOrigin;
27use sp_runtime::traits::Saturating;
28
29use super::*;
30use crate::Pallet as TipsMod;
31
32const SEED: u32 = 0;
33
34fn setup_awesome<T: Config<I>, I: 'static>(length: u32) -> (T::AccountId, Vec<u8>, T::AccountId) {
36 let caller = whitelisted_caller();
37 let value = T::TipReportDepositBase::get() +
38 T::DataDepositPerByte::get() * length.into() +
39 T::Currency::minimum_balance();
40 let _ = T::Currency::make_free_balance_be(&caller, value);
41 let reason = vec![0; length as usize];
42 let awesome_person = account("awesome", 0, SEED);
43 (caller, reason, awesome_person)
44}
45
46fn setup_tip<T: Config<I>, I: 'static>(
48 r: u32,
49 t: u32,
50) -> Result<(T::AccountId, Vec<u8>, T::AccountId, BalanceOf<T, I>), &'static str> {
51 let tippers_count = T::Tippers::count();
52
53 for i in 0..t {
54 let member = account("member", i, SEED);
55 T::Tippers::add(&member);
56 ensure!(T::Tippers::contains(&member), "failed to add tipper");
57 }
58
59 ensure!(T::Tippers::count() == tippers_count + t as usize, "problem creating tippers");
60 let caller = account("member", t - 1, SEED);
61 let reason = vec![0; r as usize];
62 let beneficiary = account("beneficiary", t, SEED);
63 let value = T::Currency::minimum_balance().saturating_mul(100u32.into());
64 Ok((caller, reason, beneficiary, value))
65}
66
67fn create_tips<T: Config<I>, I: 'static>(
70 t: u32,
71 hash: T::Hash,
72 value: BalanceOf<T, I>,
73) -> Result<(), &'static str> {
74 for i in 0..t {
75 let caller = account("member", i, SEED);
76 ensure!(T::Tippers::contains(&caller), "caller is not a tipper");
77 TipsMod::<T, I>::tip(RawOrigin::Signed(caller).into(), hash, value)?;
78 }
79 Tips::<T, I>::mutate(hash, |maybe_tip| {
80 if let Some(open_tip) = maybe_tip {
81 open_tip.closes = Some(frame_system::pallet_prelude::BlockNumberFor::<T>::zero());
82 }
83 });
84 Ok(())
85}
86
87fn setup_pot_account<T: Config<I>, I: 'static>() {
88 let pot_account = TipsMod::<T, I>::account_id();
89 let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000u32.into());
90 let _ = T::Currency::make_free_balance_be(&pot_account, value);
91}
92
93benchmarks_instance_pallet! {
94 report_awesome {
95 let r in 0 .. T::MaximumReasonLength::get();
96 let (caller, reason, awesome_person) = setup_awesome::<T, I>(r);
97 let awesome_person_lookup = T::Lookup::unlookup(awesome_person);
98 let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
100 frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
101 }: _(RawOrigin::Signed(caller), reason, awesome_person_lookup)
102
103 retract_tip {
104 let r = T::MaximumReasonLength::get();
105 let (caller, reason, awesome_person) = setup_awesome::<T, I>(r);
106 let awesome_person_lookup = T::Lookup::unlookup(awesome_person.clone());
107 TipsMod::<T, I>::report_awesome(
108 RawOrigin::Signed(caller.clone()).into(),
109 reason.clone(),
110 awesome_person_lookup
111 )?;
112 let reason_hash = T::Hashing::hash(&reason[..]);
113 let hash = T::Hashing::hash_of(&(&reason_hash, &awesome_person));
114 let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
116 frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
117 }: _(RawOrigin::Signed(caller), hash)
118
119 tip_new {
120 let r in 0 .. T::MaximumReasonLength::get();
121 let t in 1 .. T::Tippers::max_len() as u32;
122
123 let (caller, reason, beneficiary, value) = setup_tip::<T, I>(r, t)?;
124 let beneficiary_lookup = T::Lookup::unlookup(beneficiary);
125 let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
127 frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
128 }: _(RawOrigin::Signed(caller), reason, beneficiary_lookup, value)
129
130 tip {
131 let t in 1 .. T::Tippers::max_len() as u32;
132 let (member, reason, beneficiary, value) = setup_tip::<T, I>(0, t)?;
133 let beneficiary_lookup = T::Lookup::unlookup(beneficiary.clone());
134 let value = T::Currency::minimum_balance().saturating_mul(100u32.into());
135 TipsMod::<T, I>::tip_new(
136 RawOrigin::Signed(member).into(),
137 reason.clone(),
138 beneficiary_lookup,
139 value
140 )?;
141 let reason_hash = T::Hashing::hash(&reason[..]);
142 let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
143 ensure!(Tips::<T, I>::contains_key(hash), "tip does not exist");
144 create_tips::<T, I>(t - 1, hash, value)?;
145 let caller = account("member", t - 1, SEED);
146 let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
148 frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
149 }: _(RawOrigin::Signed(caller), hash, value)
150
151 close_tip {
152 let t in 1 .. T::Tippers::max_len() as u32;
153
154 setup_pot_account::<T, I>();
156
157 let (member, reason, beneficiary, value) = setup_tip::<T, I>(0, t)?;
159 let beneficiary_lookup = T::Lookup::unlookup(beneficiary.clone());
160 let value = T::Currency::minimum_balance().saturating_mul(100u32.into());
161 TipsMod::<T, I>::tip_new(
162 RawOrigin::Signed(member).into(),
163 reason.clone(),
164 beneficiary_lookup,
165 value
166 )?;
167
168 let reason_hash = T::Hashing::hash(&reason[..]);
170 let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
171 ensure!(Tips::<T, I>::contains_key(hash), "tip does not exist");
172
173 create_tips::<T, I>(t, hash, value)?;
174
175 let caller = account("caller", t, SEED);
176 let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
178 frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
179 }: _(RawOrigin::Signed(caller), hash)
180
181 slash_tip {
182 let t in 1 .. T::Tippers::max_len() as u32;
183
184 setup_pot_account::<T, I>();
186
187 let (member, reason, beneficiary, value) = setup_tip::<T, I>(0, t)?;
189 let beneficiary_lookup = T::Lookup::unlookup(beneficiary.clone());
190 let value = T::Currency::minimum_balance().saturating_mul(100u32.into());
191 TipsMod::<T, I>::tip_new(
192 RawOrigin::Signed(member).into(),
193 reason.clone(),
194 beneficiary_lookup,
195 value
196 )?;
197
198 let reason_hash = T::Hashing::hash(&reason[..]);
199 let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary));
200 ensure!(Tips::<T, I>::contains_key(hash), "tip does not exist");
201 let reject_origin =
202 T::RejectOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
203 }: _<T::RuntimeOrigin>(reject_origin, hash)
204
205 impl_benchmark_test_suite!(TipsMod, crate::tests::new_test_ext(), crate::tests::Test);
206}