1#![cfg(feature = "runtime-benchmarks")]
21
22use frame::benchmarking::prelude::*;
23
24use crate::*;
25
26const SEED: u32 = 0;
27
28type BalanceOf<T> =
29 <<T as Config>::Currency as FunInspect<<T as frame_system::Config>::AccountId>>::Balance;
30
31fn fill_queues<T: Config>() -> Result<(), DispatchError> {
32 let queues = T::QueueCount::get();
36 let bids = T::MaxQueueLen::get();
37
38 let caller: T::AccountId = whitelisted_caller();
39 T::Currency::set_balance(&caller, T::MinBid::get() * BalanceOf::<T>::from(queues + bids));
40
41 for _ in 0..bids {
42 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
43 }
44 for d in 1..queues {
45 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1 + d)?;
46 }
47 Ok(())
48}
49
50#[benchmarks]
51mod benchmarks {
52 use super::*;
53
54 #[benchmark]
55 fn place_bid(l: Linear<0, { T::MaxQueueLen::get() - 1 }>) -> Result<(), BenchmarkError> {
56 let caller: T::AccountId = whitelisted_caller();
57 let ed = T::Currency::minimum_balance();
58 let bid = T::MinBid::get();
59 T::Currency::set_balance(&caller, (ed + bid) * BalanceOf::<T>::from(l + 1) + bid);
60 for _ in 0..l {
61 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
62 }
63
64 #[extrinsic_call]
65 _(RawOrigin::Signed(caller.clone()), T::MinBid::get() * BalanceOf::<T>::from(2_u32), 1);
66
67 assert_eq!(
68 QueueTotals::<T>::get()[0],
69 (l + 1, T::MinBid::get() * BalanceOf::<T>::from(l + 2))
70 );
71
72 Ok(())
73 }
74
75 #[benchmark]
76 fn place_bid_max() -> Result<(), BenchmarkError> {
77 let caller: T::AccountId = whitelisted_caller();
78 let origin = RawOrigin::Signed(caller.clone());
79 let ed = T::Currency::minimum_balance();
80 let bid = T::MinBid::get();
81 let ql = T::MaxQueueLen::get();
82 T::Currency::set_balance(&caller, (ed + bid) * BalanceOf::<T>::from(ql + 1) + bid);
83 for _ in 0..T::MaxQueueLen::get() {
84 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
85 }
86
87 #[extrinsic_call]
88 place_bid(origin, T::MinBid::get() * BalanceOf::<T>::from(2_u32), 1);
89
90 assert_eq!(
91 QueueTotals::<T>::get()[0],
92 (
93 T::MaxQueueLen::get(),
94 T::MinBid::get() * BalanceOf::<T>::from(T::MaxQueueLen::get() + 1),
95 )
96 );
97
98 Ok(())
99 }
100
101 #[benchmark]
102 fn retract_bid(l: Linear<1, { T::MaxQueueLen::get() }>) -> Result<(), BenchmarkError> {
103 let caller: T::AccountId = whitelisted_caller();
104 let ed = T::Currency::minimum_balance();
105 let bid = T::MinBid::get();
106 T::Currency::set_balance(&caller, (ed + bid) * BalanceOf::<T>::from(l + 1) + bid);
107 for _ in 0..l {
108 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinBid::get(), 1)?;
109 }
110
111 #[extrinsic_call]
112 _(RawOrigin::Signed(caller.clone()), T::MinBid::get(), 1);
113
114 assert_eq!(
115 QueueTotals::<T>::get()[0],
116 (l - 1, T::MinBid::get() * BalanceOf::<T>::from(l - 1))
117 );
118
119 Ok(())
120 }
121
122 #[benchmark]
123 fn fund_deficit() -> Result<(), BenchmarkError> {
124 T::BenchmarkSetup::create_counterpart_asset();
125 let origin =
126 T::FundOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
127 let caller: T::AccountId = whitelisted_caller();
128 let bid = T::MinBid::get().max(One::one());
129 let ed = T::Currency::minimum_balance();
130 T::Currency::set_balance(&caller, ed + bid);
131 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
132 Pallet::<T>::process_queues(Perquintill::one(), 1, 1, &mut WeightCounter::unlimited());
133 Pallet::<T>::communify(RawOrigin::Signed(caller.clone()).into(), 0)?;
134 let original = T::Currency::balance(&Pallet::<T>::account_id());
135 T::Currency::set_balance(&Pallet::<T>::account_id(), BalanceOf::<T>::min_value());
136
137 #[extrinsic_call]
138 _(origin as T::RuntimeOrigin);
139
140 let missing =
142 Perquintill::from_rational(T::Currency::balance(&Pallet::<T>::account_id()), original)
143 .left_from_one();
144 assert!(missing <= Perquintill::one() / 100_000);
145
146 Ok(())
147 }
148
149 #[benchmark]
150 fn communify() -> Result<(), BenchmarkError> {
151 T::BenchmarkSetup::create_counterpart_asset();
152 let caller: T::AccountId = whitelisted_caller();
153 let bid = T::MinBid::get().max(One::one()) * 100u32.into();
154 let ed = T::Currency::minimum_balance();
155 T::Currency::set_balance(&caller, ed + bid + bid);
156 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
157 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
158 Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
159
160 #[extrinsic_call]
161 _(RawOrigin::Signed(caller.clone()), 0);
162
163 assert_eq!(Pallet::<T>::owner(&0), None);
164
165 Ok(())
166 }
167
168 #[benchmark]
169 fn privatize() -> Result<(), BenchmarkError> {
170 T::BenchmarkSetup::create_counterpart_asset();
171 let caller: T::AccountId = whitelisted_caller();
172 let bid = T::MinBid::get().max(One::one());
173 let ed = T::Currency::minimum_balance();
174 T::Currency::set_balance(&caller, ed + bid + bid);
175 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
176 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
177 Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
178 Pallet::<T>::communify(RawOrigin::Signed(caller.clone()).into(), 0)?;
179
180 #[extrinsic_call]
181 _(RawOrigin::Signed(caller.clone()), 0);
182
183 assert_eq!(Pallet::<T>::owner(&0), Some(caller));
184
185 Ok(())
186 }
187
188 #[benchmark]
189 fn thaw_private() -> Result<(), BenchmarkError> {
190 T::BenchmarkSetup::create_counterpart_asset();
191 let whale: T::AccountId = account("whale", 0, SEED);
192 let caller: T::AccountId = whitelisted_caller();
193 let bid = T::MinBid::get().max(One::one());
194 let ed = T::Currency::minimum_balance();
195 T::Currency::set_balance(&caller, ed + bid + bid);
196 T::Currency::set_balance(
198 &whale,
199 T::ThawThrottle::get()
200 .0
201 .saturating_reciprocal_mul_ceil(T::Currency::balance(&caller)),
202 );
203 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
204 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
205 Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
206 frame_system::Pallet::<T>::set_block_number(Receipts::<T>::get(0).unwrap().expiry);
207
208 #[extrinsic_call]
209 _(RawOrigin::Signed(caller.clone()), 0, None);
210
211 assert!(Receipts::<T>::get(0).is_none());
212
213 Ok(())
214 }
215
216 #[benchmark]
217 fn thaw_communal() -> Result<(), BenchmarkError> {
218 T::BenchmarkSetup::create_counterpart_asset();
219 let whale: T::AccountId = account("whale", 0, SEED);
220 let caller: T::AccountId = whitelisted_caller();
221 let bid = T::MinBid::get().max(One::one());
222 let ed = T::Currency::minimum_balance();
223 T::Currency::set_balance(&caller, ed + bid + bid);
224 T::Currency::set_balance(
226 &whale,
227 T::ThawThrottle::get()
228 .0
229 .saturating_reciprocal_mul_ceil(T::Currency::balance(&caller)),
230 );
231 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
232 Pallet::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), bid, 1)?;
233 Pallet::<T>::process_queues(Perquintill::one(), 1, 2, &mut WeightCounter::unlimited());
234 frame_system::Pallet::<T>::set_block_number(Receipts::<T>::get(0).unwrap().expiry);
235 Pallet::<T>::communify(RawOrigin::Signed(caller.clone()).into(), 0)?;
236
237 #[extrinsic_call]
238 _(RawOrigin::Signed(caller.clone()), 0);
239
240 assert!(Receipts::<T>::get(0).is_none());
241
242 Ok(())
243 }
244
245 #[benchmark]
246 fn process_queues() -> Result<(), BenchmarkError> {
247 fill_queues::<T>()?;
248
249 #[block]
250 {
251 Pallet::<T>::process_queues(
252 Perquintill::one(),
253 Zero::zero(),
254 u32::max_value(),
255 &mut WeightCounter::unlimited(),
256 );
257 }
258
259 Ok(())
260 }
261
262 #[benchmark]
263 fn process_queue() {
264 let our_account = Pallet::<T>::account_id();
265 let issuance = Pallet::<T>::issuance();
266 let mut summary = Summary::<T>::get();
267
268 #[block]
269 {
270 Pallet::<T>::process_queue(
271 1_u32,
272 1_u32.into(),
273 &our_account,
274 &issuance,
275 0,
276 &mut Bounded::max_value(),
277 &mut (T::MaxQueueLen::get(), Bounded::max_value()),
278 &mut summary,
279 &mut WeightCounter::unlimited(),
280 );
281 }
282 }
283
284 #[benchmark]
285 fn process_bid() {
286 let who = account::<T::AccountId>("bidder", 0, SEED);
287 let min_bid = T::MinBid::get().max(One::one());
288 let ed = T::Currency::minimum_balance();
289 T::Currency::set_balance(&who, ed + min_bid);
290 let bid = Bid { amount: T::MinBid::get(), who };
291 let our_account = Pallet::<T>::account_id();
292 let issuance = Pallet::<T>::issuance();
293 let mut summary = Summary::<T>::get();
294
295 #[block]
296 {
297 Pallet::<T>::process_bid(
298 bid,
299 2_u32.into(),
300 &our_account,
301 &issuance,
302 &mut Bounded::max_value(),
303 &mut Bounded::max_value(),
304 &mut summary,
305 );
306 }
307 }
308
309 impl_benchmark_test_suite! {
310 Pallet,
311 mock::new_test_ext_empty(),
312 mock::Test
313 }
314}