referrerpolicy=no-referrer-when-downgrade

pallet_tips/
benchmarking.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Treasury tips benchmarking.
19
20#![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
34// Create the pre-requisite information needed to create a `report_awesome`.
35fn 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
46// Create the pre-requisite information needed to call `tip_new`.
47fn 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
67// Create `t` new tips for the tip proposal with `hash`.
68// This function automatically makes the tip able to close.
69fn 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		// Whitelist caller account from further DB operations.
99		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		// Whitelist caller account from further DB operations.
115		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		// Whitelist caller account from further DB operations.
126		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		// Whitelist caller account from further DB operations.
147		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		// Make sure pot is funded
155		setup_pot_account::<T, I>();
156
157		// Set up a new tip proposal
158		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		// Create a bunch of tips
169		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		// Whitelist caller account from further DB operations.
177		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		// Make sure pot is funded
185		setup_pot_account::<T, I>();
186
187		// Set up a new tip proposal
188		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}