Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Add child-bounties pallet. (#10309)
Browse files Browse the repository at this point in the history
* Extract child-bounties as a separate pallet.

* Initial tests added.

* More tests.

* Tests complete. Fixed curator fee issue.

* Fixed comments.

* Added benchmarks for child-bounties pallet.

* Added weights.

* Fixed formatting.

* Fixed comments.

* Re-run benchmarks for bounties pallet.

* Make cargo fmt happy again

* add max encoded len

* use event structs

* fmt

* fix compile

* Addressed review comments.

* Use config type instead of const in benchmarking.

* Addressed more review comments.

* Use ensure_can_withdraw instead of just checking min balance.

* fmt.

* Introduce ChildBountyCuratorDepositBase to avoid zero curator deposits for child bounties.

* Fix unassign curator logic for child-bounties.

* Added more tests for unassign curator.

* Reduce bounty description max length in node runtime.

* Updated weights for child bounties pallet.

* reduce indentation of unassign_curator

* more indentation reduction

* deduplicate slashing arms

* reintroduce ensure check

* add assertion to check that bad unassign origin fails

* formatting

* Updated comments.

Co-authored-by: Ricardo Rius <ricardo@parity.io>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
  • Loading branch information
4 people committed Dec 7, 2021
1 parent fd350e3 commit 4abd91c
Show file tree
Hide file tree
Showing 13 changed files with 2,896 additions and 78 deletions.
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ members = [
"frame/beefy-mmr/primitives",
"frame/benchmarking",
"frame/bounties",
"frame/child-bounties",
"frame/collective",
"frame/contracts",
"frame/contracts/rpc",
Expand Down
6 changes: 5 additions & 1 deletion bin/node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../.
pallet-bags-list = { version = "4.0.0-dev", default-features = false, path = "../../../frame/bags-list" }
pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" }
pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/bounties" }
pallet-child-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/child-bounties" }
pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../../../frame/collective" }
pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" }
pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/common/" }
Expand Down Expand Up @@ -173,7 +174,8 @@ std = [
"log/std",
"frame-try-runtime/std",
"sp-npos-elections/std",
"sp-io/std"
"sp-io/std",
"pallet-child-bounties/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
Expand All @@ -186,6 +188,7 @@ runtime-benchmarks = [
"pallet-bags-list/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-bounties/runtime-benchmarks",
"pallet-child-bounties/runtime-benchmarks",
"pallet-collective/runtime-benchmarks",
"pallet-contracts/runtime-benchmarks",
"pallet-democracy/runtime-benchmarks",
Expand Down Expand Up @@ -225,6 +228,7 @@ try-runtime = [
"pallet-babe/try-runtime",
"pallet-balances/try-runtime",
"pallet-bounties/try-runtime",
"pallet-child-bounties/try-runtime",
"pallet-collective/try-runtime",
"pallet-contracts/try-runtime",
"pallet-democracy/try-runtime",
Expand Down
17 changes: 16 additions & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,10 +844,13 @@ parameter_types! {
pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
pub const MaximumReasonLength: u32 = 16384;
pub const MaximumReasonLength: u32 = 300;
pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
pub const BountyValueMinimum: Balance = 5 * DOLLARS;
pub const MaxApprovals: u32 = 100;
pub const MaxActiveChildBountyCount: u32 = 5;
pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS;
pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10);
}

impl pallet_treasury::Config for Runtime {
Expand Down Expand Up @@ -883,6 +886,15 @@ impl pallet_bounties::Config for Runtime {
type DataDepositPerByte = DataDepositPerByte;
type MaximumReasonLength = MaximumReasonLength;
type WeightInfo = pallet_bounties::weights::SubstrateWeight<Runtime>;
type ChildBountyManager = ChildBounties;
}

impl pallet_child_bounties::Config for Runtime {
type Event = Event;
type MaxActiveChildBountyCount = MaxActiveChildBountyCount;
type ChildBountyValueMinimum = ChildBountyValueMinimum;
type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase;
type WeightInfo = pallet_child_bounties::weights::SubstrateWeight<Runtime>;
}

impl pallet_tips::Config for Runtime {
Expand Down Expand Up @@ -1302,6 +1314,7 @@ construct_runtime!(
Uniques: pallet_uniques,
TransactionStorage: pallet_transaction_storage,
BagsList: pallet_bags_list,
ChildBounties: pallet_child_bounties,
}
);

Expand Down Expand Up @@ -1652,6 +1665,7 @@ impl_runtime_apis! {
list_benchmark!(list, extra, pallet_bags_list, BagsList);
list_benchmark!(list, extra, pallet_balances, Balances);
list_benchmark!(list, extra, pallet_bounties, Bounties);
list_benchmark!(list, extra, pallet_child_bounties, ChildBounties);
list_benchmark!(list, extra, pallet_collective, Council);
list_benchmark!(list, extra, pallet_contracts, Contracts);
list_benchmark!(list, extra, pallet_democracy, Democracy);
Expand Down Expand Up @@ -1729,6 +1743,7 @@ impl_runtime_apis! {
add_benchmark!(params, batches, pallet_balances, Balances);
add_benchmark!(params, batches, pallet_bags_list, BagsList);
add_benchmark!(params, batches, pallet_bounties, Bounties);
add_benchmark!(params, batches, pallet_child_bounties, ChildBounties);
add_benchmark!(params, batches, pallet_collective, Council);
add_benchmark!(params, batches, pallet_contracts, Contracts);
add_benchmark!(params, batches, pallet_democracy, Democracy);
Expand Down
57 changes: 56 additions & 1 deletion frame/bounties/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ pub struct Bounty<AccountId, Balance, BlockNumber> {
status: BountyStatus<AccountId, BlockNumber>,
}

impl<AccountId: PartialEq + Clone + Ord + Default, Balance, BlockNumber: Clone>
Bounty<AccountId, Balance, BlockNumber>
{
/// Getter for bounty status, to be used for child bounties.
pub fn get_status(&self) -> BountyStatus<AccountId, BlockNumber> {
self.status.clone()
}
}

/// The status of a bounty proposal.
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub enum BountyStatus<AccountId, BlockNumber> {
Expand Down Expand Up @@ -156,6 +165,15 @@ pub enum BountyStatus<AccountId, BlockNumber> {
},
}

/// The child-bounty manager.
pub trait ChildBountyManager<Balance> {
/// Get the active child-bounties for a parent bounty.
fn child_bounties_count(bounty_id: BountyIndex) -> BountyIndex;

/// Get total curator fees of children-bounty curators.
fn children_curator_fees(bounty_id: BountyIndex) -> Balance;
}

#[frame_support::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -202,6 +220,9 @@ pub mod pallet {

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;

/// The child-bounty manager.
type ChildBountyManager: ChildBountyManager<BalanceOf<Self>>;
}

#[pallet::error]
Expand All @@ -225,6 +246,8 @@ pub mod pallet {
PendingPayout,
/// The bounties cannot be claimed/closed because it's still in the countdown period.
Premature,
/// The bounty cannot be closed because it has active child-bounties.
HasActiveChildBounty,
}

#[pallet::event]
Expand Down Expand Up @@ -512,6 +535,13 @@ pub mod pallet {

Bounties::<T>::try_mutate_exists(bounty_id, |maybe_bounty| -> DispatchResult {
let mut bounty = maybe_bounty.as_mut().ok_or(Error::<T>::InvalidIndex)?;

// Ensure no active child-bounties before processing the call.
ensure!(
T::ChildBountyManager::child_bounties_count(bounty_id) == 0,
Error::<T>::HasActiveChildBounty
);

match &bounty.status {
BountyStatus::Active { curator, .. } => {
ensure!(signer == *curator, Error::<T>::RequireCurator);
Expand Down Expand Up @@ -563,7 +593,15 @@ pub mod pallet {
let payout = balance.saturating_sub(fee);
let err_amount = T::Currency::unreserve(&curator, bounty.curator_deposit);
debug_assert!(err_amount.is_zero());
let res = T::Currency::transfer(&bounty_account, &curator, fee, AllowDeath); // should not fail

// Get total child-bounties curator fees, and subtract it from master curator
// fee.
let children_fee = T::ChildBountyManager::children_curator_fees(bounty_id);
debug_assert!(children_fee <= fee);

let final_fee = fee.saturating_sub(children_fee);
let res =
T::Currency::transfer(&bounty_account, &curator, final_fee, AllowDeath); // should not fail
debug_assert!(res.is_ok());
let res =
T::Currency::transfer(&bounty_account, &beneficiary, payout, AllowDeath); // should not fail
Expand Down Expand Up @@ -609,6 +647,12 @@ pub mod pallet {
|maybe_bounty| -> DispatchResultWithPostInfo {
let bounty = maybe_bounty.as_ref().ok_or(Error::<T>::InvalidIndex)?;

// Ensure no active child-bounties before processing the call.
ensure!(
T::ChildBountyManager::child_bounties_count(bounty_id) == 0,
Error::<T>::HasActiveChildBounty
);

match &bounty.status {
BountyStatus::Proposed => {
// The reject origin would like to cancel a proposed bounty.
Expand Down Expand Up @@ -813,3 +857,14 @@ impl<T: Config> pallet_treasury::SpendFunds<T> for Pallet<T> {
*total_weight += <T as Config>::WeightInfo::spend_funds(bounties_len);
}
}

// Default impl for when ChildBounties is not being used in the runtime.
impl<Balance: Zero> ChildBountyManager<Balance> for () {
fn child_bounties_count(_bounty_id: BountyIndex) -> BountyIndex {
Default::default()
}

fn children_curator_fees(_bounty_id: BountyIndex) -> Balance {
Zero::zero()
}
}
1 change: 1 addition & 0 deletions frame/bounties/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ impl Config for Test {
type DataDepositPerByte = DataDepositPerByte;
type MaximumReasonLength = MaximumReasonLength;
type WeightInfo = ();
type ChildBountyManager = ();
}

type TreasuryError = pallet_treasury::Error<Test>;
Expand Down
Loading

0 comments on commit 4abd91c

Please sign in to comment.