mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 01:41:09 +00:00
Bounties (#5715)
* add some compact annotation * implement bounties for treasury * fix test build * remove some duplicated code * fix build * add tests * fix build * fix tests * rename * merge deposit byte fee * add comments * refactor storage * support sub bounty * emit BountyBecameActive when sub bounty is created * able to contribute bounty * allow curator to cancel bounty * remove bounty contribution * implement bounty expiry * Able to extend bounty * fix build and update tests * create sub bounty test * add more tests * add benchmarks for bounties * fix build * line width * fix benchmarking test * update trait * fix typo * Update lib.rs Missing documentation on Bounties added on this change. Please check the definitions of `propose_bounty` and `create_bounty`. * update docs * add MaximumSubBountyDepth * put BountyValueMinimum into storage * rework bount depth * split on_initialize benchmarks * remove components from constant functions * Update weight integration into treasury * Update reject proposal read/writes * fix weight calculation * Ignore weights with 0 factor * Remove 0 multipliers * add some docs * allow unused for generated code * line width * allow RejectOrigin to cancel a pending payout bounty * require BountyValueMinimum > ED * make BountyValueMinimum configurable by chain spec * remove sub-bounty features * update curator * accept curator * unassign and cancel * fix tests * new tests * Update lib.rs - Include on `Assign_curator`, `accept_curator` and `unassign_curator` on Bounties Protocol Section - Include curator fee and curator deposit definitions on Terminology - Update intro. * fix test * update extend_bounty_expiry * fix benchmarking * add new benchmarking code * add docs * fix tests * Update benchmarking.rs * Make BountyValueMinimum a trait config instead of stroage value * fix runtime build * Update weights * Update default_weights.rs * update weights * update * update comments * unreserve curator fee * update tests * update benchmarks * fix curator deposit handling * trigger CI * fix benchmarking * use append instead of mutate push * additional noop tests * improve fee hanlding. update event docs * RejectOrigin to unassign * update bounty cancel logic * use Zero::zero() over 0.into() * fix tests * fix benchmarks * proposed fixes to bounties * fix tests * fix benchmarks * update weightinfo * use closure * fix compile * update weights Co-authored-by: RRTTI <raul@ost.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -47,7 +47,7 @@ fn setup_proposal<T: Trait<I>, I: Instance>(u: u32) -> (
|
||||
fn setup_awesome<T: Trait<I>, I: Instance>(length: u32) -> (T::AccountId, Vec<u8>, T::AccountId) {
|
||||
let caller = whitelisted_caller();
|
||||
let value = T::TipReportDepositBase::get()
|
||||
+ T::TipReportDepositPerByte::get() * length.into()
|
||||
+ T::DataDepositPerByte::get() * length.into()
|
||||
+ T::Currency::minimum_balance();
|
||||
let _ = T::Currency::make_free_balance_be(&caller, value);
|
||||
let reason = vec![0; length as usize];
|
||||
@@ -109,6 +109,58 @@ fn create_approved_proposals<T: Trait<I>, I: Instance>(n: u32) -> Result<(), &'s
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Create bounties that are approved for use in `on_initialize`.
|
||||
fn create_approved_bounties<T: Trait<I>, I: Instance>(n: u32) -> Result<(), &'static str> {
|
||||
for i in 0 .. n {
|
||||
let (caller, _curator, _fee, value, reason) = setup_bounty::<T, I>(i, MAX_BYTES);
|
||||
Treasury::<T, I>::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?;
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
Treasury::<T, I>::approve_bounty(RawOrigin::Root.into(), bounty_id)?;
|
||||
}
|
||||
ensure!(BountyApprovals::<I>::get().len() == n as usize, "Not all bounty approved");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Create the pre-requisite information needed to create a treasury `propose_bounty`.
|
||||
fn setup_bounty<T: Trait<I>, I: Instance>(u: u32, d: u32) -> (
|
||||
T::AccountId,
|
||||
T::AccountId,
|
||||
BalanceOf<T, I>,
|
||||
BalanceOf<T, I>,
|
||||
Vec<u8>,
|
||||
) {
|
||||
let caller = account("caller", u, SEED);
|
||||
let value: BalanceOf<T, I> = T::Currency::minimum_balance().saturating_mul(100.into());
|
||||
let fee = T::Currency::minimum_balance().saturating_mul(2.into());
|
||||
let deposit = T::BountyDepositBase::get() + T::DataDepositPerByte::get() * MAX_BYTES.into();
|
||||
let _ = T::Currency::make_free_balance_be(&caller, deposit);
|
||||
let curator = account("curator", u, SEED);
|
||||
let _ = T::Currency::make_free_balance_be(&curator, fee / 2.into());
|
||||
let reason = vec![0; d as usize];
|
||||
(caller, curator, fee, value, reason)
|
||||
}
|
||||
|
||||
fn create_bounty<T: Trait<I>, I: Instance>() -> Result<(
|
||||
<T::Lookup as StaticLookup>::Source,
|
||||
BountyIndex,
|
||||
), &'static str> {
|
||||
let (caller, curator, fee, value, reason) = setup_bounty::<T, I>(0, MAX_BYTES);
|
||||
let curator_lookup = T::Lookup::unlookup(curator.clone());
|
||||
Treasury::<T, I>::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?;
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
Treasury::<T, I>::approve_bounty(RawOrigin::Root.into(), bounty_id)?;
|
||||
Treasury::<T, I>::on_initialize(T::BlockNumber::zero());
|
||||
Treasury::<T, I>::propose_curator(RawOrigin::Root.into(), bounty_id, curator_lookup.clone(), fee)?;
|
||||
Treasury::<T, I>::accept_curator(RawOrigin::Signed(curator).into(), bounty_id)?;
|
||||
Ok((curator_lookup, bounty_id))
|
||||
}
|
||||
|
||||
fn setup_pod_account<T: Trait<I>, I: Instance>() {
|
||||
let pot_account = Treasury::<T, I>::account_id();
|
||||
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
||||
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
||||
}
|
||||
|
||||
const MAX_BYTES: u32 = 16384;
|
||||
const MAX_TIPPERS: u32 = 100;
|
||||
|
||||
@@ -116,16 +168,14 @@ benchmarks_instance! {
|
||||
_ { }
|
||||
|
||||
propose_spend {
|
||||
let u in 0 .. 1000;
|
||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(u);
|
||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(SEED);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: _(RawOrigin::Signed(caller), value, beneficiary_lookup)
|
||||
|
||||
reject_proposal {
|
||||
let u in 0 .. 1000;
|
||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(u);
|
||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(SEED);
|
||||
Treasury::<T, _>::propose_spend(
|
||||
RawOrigin::Signed(caller).into(),
|
||||
value,
|
||||
@@ -135,8 +185,7 @@ benchmarks_instance! {
|
||||
}: _(RawOrigin::Root, proposal_id)
|
||||
|
||||
approve_proposal {
|
||||
let u in 0 .. 1000;
|
||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(u);
|
||||
let (caller, value, beneficiary_lookup) = setup_proposal::<T, _>(SEED);
|
||||
Treasury::<T, _>::propose_spend(
|
||||
RawOrigin::Signed(caller).into(),
|
||||
value,
|
||||
@@ -202,9 +251,7 @@ benchmarks_instance! {
|
||||
let t in 1 .. MAX_TIPPERS;
|
||||
|
||||
// Make sure pot is funded
|
||||
let pot_account = Treasury::<T, _>::account_id();
|
||||
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
||||
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
||||
setup_pod_account::<T, _>();
|
||||
|
||||
// Set up a new tip proposal
|
||||
let (member, reason, beneficiary, value) = setup_tip::<T, _>(0, t)?;
|
||||
@@ -228,15 +275,112 @@ benchmarks_instance! {
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: _(RawOrigin::Signed(caller), hash)
|
||||
|
||||
on_initialize {
|
||||
propose_bounty {
|
||||
let d in 0 .. MAX_BYTES;
|
||||
|
||||
let (caller, curator, fee, value, description) = setup_bounty::<T, _>(0, d);
|
||||
}: _(RawOrigin::Signed(caller), value, description)
|
||||
|
||||
approve_bounty {
|
||||
let (caller, curator, fee, value, reason) = setup_bounty::<T, _>(0, MAX_BYTES);
|
||||
Treasury::<T, _>::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?;
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
}: _(RawOrigin::Root, bounty_id)
|
||||
|
||||
propose_curator {
|
||||
setup_pod_account::<T, _>();
|
||||
let (caller, curator, fee, value, reason) = setup_bounty::<T, _>(0, MAX_BYTES);
|
||||
let curator_lookup = T::Lookup::unlookup(curator.clone());
|
||||
Treasury::<T, _>::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?;
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
Treasury::<T, _>::approve_bounty(RawOrigin::Root.into(), bounty_id)?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
}: _(RawOrigin::Root, bounty_id, curator_lookup, fee)
|
||||
|
||||
// Worst case when curator is inactive and any sender unassigns the curator.
|
||||
unassign_curator {
|
||||
setup_pod_account::<T, _>();
|
||||
let (curator_lookup, bounty_id) = create_bounty::<T, _>()?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
frame_system::Module::<T>::set_block_number(T::BountyUpdatePeriod::get() + 1.into());
|
||||
let caller = whitelisted_caller();
|
||||
}: _(RawOrigin::Signed(caller), bounty_id)
|
||||
|
||||
accept_curator {
|
||||
setup_pod_account::<T, _>();
|
||||
let (caller, curator, fee, value, reason) = setup_bounty::<T, _>(0, MAX_BYTES);
|
||||
let curator_lookup = T::Lookup::unlookup(curator.clone());
|
||||
Treasury::<T, _>::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?;
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
Treasury::<T, _>::approve_bounty(RawOrigin::Root.into(), bounty_id)?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
Treasury::<T, _>::propose_curator(RawOrigin::Root.into(), bounty_id, curator_lookup, fee)?;
|
||||
}: _(RawOrigin::Signed(curator), bounty_id)
|
||||
|
||||
award_bounty {
|
||||
setup_pod_account::<T, _>();
|
||||
let (curator_lookup, bounty_id) = create_bounty::<T, _>()?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
let curator = T::Lookup::lookup(curator_lookup)?;
|
||||
let beneficiary = T::Lookup::unlookup(account("beneficiary", 0, SEED));
|
||||
}: _(RawOrigin::Signed(curator), bounty_id, beneficiary)
|
||||
|
||||
claim_bounty {
|
||||
setup_pod_account::<T, _>();
|
||||
let (curator_lookup, bounty_id) = create_bounty::<T, _>()?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
let curator = T::Lookup::lookup(curator_lookup)?;
|
||||
|
||||
let beneficiary = T::Lookup::unlookup(account("beneficiary", 0, SEED));
|
||||
Treasury::<T, _>::award_bounty(RawOrigin::Signed(curator.clone()).into(), bounty_id, beneficiary)?;
|
||||
|
||||
frame_system::Module::<T>::set_block_number(T::BountyDepositPayoutDelay::get());
|
||||
|
||||
}: _(RawOrigin::Signed(curator), bounty_id)
|
||||
|
||||
close_bounty_proposed {
|
||||
setup_pod_account::<T, _>();
|
||||
let (caller, curator, fee, value, reason) = setup_bounty::<T, _>(0, 0);
|
||||
Treasury::<T, _>::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?;
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
}: close_bounty(RawOrigin::Root, bounty_id)
|
||||
|
||||
close_bounty_active {
|
||||
setup_pod_account::<T, _>();
|
||||
let (curator_lookup, bounty_id) = create_bounty::<T, _>()?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
}: close_bounty(RawOrigin::Root, bounty_id)
|
||||
|
||||
extend_bounty_expiry {
|
||||
setup_pod_account::<T, _>();
|
||||
let (curator_lookup, bounty_id) = create_bounty::<T, _>()?;
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
|
||||
let bounty_id = BountyCount::<I>::get() - 1;
|
||||
let curator = T::Lookup::lookup(curator_lookup)?;
|
||||
}: _(RawOrigin::Signed(curator), bounty_id, Vec::new())
|
||||
|
||||
on_initialize_proposals {
|
||||
let p in 0 .. 100;
|
||||
let pot_account = Treasury::<T, _>::account_id();
|
||||
let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000.into());
|
||||
let _ = T::Currency::make_free_balance_be(&pot_account, value);
|
||||
setup_pod_account::<T, _>();
|
||||
create_approved_proposals::<T, _>(p)?;
|
||||
}: {
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
}
|
||||
|
||||
on_initialize_bounties {
|
||||
let b in 0 .. 100;
|
||||
setup_pod_account::<T, _>();
|
||||
create_approved_bounties::<T, _>(b)?;
|
||||
}: {
|
||||
Treasury::<T, _>::on_initialize(T::BlockNumber::zero());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -256,7 +400,18 @@ mod tests {
|
||||
assert_ok!(test_benchmark_tip_new::<Test>());
|
||||
assert_ok!(test_benchmark_tip::<Test>());
|
||||
assert_ok!(test_benchmark_close_tip::<Test>());
|
||||
assert_ok!(test_benchmark_on_initialize::<Test>());
|
||||
assert_ok!(test_benchmark_propose_bounty::<Test>());
|
||||
assert_ok!(test_benchmark_approve_bounty::<Test>());
|
||||
assert_ok!(test_benchmark_propose_curator::<Test>());
|
||||
assert_ok!(test_benchmark_unassign_curator::<Test>());
|
||||
assert_ok!(test_benchmark_accept_curator::<Test>());
|
||||
assert_ok!(test_benchmark_award_bounty::<Test>());
|
||||
assert_ok!(test_benchmark_claim_bounty::<Test>());
|
||||
assert_ok!(test_benchmark_close_bounty_proposed::<Test>());
|
||||
assert_ok!(test_benchmark_close_bounty_active::<Test>());
|
||||
assert_ok!(test_benchmark_extend_bounty_expiry::<Test>());
|
||||
assert_ok!(test_benchmark_on_initialize_proposals::<Test>());
|
||||
assert_ok!(test_benchmark_on_initialize_bounties::<Test>());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user