1#![cfg(feature = "runtime-benchmarks")]
21
22use core::{cmp, mem::size_of};
23use sp_runtime::traits::{Bounded, Hash, StaticLookup};
24
25use frame_benchmarking::{account, v2::*, BenchmarkError};
26use frame_support::traits::{EnsureOrigin, Get, UnfilteredDispatchable};
27use frame_system::{pallet_prelude::BlockNumberFor, Pallet as System, RawOrigin as SystemOrigin};
28
29use super::{Call as AllianceCall, Pallet as Alliance, *};
30
31const SEED: u32 = 0;
32
33const MAX_BYTES: u32 = 1_024;
34
35fn assert_last_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) {
36 frame_system::Pallet::<T>::assert_last_event(generic_event.into());
37}
38
39fn cid(input: impl AsRef<[u8]>) -> Cid {
40 let result = sp_crypto_hashing::sha2_256(input.as_ref());
41 Cid::new_v0(result)
42}
43
44fn rule(input: impl AsRef<[u8]>) -> Cid {
45 cid(input)
46}
47
48fn announcement(input: impl AsRef<[u8]>) -> Cid {
49 cid(input)
50}
51
52fn funded_account<T: Config<I>, I: 'static>(name: &'static str, index: u32) -> T::AccountId {
53 let account: T::AccountId = account(name, index, SEED);
54 T::Currency::make_free_balance_be(&account, BalanceOf::<T, I>::max_value() / 100u8.into());
55 account
56}
57
58fn fellow<T: Config<I>, I: 'static>(index: u32) -> T::AccountId {
59 funded_account::<T, I>("fellow", index)
60}
61
62fn ally<T: Config<I>, I: 'static>(index: u32) -> T::AccountId {
63 funded_account::<T, I>("ally", index)
64}
65
66fn outsider<T: Config<I>, I: 'static>(index: u32) -> T::AccountId {
67 funded_account::<T, I>("outsider", index)
68}
69
70fn generate_unscrupulous_account<T: Config<I>, I: 'static>(index: u32) -> T::AccountId {
71 funded_account::<T, I>("unscrupulous", index)
72}
73
74fn set_members<T: Config<I>, I: 'static>() {
75 let fellows: BoundedVec<_, T::MaxMembersCount> =
76 BoundedVec::try_from(vec![fellow::<T, I>(1), fellow::<T, I>(2)]).unwrap();
77 fellows.iter().for_each(|who| {
78 T::Currency::reserve(&who, T::AllyDeposit::get()).unwrap();
79 <DepositOf<T, I>>::insert(&who, T::AllyDeposit::get());
80 });
81 Members::<T, I>::insert(MemberRole::Fellow, fellows.clone());
82
83 let allies: BoundedVec<_, T::MaxMembersCount> =
84 BoundedVec::try_from(vec![ally::<T, I>(1)]).unwrap();
85 allies.iter().for_each(|who| {
86 T::Currency::reserve(&who, T::AllyDeposit::get()).unwrap();
87 <DepositOf<T, I>>::insert(&who, T::AllyDeposit::get());
88 });
89 Members::<T, I>::insert(MemberRole::Ally, allies);
90
91 T::InitializeMembers::initialize_members(&[fellows.as_slice()].concat());
92}
93
94#[instance_benchmarks]
95mod benchmarks {
96 use super::*;
97
98 #[benchmark]
100 fn propose_proposed(
101 b: Linear<1, MAX_BYTES>,
102 m: Linear<2, { T::MaxFellows::get() }>,
103 p: Linear<1, { T::MaxProposals::get() }>,
104 ) -> Result<(), BenchmarkError> {
105 let bytes_in_storage = b + size_of::<Cid>() as u32 + 32;
106
107 let fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
109 let proposer = fellows[0].clone();
110
111 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows, vec![])?;
112
113 let threshold = m;
114 for i in 0..p - 1 {
116 let proposal: T::Proposal =
118 AllianceCall::<T, I>::set_rule { rule: rule(vec![i as u8; b as usize]) }.into();
119 Alliance::<T, I>::propose(
120 SystemOrigin::Signed(proposer.clone()).into(),
121 threshold,
122 Box::new(proposal),
123 bytes_in_storage,
124 )?;
125 }
126
127 let proposal: T::Proposal =
128 AllianceCall::<T, I>::set_rule { rule: rule(vec![p as u8; b as usize]) }.into();
129
130 #[extrinsic_call]
131 propose(
132 SystemOrigin::Signed(proposer.clone()),
133 threshold,
134 Box::new(proposal.clone()),
135 bytes_in_storage,
136 );
137
138 let proposal_hash = T::Hashing::hash_of(&proposal);
139 assert_eq!(T::ProposalProvider::proposal_of(proposal_hash), Some(proposal));
140 Ok(())
141 }
142
143 #[benchmark]
144 fn vote(m: Linear<5, { T::MaxFellows::get() }>) -> Result<(), BenchmarkError> {
145 let p = T::MaxProposals::get();
146 let b = MAX_BYTES;
147 let _bytes_in_storage = b + size_of::<Cid>() as u32 + 32;
148
149 let fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
151 let proposer = fellows[0].clone();
152
153 let members = fellows.clone();
154
155 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows, vec![])?;
156
157 let threshold = m - 1;
159
160 let mut last_hash = T::Hash::default();
162 for i in 0..p {
163 let proposal: T::Proposal =
165 AllianceCall::<T, I>::set_rule { rule: rule(vec![i as u8; b as usize]) }.into();
166 Alliance::<T, I>::propose(
167 SystemOrigin::Signed(proposer.clone()).into(),
168 threshold,
169 Box::new(proposal.clone()),
170 b,
171 )?;
172 last_hash = T::Hashing::hash_of(&proposal);
173 }
174
175 let index = p - 1;
176 for j in 0..m - 3 {
178 let voter = &members[j as usize];
179 Alliance::<T, I>::vote(
180 SystemOrigin::Signed(voter.clone()).into(),
181 last_hash,
182 index,
183 true,
184 )?;
185 }
186
187 let voter = members[m as usize - 3].clone();
188 Alliance::<T, I>::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash, index, true)?;
190
191 let approve = false;
193
194 let voter_key = frame_system::Account::<T>::hashed_key_for(&voter);
196 frame_benchmarking::benchmarking::add_to_whitelist(voter_key.into());
197
198 #[extrinsic_call]
199 _(SystemOrigin::Signed(voter), last_hash, index, approve);
200
201 Ok(())
203 }
204
205 #[benchmark]
206 fn close_early_disapproved(
207 m: Linear<4, { T::MaxFellows::get() }>,
208 p: Linear<1, { T::MaxProposals::get() }>,
209 ) -> Result<(), BenchmarkError> {
210 let bytes = 100;
211 let bytes_in_storage = bytes + size_of::<Cid>() as u32 + 32;
212
213 let fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
215
216 let members = fellows.clone();
217
218 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows, vec![])?;
219
220 let proposer = members[0].clone();
221 let voter = members[1].clone();
222
223 let threshold = m;
225
226 let mut last_hash = T::Hash::default();
228 for i in 0..p {
229 let proposal: T::Proposal =
231 AllianceCall::<T, I>::set_rule { rule: rule(vec![i as u8; bytes as usize]) }.into();
232 Alliance::<T, I>::propose(
233 SystemOrigin::Signed(proposer.clone()).into(),
234 threshold,
235 Box::new(proposal.clone()),
236 bytes_in_storage,
237 )?;
238 last_hash = T::Hashing::hash_of(&proposal);
239 assert_eq!(T::ProposalProvider::proposal_of(last_hash), Some(proposal));
240 }
241
242 let index = p - 1;
243 for j in 2..m - 1 {
245 let voter = &members[j as usize];
246 Alliance::<T, I>::vote(
247 SystemOrigin::Signed(voter.clone()).into(),
248 last_hash,
249 index,
250 true,
251 )?;
252 }
253
254 Alliance::<T, I>::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash, index, true)?;
256
257 Alliance::<T, I>::vote(
259 SystemOrigin::Signed(voter.clone()).into(),
260 last_hash,
261 index,
262 false,
263 )?;
264
265 let voter_key = frame_system::Account::<T>::hashed_key_for(&voter);
267 frame_benchmarking::benchmarking::add_to_whitelist(voter_key.into());
268
269 #[extrinsic_call]
270 close(SystemOrigin::Signed(voter), last_hash, index, Weight::MAX, bytes_in_storage);
271
272 assert_eq!(T::ProposalProvider::proposal_of(last_hash), None);
273 Ok(())
274 }
275
276 #[benchmark]
279 fn close_early_approved(
280 b: Linear<1, MAX_BYTES>,
281 m: Linear<4, { T::MaxFellows::get() }>,
282 p: Linear<1, { T::MaxProposals::get() }>,
283 ) -> Result<(), BenchmarkError> {
284 let bytes_in_storage = b + size_of::<Cid>() as u32 + 32;
285
286 let fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
288
289 let members = fellows.clone();
290
291 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows, vec![])?;
292
293 let proposer = members[0].clone();
294 let threshold = 2;
296
297 let mut last_hash = T::Hash::default();
299 for i in 0..p {
300 let proposal: T::Proposal =
302 AllianceCall::<T, I>::set_rule { rule: rule(vec![i as u8; b as usize]) }.into();
303 Alliance::<T, I>::propose(
304 SystemOrigin::Signed(proposer.clone()).into(),
305 threshold,
306 Box::new(proposal.clone()),
307 bytes_in_storage,
308 )?;
309 last_hash = T::Hashing::hash_of(&proposal);
310 assert_eq!(T::ProposalProvider::proposal_of(last_hash), Some(proposal));
311 }
312
313 let index = p - 1;
314 Alliance::<T, I>::vote(
317 SystemOrigin::Signed(proposer.clone()).into(),
318 last_hash,
319 index,
320 false,
321 )?;
322
323 for j in 2..m - 1 {
325 let voter = &members[j as usize];
326 Alliance::<T, I>::vote(
327 SystemOrigin::Signed(voter.clone()).into(),
328 last_hash,
329 index,
330 false,
331 )?;
332 }
333
334 Alliance::<T, I>::vote(
336 SystemOrigin::Signed(members[0].clone()).into(),
337 last_hash,
338 index,
339 true,
340 )?;
341
342 let voter = members[1].clone();
343 Alliance::<T, I>::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash, index, true)?;
345
346 #[extrinsic_call]
347 close(SystemOrigin::Signed(voter), last_hash, index, Weight::MAX, bytes_in_storage);
348
349 assert_eq!(T::ProposalProvider::proposal_of(last_hash), None);
350 Ok(())
351 }
352
353 #[benchmark]
354 fn close_disapproved(
355 m: Linear<2, { T::MaxFellows::get() }>,
356 p: Linear<1, { T::MaxProposals::get() }>,
357 ) -> Result<(), BenchmarkError> {
358 let bytes = 100;
359 let bytes_in_storage = bytes + size_of::<Cid>() as u32 + 32;
360
361 let fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
363
364 let members = fellows.clone();
365
366 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows, vec![])?;
367
368 let proposer = members[0].clone();
369 let voter = members[1].clone();
370
371 let threshold = m - 1;
373
374 let mut last_hash = T::Hash::default();
376 for i in 0..p {
377 let proposal: T::Proposal =
379 AllianceCall::<T, I>::set_rule { rule: rule(vec![i as u8; bytes as usize]) }.into();
380 Alliance::<T, I>::propose(
381 SystemOrigin::Signed(proposer.clone()).into(),
382 threshold,
383 Box::new(proposal.clone()),
384 bytes_in_storage,
385 )?;
386 last_hash = T::Hashing::hash_of(&proposal);
387 assert_eq!(T::ProposalProvider::proposal_of(last_hash), Some(proposal));
388 }
389
390 let index = p - 1;
391 for j in 2..m - 1 {
394 let voter = &members[j as usize];
395 Alliance::<T, I>::vote(
396 SystemOrigin::Signed(voter.clone()).into(),
397 last_hash,
398 index,
399 true,
400 )?;
401 }
402
403 Alliance::<T, I>::vote(
404 SystemOrigin::Signed(voter.clone()).into(),
405 last_hash,
406 index,
407 false,
408 )?;
409
410 System::<T>::set_block_number(BlockNumberFor::<T>::max_value());
411
412 #[extrinsic_call]
413 close(SystemOrigin::Signed(voter), last_hash, index, Weight::MAX, bytes_in_storage);
414
415 assert_eq!(T::ProposalProvider::proposal_of(last_hash), None);
417 Ok(())
418 }
419
420 #[benchmark]
423 fn close_approved(
424 b: Linear<1, MAX_BYTES>,
425 m: Linear<5, { T::MaxFellows::get() }>,
426 p: Linear<1, { T::MaxProposals::get() }>,
427 ) -> Result<(), BenchmarkError> {
428 let bytes_in_storage = b + size_of::<Cid>() as u32 + 32;
429
430 let fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
432
433 let members = fellows.clone();
434
435 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows, vec![])?;
436
437 let proposer = members[0].clone();
438 let threshold = 2;
440
441 let mut last_hash = T::Hash::default();
443 for i in 0..p {
444 let proposal: T::Proposal =
446 AllianceCall::<T, I>::set_rule { rule: rule(vec![i as u8; b as usize]) }.into();
447 Alliance::<T, I>::propose(
448 SystemOrigin::Signed(proposer.clone()).into(),
449 threshold,
450 Box::new(proposal.clone()),
451 bytes_in_storage,
452 )?;
453 last_hash = T::Hashing::hash_of(&proposal);
454 assert_eq!(T::ProposalProvider::proposal_of(last_hash), Some(proposal));
455 }
456
457 Alliance::<T, I>::vote(
459 SystemOrigin::Signed(proposer.clone()).into(),
460 last_hash,
461 p - 1,
462 true, )?;
464
465 let index = p - 1;
466 for j in 2..m - 1 {
469 let voter = &members[j as usize];
470 Alliance::<T, I>::vote(
471 SystemOrigin::Signed(voter.clone()).into(),
472 last_hash,
473 index,
474 false,
475 )?;
476 }
477
478 System::<T>::set_block_number(BlockNumberFor::<T>::max_value());
480
481 #[extrinsic_call]
482 close(SystemOrigin::Signed(proposer), last_hash, index, Weight::MAX, bytes_in_storage);
483
484 assert_eq!(T::ProposalProvider::proposal_of(last_hash), None);
485 Ok(())
486 }
487
488 #[benchmark]
489 fn init_members(
490 m: Linear<1, { T::MaxFellows::get() }>,
491 z: Linear<0, { T::MaxAllies::get() }>,
492 ) -> Result<(), BenchmarkError> {
493 let mut fellows = (0..m).map(fellow::<T, I>).collect::<Vec<_>>();
494 let mut allies = (0..z).map(ally::<T, I>).collect::<Vec<_>>();
495
496 #[extrinsic_call]
497 _(SystemOrigin::Root, fellows.clone(), allies.clone());
498
499 fellows.sort();
500 allies.sort();
501 assert_last_event::<T, I>(
502 Event::MembersInitialized { fellows: fellows.clone(), allies: allies.clone() }.into(),
503 );
504 assert_eq!(Members::<T, I>::get(MemberRole::Fellow), fellows);
505 assert_eq!(Members::<T, I>::get(MemberRole::Ally), allies);
506 Ok(())
507 }
508
509 #[benchmark]
510 fn disband(
511 x: Linear<1, { T::MaxFellows::get() }>,
512 y: Linear<0, { T::MaxAllies::get() }>,
513 z: Linear<0, { T::MaxMembersCount::get() / 2 }>,
514 ) -> Result<(), BenchmarkError> {
515 let fellows = (0..x).map(fellow::<T, I>).collect::<Vec<_>>();
516 let allies = (0..y).map(ally::<T, I>).collect::<Vec<_>>();
517 let witness = DisbandWitness { fellow_members: x, ally_members: y };
518
519 Alliance::<T, I>::init_members(SystemOrigin::Root.into(), fellows.clone(), allies.clone())?;
521
522 let deposit = T::AllyDeposit::get();
524 for member in fellows.iter().chain(allies.iter()).take(z as usize) {
525 T::Currency::reserve(&member, deposit)?;
526 <DepositOf<T, I>>::insert(&member, deposit);
527 }
528
529 assert_eq!(Alliance::<T, I>::voting_members_count(), x);
530 assert_eq!(Alliance::<T, I>::ally_members_count(), y);
531
532 #[extrinsic_call]
533 _(SystemOrigin::Root, witness);
534
535 assert_last_event::<T, I>(
536 Event::AllianceDisbanded {
537 fellow_members: x,
538 ally_members: y,
539 unreserved: cmp::min(z, x + y),
540 }
541 .into(),
542 );
543
544 assert!(!Alliance::<T, I>::is_initialized());
545 Ok(())
546 }
547
548 #[benchmark]
549 fn set_rule() -> Result<(), BenchmarkError> {
550 set_members::<T, I>();
551
552 let rule = rule(b"hello world");
553
554 let call = Call::<T, I>::set_rule { rule: rule.clone() };
555 let origin =
556 T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
557
558 #[block]
559 {
560 call.dispatch_bypass_filter(origin)?;
561 }
562 assert_eq!(Rule::<T, I>::get(), Some(rule.clone()));
563 assert_last_event::<T, I>(Event::NewRuleSet { rule }.into());
564 Ok(())
565 }
566
567 #[benchmark]
568 fn announce() -> Result<(), BenchmarkError> {
569 set_members::<T, I>();
570
571 let announcement = announcement(b"hello world");
572
573 let call = Call::<T, I>::announce { announcement: announcement.clone() };
574 let origin = T::AnnouncementOrigin::try_successful_origin()
575 .map_err(|_| BenchmarkError::Weightless)?;
576
577 #[block]
578 {
579 call.dispatch_bypass_filter(origin)?;
580 }
581
582 assert!(Announcements::<T, I>::get().contains(&announcement));
583 assert_last_event::<T, I>(Event::Announced { announcement }.into());
584 Ok(())
585 }
586
587 #[benchmark]
588 fn remove_announcement() -> Result<(), BenchmarkError> {
589 set_members::<T, I>();
590
591 let announcement = announcement(b"hello world");
592 let announcements: BoundedVec<_, T::MaxAnnouncementsCount> =
593 BoundedVec::try_from(vec![announcement.clone()]).unwrap();
594 Announcements::<T, I>::put(announcements);
595
596 let call = Call::<T, I>::remove_announcement { announcement: announcement.clone() };
597 let origin = T::AnnouncementOrigin::try_successful_origin()
598 .map_err(|_| BenchmarkError::Weightless)?;
599
600 #[block]
601 {
602 call.dispatch_bypass_filter(origin)?;
603 }
604
605 assert!(!Announcements::<T, I>::get().contains(&announcement));
606 assert_last_event::<T, I>(Event::AnnouncementRemoved { announcement }.into());
607 Ok(())
608 }
609
610 #[benchmark]
611 fn join_alliance() -> Result<(), BenchmarkError> {
612 set_members::<T, I>();
613
614 let outsider = outsider::<T, I>(1);
615 assert!(!Alliance::<T, I>::is_member(&outsider));
616 assert_eq!(DepositOf::<T, I>::get(&outsider), None);
617
618 #[extrinsic_call]
619 _(SystemOrigin::Signed(outsider.clone()));
620
621 assert!(Alliance::<T, I>::is_member_of(&outsider, MemberRole::Ally)); assert_eq!(DepositOf::<T, I>::get(&outsider), Some(T::AllyDeposit::get())); assert!(!Alliance::<T, I>::has_voting_rights(&outsider)); assert_last_event::<T, I>(
625 Event::NewAllyJoined {
626 ally: outsider,
627 nominator: None,
628 reserved: Some(T::AllyDeposit::get()),
629 }
630 .into(),
631 );
632 Ok(())
633 }
634
635 #[benchmark]
636 fn nominate_ally() -> Result<(), BenchmarkError> {
637 set_members::<T, I>();
638
639 let fellow1 = fellow::<T, I>(1);
640 assert!(Alliance::<T, I>::is_member_of(&fellow1, MemberRole::Fellow));
641
642 let outsider = outsider::<T, I>(1);
643 assert!(!Alliance::<T, I>::is_member(&outsider));
644 assert_eq!(DepositOf::<T, I>::get(&outsider), None);
645
646 let outsider_lookup = T::Lookup::unlookup(outsider.clone());
647
648 #[extrinsic_call]
649 _(SystemOrigin::Signed(fellow1.clone()), outsider_lookup);
650
651 assert!(Alliance::<T, I>::is_member_of(&outsider, MemberRole::Ally)); assert_eq!(DepositOf::<T, I>::get(&outsider), None); assert!(!Alliance::<T, I>::has_voting_rights(&outsider)); assert_last_event::<T, I>(
655 Event::NewAllyJoined { ally: outsider, nominator: Some(fellow1), reserved: None }
656 .into(),
657 );
658
659 Ok(())
660 }
661
662 #[benchmark]
663 fn elevate_ally() -> Result<(), BenchmarkError> {
664 set_members::<T, I>();
665
666 let ally1 = ally::<T, I>(1);
667 assert!(Alliance::<T, I>::is_ally(&ally1));
668
669 let ally1_lookup = T::Lookup::unlookup(ally1.clone());
670 let call = Call::<T, I>::elevate_ally { ally: ally1_lookup };
671 let origin = T::MembershipManager::try_successful_origin()
672 .map_err(|_| BenchmarkError::Weightless)?;
673
674 #[block]
675 {
676 call.dispatch_bypass_filter(origin)?;
677 }
678
679 assert!(!Alliance::<T, I>::is_ally(&ally1));
680 assert!(Alliance::<T, I>::has_voting_rights(&ally1));
681 assert_last_event::<T, I>(Event::AllyElevated { ally: ally1 }.into());
682 Ok(())
683 }
684
685 #[benchmark]
686 fn give_retirement_notice() -> Result<(), BenchmarkError> {
687 set_members::<T, I>();
688 let fellow2 = fellow::<T, I>(2);
689
690 assert!(Alliance::<T, I>::has_voting_rights(&fellow2));
691
692 #[extrinsic_call]
693 _(SystemOrigin::Signed(fellow2.clone()));
694
695 assert!(Alliance::<T, I>::is_member_of(&fellow2, MemberRole::Retiring));
696
697 assert_eq!(
698 RetiringMembers::<T, I>::get(&fellow2),
699 Some(System::<T>::block_number() + T::RetirementPeriod::get())
700 );
701 assert_last_event::<T, I>(Event::MemberRetirementPeriodStarted { member: fellow2 }.into());
702 Ok(())
703 }
704
705 #[benchmark]
706 fn retire() -> Result<(), BenchmarkError> {
707 set_members::<T, I>();
708
709 let fellow2 = fellow::<T, I>(2);
710 assert!(Alliance::<T, I>::has_voting_rights(&fellow2));
711
712 assert_eq!(
713 Alliance::<T, I>::give_retirement_notice(SystemOrigin::Signed(fellow2.clone()).into()),
714 Ok(())
715 );
716 System::<T>::set_block_number(System::<T>::block_number() + T::RetirementPeriod::get());
717
718 assert_eq!(DepositOf::<T, I>::get(&fellow2), Some(T::AllyDeposit::get()));
719
720 #[extrinsic_call]
721 _(SystemOrigin::Signed(fellow2.clone()));
722
723 assert!(!Alliance::<T, I>::is_member(&fellow2));
724 assert_eq!(DepositOf::<T, I>::get(&fellow2), None);
725 assert_last_event::<T, I>(
726 Event::MemberRetired { member: fellow2, unreserved: Some(T::AllyDeposit::get()) }
727 .into(),
728 );
729 Ok(())
730 }
731
732 #[benchmark]
733 fn kick_member() -> Result<(), BenchmarkError> {
734 set_members::<T, I>();
735
736 let fellow2 = fellow::<T, I>(2);
737 assert!(Alliance::<T, I>::is_member_of(&fellow2, MemberRole::Fellow));
738 assert_eq!(DepositOf::<T, I>::get(&fellow2), Some(T::AllyDeposit::get()));
739
740 let fellow2_lookup = T::Lookup::unlookup(fellow2.clone());
741 let call = Call::<T, I>::kick_member { who: fellow2_lookup };
742 let origin = T::MembershipManager::try_successful_origin()
743 .map_err(|_| BenchmarkError::Weightless)?;
744
745 #[block]
746 {
747 call.dispatch_bypass_filter(origin)?;
748 }
749
750 assert!(!Alliance::<T, I>::is_member(&fellow2));
751 assert_eq!(DepositOf::<T, I>::get(&fellow2), None);
752 assert_last_event::<T, I>(
753 Event::MemberKicked { member: fellow2, slashed: Some(T::AllyDeposit::get()) }.into(),
754 );
755 Ok(())
756 }
757
758 #[benchmark]
759 fn add_unscrupulous_items(
760 n: Linear<0, { T::MaxUnscrupulousItems::get() }>,
761 l: Linear<0, { T::MaxWebsiteUrlLength::get() }>,
762 ) -> Result<(), BenchmarkError> {
763 set_members::<T, I>();
764
765 let accounts = (0..n).map(|i| generate_unscrupulous_account::<T, I>(i)).collect::<Vec<_>>();
766 let websites = (0..n)
767 .map(|i| -> BoundedVec<u8, T::MaxWebsiteUrlLength> {
768 BoundedVec::try_from(vec![i as u8; l as usize]).unwrap()
769 })
770 .collect::<Vec<_>>();
771
772 let mut unscrupulous_list = Vec::with_capacity(accounts.len() + websites.len());
773 unscrupulous_list.extend(accounts.into_iter().map(UnscrupulousItem::AccountId));
774 unscrupulous_list.extend(websites.into_iter().map(UnscrupulousItem::Website));
775
776 let call = Call::<T, I>::add_unscrupulous_items { items: unscrupulous_list.clone() };
777 let origin = T::AnnouncementOrigin::try_successful_origin()
778 .map_err(|_| BenchmarkError::Weightless)?;
779
780 #[block]
781 {
782 call.dispatch_bypass_filter(origin)?;
783 }
784
785 assert_last_event::<T, I>(Event::UnscrupulousItemAdded { items: unscrupulous_list }.into());
786 Ok(())
787 }
788
789 #[benchmark]
790 fn remove_unscrupulous_items(
791 n: Linear<0, { T::MaxUnscrupulousItems::get() }>,
792 l: Linear<0, { T::MaxWebsiteUrlLength::get() }>,
793 ) -> Result<(), BenchmarkError> {
794 set_members::<T, I>();
795
796 let mut accounts =
797 (0..n).map(|i| generate_unscrupulous_account::<T, I>(i)).collect::<Vec<_>>();
798 accounts.sort();
799 let accounts: BoundedVec<_, T::MaxUnscrupulousItems> = accounts.try_into().unwrap();
800 UnscrupulousAccounts::<T, I>::put(accounts.clone());
801
802 let mut websites = (0..n)
803 .map(|i| -> BoundedVec<_, T::MaxWebsiteUrlLength> {
804 BoundedVec::try_from(vec![i as u8; l as usize]).unwrap()
805 })
806 .collect::<Vec<_>>();
807 websites.sort();
808 let websites: BoundedVec<_, T::MaxUnscrupulousItems> = websites.try_into().unwrap();
809 UnscrupulousWebsites::<T, I>::put(websites.clone());
810
811 let mut unscrupulous_list = Vec::with_capacity(accounts.len() + websites.len());
812 unscrupulous_list.extend(accounts.into_iter().map(UnscrupulousItem::AccountId));
813 unscrupulous_list.extend(websites.into_iter().map(UnscrupulousItem::Website));
814
815 let call = Call::<T, I>::remove_unscrupulous_items { items: unscrupulous_list.clone() };
816 let origin = T::AnnouncementOrigin::try_successful_origin()
817 .map_err(|_| BenchmarkError::Weightless)?;
818
819 #[block]
820 {
821 call.dispatch_bypass_filter(origin)?;
822 }
823
824 assert_last_event::<T, I>(
825 Event::UnscrupulousItemRemoved { items: unscrupulous_list }.into(),
826 );
827 Ok(())
828 }
829
830 #[benchmark]
831 fn abdicate_fellow_status() -> Result<(), BenchmarkError> {
832 set_members::<T, I>();
833 let fellow2 = fellow::<T, I>(2);
834 assert!(Alliance::<T, I>::has_voting_rights(&fellow2));
835
836 #[extrinsic_call]
837 _(SystemOrigin::Signed(fellow2.clone()));
838
839 assert_last_event::<T, I>(Event::FellowAbdicated { fellow: fellow2 }.into());
840 Ok(())
841 }
842
843 impl_benchmark_test_suite!(Alliance, crate::mock::new_bench_ext(), crate::mock::Test);
844}