// This file is part of Substrate. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Democracy pallet benchmarking. use super::*; use frame_benchmarking::v1::{account, benchmarks, whitelist_account, BenchmarkError}; use frame_support::{ assert_noop, assert_ok, traits::{Currency, EnsureOrigin, Get, OnInitialize, UnfilteredDispatchable}, }; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use sp_runtime::{traits::Bounded, BoundedVec}; use crate::Pallet as Democracy; const REFERENDUM_COUNT_HINT: u32 = 10; const SEED: u32 = 0; fn funded_account(name: &'static str, index: u32) -> T::AccountId { let caller: T::AccountId = account(name, index, SEED); // Give the account half of the maximum value of the `Balance` type. // Otherwise some transfers will fail with an overflow error. T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); caller } fn make_proposal(n: u32) -> BoundedCallOf { let call: CallOf = frame_system::Call::remark { remark: n.encode() }.into(); ::Preimages::bound(call).unwrap() } fn add_proposal(n: u32) -> Result { let other = funded_account::("proposer", n); let value = T::MinimumDeposit::get(); let proposal = make_proposal::(n); Democracy::::propose(RawOrigin::Signed(other).into(), proposal.clone(), value)?; Ok(proposal.hash()) } // add a referendum with a metadata. fn add_referendum(n: u32) -> (ReferendumIndex, T::Hash, T::Hash) { let vote_threshold = VoteThreshold::SimpleMajority; let proposal = make_proposal::(n); let hash = proposal.hash(); let index = Democracy::::inject_referendum( T::LaunchPeriod::get(), proposal, vote_threshold, 0u32.into(), ); let preimage_hash = note_preimage::(); MetadataOf::::insert(crate::MetadataOwner::Referendum(index), preimage_hash); (index, hash, preimage_hash) } fn account_vote(b: BalanceOf) -> AccountVote> { let v = Vote { aye: true, conviction: Conviction::Locked1x }; AccountVote::Standard { vote: v, balance: b } } fn assert_last_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_last_event(generic_event.into()); } fn assert_has_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_has_event(generic_event.into()); } // note a new preimage. fn note_preimage() -> T::Hash { use core::sync::atomic::{AtomicU8, Ordering}; use sp_std::borrow::Cow; // note a new preimage on every function invoke. static COUNTER: AtomicU8 = AtomicU8::new(0); let data = Cow::from(vec![COUNTER.fetch_add(1, Ordering::Relaxed)]); let hash = ::Preimages::note(data).unwrap(); hash } benchmarks! { propose { let p = T::MaxProposals::get(); for i in 0 .. (p - 1) { add_proposal::(i)?; } let caller = funded_account::("caller", 0); let proposal = make_proposal::(0); let value = T::MinimumDeposit::get(); whitelist_account!(caller); }: _(RawOrigin::Signed(caller), proposal, value) verify { assert_eq!(Democracy::::public_props().len(), p as usize, "Proposals not created."); } second { let caller = funded_account::("caller", 0); add_proposal::(0)?; // Create s existing "seconds" // we must reserve one deposit for the `proposal` and one for our benchmarked `second` call. for i in 0 .. T::MaxDeposits::get() - 2 { let seconder = funded_account::("seconder", i); Democracy::::second(RawOrigin::Signed(seconder).into(), 0)?; } let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; assert_eq!(deposits.0.len(), (T::MaxDeposits::get() - 1) as usize, "Seconds not recorded"); whitelist_account!(caller); }: _(RawOrigin::Signed(caller), 0) verify { let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; assert_eq!(deposits.0.len(), (T::MaxDeposits::get()) as usize, "`second` benchmark did not work"); } vote_new { let caller = funded_account::("caller", 0); let account_vote = account_vote::(100u32.into()); // We need to create existing direct votes for i in 0 .. T::MaxVotes::get() - 1 { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?; } let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), (T::MaxVotes::get() - 1) as usize, "Votes were not recorded."); let ref_index = add_referendum::(T::MaxVotes::get() - 1).0; whitelist_account!(caller); }: vote(RawOrigin::Signed(caller.clone()), ref_index, account_vote) verify { let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Vote was not recorded."); } vote_existing { let caller = funded_account::("caller", 0); let account_vote = account_vote::(100u32.into()); // We need to create existing direct votes for i in 0..T::MaxVotes::get() { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?; } let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Votes were not recorded."); // Change vote from aye to nay let nay = Vote { aye: false, conviction: Conviction::Locked1x }; let new_vote = AccountVote::Standard { vote: nay, balance: 1000u32.into() }; let ref_index = Democracy::::referendum_count() - 1; // This tests when a user changes a vote whitelist_account!(caller); }: vote(RawOrigin::Signed(caller.clone()), ref_index, new_vote) verify { let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Vote was incorrectly added"); let referendum_info = Democracy::::referendum_info(ref_index) .ok_or("referendum doesn't exist")?; let tally = match referendum_info { ReferendumInfo::Ongoing(r) => r.tally, _ => return Err("referendum not ongoing".into()), }; assert_eq!(tally.nays, 1000u32.into(), "changed vote was not recorded"); } emergency_cancel { let origin = T::CancellationOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let (ref_index, _, preimage_hash) = add_referendum::(0); assert_ok!(Democracy::::referendum_status(ref_index)); }: _(origin, ref_index) verify { // Referendum has been canceled assert_noop!( Democracy::::referendum_status(ref_index), Error::::ReferendumInvalid, ); assert_last_event::(crate::Event::MetadataCleared { owner: MetadataOwner::Referendum(ref_index), hash: preimage_hash, }.into()); } blacklist { // Place our proposal at the end to make sure it's worst case. for i in 0 .. T::MaxProposals::get() - 1 { add_proposal::(i)?; } // We should really add a lot of seconds here, but we're not doing it elsewhere. // Add a referendum of our proposal. let (ref_index, hash, preimage_hash) = add_referendum::(0); assert_ok!(Democracy::::referendum_status(ref_index)); // Place our proposal in the external queue, too. assert_ok!(Democracy::::external_propose( T::ExternalOrigin::try_successful_origin() .expect("ExternalOrigin has no successful origin required for the benchmark"), make_proposal::(0) )); let origin = T::BlacklistOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; }: _(origin, hash, Some(ref_index)) verify { // Referendum has been canceled assert_noop!( Democracy::::referendum_status(ref_index), Error::::ReferendumInvalid ); assert_has_event::(crate::Event::MetadataCleared { owner: MetadataOwner::Referendum(ref_index), hash: preimage_hash, }.into()); } // Worst case scenario, we external propose a previously blacklisted proposal external_propose { let origin = T::ExternalOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let proposal = make_proposal::(0); // Add proposal to blacklist with block number 0 let addresses: BoundedVec<_, _> = (0..(T::MaxBlacklisted::get() - 1)) .into_iter() .map(|i| account::("blacklist", i, SEED)) .collect::>() .try_into() .unwrap(); Blacklist::::insert(proposal.hash(), (BlockNumberFor::::zero(), addresses)); }: _(origin, proposal) verify { // External proposal created ensure!(>::exists(), "External proposal didn't work"); } external_propose_majority { let origin = T::ExternalMajorityOrigin::try_successful_origin() .map_err(|_| BenchmarkError::Weightless)?; let proposal = make_proposal::(0); }: _(origin, proposal) verify { // External proposal created ensure!(>::exists(), "External proposal didn't work"); } external_propose_default { let origin = T::ExternalDefaultOrigin::try_successful_origin() .map_err(|_| BenchmarkError::Weightless)?; let proposal = make_proposal::(0); }: _(origin, proposal) verify { // External proposal created ensure!(>::exists(), "External proposal didn't work"); } fast_track { let origin_propose = T::ExternalDefaultOrigin::try_successful_origin() .expect("ExternalDefaultOrigin has no successful origin required for the benchmark"); let proposal = make_proposal::(0); let proposal_hash = proposal.hash(); Democracy::::external_propose_default(origin_propose.clone(), proposal)?; // Set metadata to the external proposal. let preimage_hash = note_preimage::(); assert_ok!(Democracy::::set_metadata( origin_propose, MetadataOwner::External, Some(preimage_hash))); // NOTE: Instant origin may invoke a little bit more logic, but may not always succeed. let origin_fast_track = T::FastTrackOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let voting_period = T::FastTrackVotingPeriod::get(); let delay = 0u32; }: _(origin_fast_track, proposal_hash, voting_period, delay.into()) verify { assert_eq!(Democracy::::referendum_count(), 1, "referendum not created"); assert_last_event::(crate::Event::MetadataTransferred { prev_owner: MetadataOwner::External, owner: MetadataOwner::Referendum(0), hash: preimage_hash, }.into()); } veto_external { let proposal = make_proposal::(0); let proposal_hash = proposal.hash(); let origin_propose = T::ExternalDefaultOrigin::try_successful_origin() .expect("ExternalDefaultOrigin has no successful origin required for the benchmark"); Democracy::::external_propose_default(origin_propose.clone(), proposal)?; let preimage_hash = note_preimage::(); assert_ok!(Democracy::::set_metadata( origin_propose, MetadataOwner::External, Some(preimage_hash)) ); let mut vetoers: BoundedVec = Default::default(); for i in 0 .. (T::MaxBlacklisted::get() - 1) { vetoers.try_push(account::("vetoer", i, SEED)).unwrap(); } vetoers.sort(); Blacklist::::insert(proposal_hash, (BlockNumberFor::::zero(), vetoers)); let origin = T::VetoOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; ensure!(NextExternal::::get().is_some(), "no external proposal"); }: _(origin, proposal_hash) verify { assert!(NextExternal::::get().is_none()); let (_, new_vetoers) = >::get(&proposal_hash).ok_or("no blacklist")?; assert_eq!(new_vetoers.len(), T::MaxBlacklisted::get() as usize, "vetoers not added"); } cancel_proposal { // Place our proposal at the end to make sure it's worst case. for i in 0 .. T::MaxProposals::get() { add_proposal::(i)?; } // Add metadata to the first proposal. let proposer = funded_account::("proposer", 0); let preimage_hash = note_preimage::(); assert_ok!(Democracy::::set_metadata( RawOrigin::Signed(proposer).into(), MetadataOwner::Proposal(0), Some(preimage_hash))); let cancel_origin = T::CancelProposalOrigin::try_successful_origin() .map_err(|_| BenchmarkError::Weightless)?; }: _(cancel_origin, 0) verify { assert_last_event::(crate::Event::MetadataCleared { owner: MetadataOwner::Proposal(0), hash: preimage_hash, }.into()); } cancel_referendum { let (ref_index, _, preimage_hash) = add_referendum::(0); }: _(RawOrigin::Root, ref_index) verify { assert_last_event::(crate::Event::MetadataCleared { owner: MetadataOwner::Referendum(0), hash: preimage_hash, }.into()); } #[extra] on_initialize_external { let r in 0 .. REFERENDUM_COUNT_HINT; for i in 0..r { add_referendum::(i); } assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); // Launch external LastTabledWasExternal::::put(false); let origin = T::ExternalMajorityOrigin::try_successful_origin() .map_err(|_| BenchmarkError::Weightless)?; let proposal = make_proposal::(r); let call = Call::::external_propose_majority { proposal }; call.dispatch_bypass_filter(origin)?; // External proposal created ensure!(>::exists(), "External proposal didn't work"); let block_number = T::LaunchPeriod::get(); }: { Democracy::::on_initialize(block_number) } verify { // One extra because of next external assert_eq!(Democracy::::referendum_count(), r + 1, "referenda not created"); ensure!(!>::exists(), "External wasn't taken"); // All but the new next external should be finished for i in 0 .. r { if let Some(value) = ReferendumInfoOf::::get(i) { match value { ReferendumInfo::Finished { .. } => (), ReferendumInfo::Ongoing(_) => return Err("Referendum was not finished".into()), } } } } #[extra] on_initialize_public { let r in 0 .. (T::MaxVotes::get() - 1); for i in 0..r { add_referendum::(i); } assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); // Launch public assert!(add_proposal::(r).is_ok(), "proposal not created"); LastTabledWasExternal::::put(true); let block_number = T::LaunchPeriod::get(); }: { Democracy::::on_initialize(block_number) } verify { // One extra because of next public assert_eq!(Democracy::::referendum_count(), r + 1, "proposal not accepted"); // All should be finished for i in 0 .. r { if let Some(value) = ReferendumInfoOf::::get(i) { match value { ReferendumInfo::Finished { .. } => (), ReferendumInfo::Ongoing(_) => return Err("Referendum was not finished".into()), } } } } // No launch no maturing referenda. on_initialize_base { let r in 0 .. (T::MaxVotes::get() - 1); for i in 0..r { add_referendum::(i); } for (key, mut info) in ReferendumInfoOf::::iter() { if let ReferendumInfo::Ongoing(ref mut status) = info { status.end += 100u32.into(); } ReferendumInfoOf::::insert(key, info); } assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); }: { Democracy::::on_initialize(1u32.into()) } verify { // All should be on going for i in 0 .. r { if let Some(value) = ReferendumInfoOf::::get(i) { match value { ReferendumInfo::Finished { .. } => return Err("Referendum has been finished".into()), ReferendumInfo::Ongoing(_) => (), } } } } on_initialize_base_with_launch_period { let r in 0 .. (T::MaxVotes::get() - 1); for i in 0..r { add_referendum::(i); } for (key, mut info) in ReferendumInfoOf::::iter() { if let ReferendumInfo::Ongoing(ref mut status) = info { status.end += 100u32.into(); } ReferendumInfoOf::::insert(key, info); } assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); let block_number = T::LaunchPeriod::get(); }: { Democracy::::on_initialize(block_number) } verify { // All should be on going for i in 0 .. r { if let Some(value) = ReferendumInfoOf::::get(i) { match value { ReferendumInfo::Finished { .. } => return Err("Referendum has been finished".into()), ReferendumInfo::Ongoing(_) => (), } } } } delegate { let r in 0 .. (T::MaxVotes::get() - 1); let initial_balance: BalanceOf = 100u32.into(); let delegated_balance: BalanceOf = 1000u32.into(); let caller = funded_account::("caller", 0); // Caller will initially delegate to `old_delegate` let old_delegate: T::AccountId = funded_account::("old_delegate", r); let old_delegate_lookup = T::Lookup::unlookup(old_delegate.clone()); Democracy::::delegate( RawOrigin::Signed(caller.clone()).into(), old_delegate_lookup, Conviction::Locked1x, delegated_balance, )?; let (target, balance) = match VotingOf::::get(&caller) { Voting::Delegating { target, balance, .. } => (target, balance), _ => return Err("Votes are not direct".into()), }; assert_eq!(target, old_delegate, "delegation target didn't work"); assert_eq!(balance, delegated_balance, "delegation balance didn't work"); // Caller will now switch to `new_delegate` let new_delegate: T::AccountId = funded_account::("new_delegate", r); let new_delegate_lookup = T::Lookup::unlookup(new_delegate.clone()); let account_vote = account_vote::(initial_balance); // We need to create existing direct votes for the `new_delegate` for i in 0..r { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(new_delegate.clone()).into(), ref_index, account_vote)?; } let votes = match VotingOf::::get(&new_delegate) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), r as usize, "Votes were not recorded."); whitelist_account!(caller); }: _(RawOrigin::Signed(caller.clone()), new_delegate_lookup, Conviction::Locked1x, delegated_balance) verify { let (target, balance) = match VotingOf::::get(&caller) { Voting::Delegating { target, balance, .. } => (target, balance), _ => return Err("Votes are not direct".into()), }; assert_eq!(target, new_delegate, "delegation target didn't work"); assert_eq!(balance, delegated_balance, "delegation balance didn't work"); let delegations = match VotingOf::::get(&new_delegate) { Voting::Direct { delegations, .. } => delegations, _ => return Err("Votes are not direct".into()), }; assert_eq!(delegations.capital, delegated_balance, "delegation was not recorded."); } undelegate { let r in 0 .. (T::MaxVotes::get() - 1); let initial_balance: BalanceOf = 100u32.into(); let delegated_balance: BalanceOf = 1000u32.into(); let caller = funded_account::("caller", 0); // Caller will delegate let the_delegate: T::AccountId = funded_account::("delegate", r); let the_delegate_lookup = T::Lookup::unlookup(the_delegate.clone()); Democracy::::delegate( RawOrigin::Signed(caller.clone()).into(), the_delegate_lookup, Conviction::Locked1x, delegated_balance, )?; let (target, balance) = match VotingOf::::get(&caller) { Voting::Delegating { target, balance, .. } => (target, balance), _ => return Err("Votes are not direct".into()), }; assert_eq!(target, the_delegate, "delegation target didn't work"); assert_eq!(balance, delegated_balance, "delegation balance didn't work"); // We need to create votes direct votes for the `delegate` let account_vote = account_vote::(initial_balance); for i in 0..r { let ref_index = add_referendum::(i).0; Democracy::::vote( RawOrigin::Signed(the_delegate.clone()).into(), ref_index, account_vote )?; } let votes = match VotingOf::::get(&the_delegate) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), r as usize, "Votes were not recorded."); whitelist_account!(caller); }: _(RawOrigin::Signed(caller.clone())) verify { // Voting should now be direct match VotingOf::::get(&caller) { Voting::Direct { .. } => (), _ => return Err("undelegation failed".into()), } } clear_public_proposals { add_proposal::(0)?; }: _(RawOrigin::Root) // Test when unlock will remove locks unlock_remove { let r in 0 .. (T::MaxVotes::get() - 1); let locker = funded_account::("locker", 0); let locker_lookup = T::Lookup::unlookup(locker.clone()); // Populate votes so things are locked let base_balance: BalanceOf = 100u32.into(); let small_vote = account_vote::(base_balance); // Vote and immediately unvote for i in 0 .. r { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(locker.clone()).into(), ref_index, small_vote)?; Democracy::::remove_vote(RawOrigin::Signed(locker.clone()).into(), ref_index)?; } let caller = funded_account::("caller", 0); whitelist_account!(caller); }: unlock(RawOrigin::Signed(caller), locker_lookup) verify { // Note that we may want to add a `get_lock` api to actually verify let voting = VotingOf::::get(&locker); assert_eq!(voting.locked_balance(), BalanceOf::::zero()); } // Test when unlock will set a new value unlock_set { let r in 0 .. (T::MaxVotes::get() - 1); let locker = funded_account::("locker", 0); let locker_lookup = T::Lookup::unlookup(locker.clone()); // Populate votes so things are locked let base_balance: BalanceOf = 100u32.into(); let small_vote = account_vote::(base_balance); for i in 0 .. r { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(locker.clone()).into(), ref_index, small_vote)?; } // Create a big vote so lock increases let big_vote = account_vote::(base_balance * 10u32.into()); let ref_index = add_referendum::(r).0; Democracy::::vote(RawOrigin::Signed(locker.clone()).into(), ref_index, big_vote)?; let votes = match VotingOf::::get(&locker) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), (r + 1) as usize, "Votes were not recorded."); let voting = VotingOf::::get(&locker); assert_eq!(voting.locked_balance(), base_balance * 10u32.into()); Democracy::::remove_vote(RawOrigin::Signed(locker.clone()).into(), ref_index)?; let caller = funded_account::("caller", 0); whitelist_account!(caller); }: unlock(RawOrigin::Signed(caller), locker_lookup) verify { let votes = match VotingOf::::get(&locker) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), r as usize, "Vote was not removed"); let voting = VotingOf::::get(&locker); // Note that we may want to add a `get_lock` api to actually verify assert_eq!(voting.locked_balance(), if r > 0 { base_balance } else { 0u32.into() }); } remove_vote { let r in 1 .. T::MaxVotes::get(); let caller = funded_account::("caller", 0); let account_vote = account_vote::(100u32.into()); for i in 0 .. r { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?; } let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), r as usize, "Votes not created"); let ref_index = r - 1; whitelist_account!(caller); }: _(RawOrigin::Signed(caller.clone()), ref_index) verify { let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), (r - 1) as usize, "Vote was not removed"); } // Worst case is when target == caller and referendum is ongoing remove_other_vote { let r in 1 .. T::MaxVotes::get(); let caller = funded_account::("caller", r); let caller_lookup = T::Lookup::unlookup(caller.clone()); let account_vote = account_vote::(100u32.into()); for i in 0 .. r { let ref_index = add_referendum::(i).0; Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?; } let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), r as usize, "Votes not created"); let ref_index = r - 1; whitelist_account!(caller); }: _(RawOrigin::Signed(caller.clone()), caller_lookup, ref_index) verify { let votes = match VotingOf::::get(&caller) { Voting::Direct { votes, .. } => votes, _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), (r - 1) as usize, "Vote was not removed"); } set_external_metadata { let origin = T::ExternalOrigin::try_successful_origin() .expect("ExternalOrigin has no successful origin required for the benchmark"); assert_ok!( Democracy::::external_propose(origin.clone(), make_proposal::(0)) ); let owner = MetadataOwner::External; let hash = note_preimage::(); }: set_metadata(origin, owner.clone(), Some(hash)) verify { assert_last_event::(crate::Event::MetadataSet { owner, hash, }.into()); } clear_external_metadata { let origin = T::ExternalOrigin::try_successful_origin() .expect("ExternalOrigin has no successful origin required for the benchmark"); assert_ok!( Democracy::::external_propose(origin.clone(), make_proposal::(0)) ); let owner = MetadataOwner::External; let proposer = funded_account::("proposer", 0); let hash = note_preimage::(); assert_ok!(Democracy::::set_metadata(origin.clone(), owner.clone(), Some(hash))); }: set_metadata(origin, owner.clone(), None) verify { assert_last_event::(crate::Event::MetadataCleared { owner, hash, }.into()); } set_proposal_metadata { // Place our proposal at the end to make sure it's worst case. for i in 0 .. T::MaxProposals::get() { add_proposal::(i)?; } let owner = MetadataOwner::Proposal(0); let proposer = funded_account::("proposer", 0); let hash = note_preimage::(); }: set_metadata(RawOrigin::Signed(proposer).into(), owner.clone(), Some(hash)) verify { assert_last_event::(crate::Event::MetadataSet { owner, hash, }.into()); } clear_proposal_metadata { // Place our proposal at the end to make sure it's worst case. for i in 0 .. T::MaxProposals::get() { add_proposal::(i)?; } let proposer = funded_account::("proposer", 0); let owner = MetadataOwner::Proposal(0); let hash = note_preimage::(); assert_ok!(Democracy::::set_metadata( RawOrigin::Signed(proposer.clone()).into(), owner.clone(), Some(hash))); }: set_metadata(RawOrigin::Signed(proposer).into(), owner.clone(), None) verify { assert_last_event::(crate::Event::MetadataCleared { owner, hash, }.into()); } set_referendum_metadata { // create not ongoing referendum. ReferendumInfoOf::::insert( 0, ReferendumInfo::Finished { end: BlockNumberFor::::zero(), approved: true }, ); let owner = MetadataOwner::Referendum(0); let caller = funded_account::("caller", 0); let hash = note_preimage::(); }: set_metadata(RawOrigin::Root.into(), owner.clone(), Some(hash)) verify { assert_last_event::(crate::Event::MetadataSet { owner, hash, }.into()); } clear_referendum_metadata { // create not ongoing referendum. ReferendumInfoOf::::insert( 0, ReferendumInfo::Finished { end: BlockNumberFor::::zero(), approved: true }, ); let owner = MetadataOwner::Referendum(0); let hash = note_preimage::(); MetadataOf::::insert(owner.clone(), hash); let caller = funded_account::("caller", 0); }: set_metadata(RawOrigin::Signed(caller).into(), owner.clone(), None) verify { assert_last_event::(crate::Event::MetadataCleared { owner, hash, }.into()); } impl_benchmark_test_suite!( Democracy, crate::tests::new_test_ext(), crate::tests::Test ); }