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

Add child-bounties pallet. #10309

Merged
merged 49 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
9a51337
Extract child-bounties as a separate pallet.
gautamdhameja Nov 15, 2021
6c0c03d
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 15, 2021
f782a94
Initial tests added.
gautamdhameja Nov 15, 2021
9926e7e
More tests.
gautamdhameja Nov 16, 2021
48853a9
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 16, 2021
46adcec
Tests complete. Fixed curator fee issue.
gautamdhameja Nov 16, 2021
ef06792
Fixed comments.
gautamdhameja Nov 17, 2021
1b40eda
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 17, 2021
7e84254
Added benchmarks for child-bounties pallet.
gautamdhameja Nov 17, 2021
524e279
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 17, 2021
74bead4
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 18, 2021
2f74ee3
Added weights.
gautamdhameja Nov 18, 2021
1260b67
Fixed formatting.
gautamdhameja Nov 18, 2021
70cfd6f
Fixed comments.
gautamdhameja Nov 18, 2021
999c294
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 18, 2021
27192b3
Re-run benchmarks for bounties pallet.
gautamdhameja Nov 19, 2021
ab25646
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 19, 2021
f58f556
Make cargo fmt happy again
Nov 19, 2021
82efd0f
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 20, 2021
26ba1a0
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 21, 2021
a555ab9
add max encoded len
shawntabrizi Nov 23, 2021
b2af33e
use event structs
shawntabrizi Nov 23, 2021
0f9575c
fmt
shawntabrizi Nov 23, 2021
583894a
fix compile
shawntabrizi Nov 24, 2021
d324416
Merge branch 'master' into gd-child-bounties
gautamdhameja Nov 28, 2021
a2c8448
Merge branch 'gd-child-bounties' of github.com:paritytech/substrate i…
gautamdhameja Nov 28, 2021
d682cee
Addressed review comments.
gautamdhameja Nov 28, 2021
a0b7155
Use config type instead of const in benchmarking.
gautamdhameja Nov 28, 2021
611ef21
Addressed more review comments.
gautamdhameja Nov 30, 2021
274c2c8
Use ensure_can_withdraw instead of just checking min balance.
gautamdhameja Dec 1, 2021
705be25
Merge branch 'master' into gd-child-bounties
gautamdhameja Dec 1, 2021
85eb39f
fmt.
gautamdhameja Dec 1, 2021
83dc90d
Introduce ChildBountyCuratorDepositBase to avoid zero curator deposit…
gautamdhameja Dec 2, 2021
f72cbb0
Merge branch 'master' into gd-child-bounties
gautamdhameja Dec 2, 2021
a230822
Fix unassign curator logic for child-bounties.
gautamdhameja Dec 3, 2021
fc297c5
Merge branch 'master' into gd-child-bounties
gautamdhameja Dec 3, 2021
284cb7d
Added more tests for unassign curator.
gautamdhameja Dec 3, 2021
6f3b147
Reduce bounty description max length in node runtime.
gautamdhameja Dec 3, 2021
e1ccf25
Merge branch 'master' into gd-child-bounties
gautamdhameja Dec 3, 2021
2323c95
Updated weights for child bounties pallet.
gautamdhameja Dec 3, 2021
05903ab
reduce indentation of unassign_curator
apopiak Dec 6, 2021
f7ba53a
more indentation reduction
apopiak Dec 6, 2021
735a9c3
deduplicate slashing arms
apopiak Dec 6, 2021
6808396
reintroduce ensure check
apopiak Dec 6, 2021
cbd8ddf
add assertion to check that bad unassign origin fails
apopiak Dec 6, 2021
a0108aa
formatting
apopiak Dec 6, 2021
3dd719a
Merge branch 'master' into gd-child-bounties
gautamdhameja Dec 6, 2021
2a24433
Merge branch 'master' into gd-child-bounties
gautamdhameja Dec 7, 2021
ed2534e
Updated comments.
gautamdhameja Dec 7, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -172,7 +173,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",
Expand All @@ -185,6 +187,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 @@ -224,6 +227,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
13 changes: 13 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,8 @@ parameter_types! {
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;
}

impl pallet_treasury::Config for Runtime {
Expand Down Expand Up @@ -873,6 +875,14 @@ 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 WeightInfo = pallet_child_bounties::weights::SubstrateWeight<Runtime>;
}

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

Expand Down Expand Up @@ -1629,6 +1640,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 @@ -1706,6 +1718,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
53 changes: 52 additions & 1 deletion frame/bounties/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@ pub struct Bounty<AccountId, Balance, BlockNumber> {
status: BountyStatus<AccountId, BlockNumber>,
}

// Getter for bounty status, to be used for child bounties.
impl<
AccountId: PartialEq + Clone + Ord + Default,
Balance,
BlockNumber: Clone
> Bounty<AccountId, Balance, BlockNumber> {
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 +167,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 @@ -200,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 @@ -223,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.
RequireNoActiveChildBounty
}

#[pallet::event]
Expand Down Expand Up @@ -510,6 +535,11 @@ 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>::RequireNoActiveChildBounty);
apopiak marked this conversation as resolved.
Show resolved Hide resolved

match &bounty.status {
BountyStatus::Active { curator, .. } => {
ensure!(signer == *curator, Error::<T>::RequireCurator);
Expand Down Expand Up @@ -561,7 +591,13 @@ 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 @@ -607,6 +643,10 @@ 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>::RequireNoActiveChildBounty);

match &bounty.status {
BountyStatus::Proposed => {
// The reject origin would like to cancel a proposed bounty.
Expand Down Expand Up @@ -811,3 +851,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 () {
kianenigma marked this conversation as resolved.
Show resolved Hide resolved
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
54 changes: 54 additions & 0 deletions frame/child-bounties/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[package]
name = "pallet-child-bounties"
version = "4.0.0-dev"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://substrate.io"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME pallet to manage child bounties"
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
"derive",
] }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" }
pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../bounties" }
sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false }
sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true }
log = { version = "0.4.14", default-features = false }

[dev-dependencies]
pallet-balances = { version = "4.0.0-dev", path = "../balances" }

[features]
default = ["std"]
std = [
"codec/std",
"sp-core/std",
"sp-io/std",
"scale-info/std",
"sp-std/std",
"sp-runtime/std",
"frame-support/std",
"frame-system/std",
"pallet-treasury/std",
"pallet-bounties/std",
"log/std",
]
runtime-benchmarks = [
"frame-benchmarking",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
21 changes: 21 additions & 0 deletions frame/child-bounties/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Child Bounties Pallet (pallet-child-bounties)

## Child Bounty

> NOTE: This pallet is tightly coupled with pallet-treasury and pallet-bounties.

With child bounties, a large bounty proposal can be divided into smaller chunks, for parallel execution, and for efficient governance and tracking of spent funds.

A child-bounty is a smaller piece of work, extracted from a parent bounty. A curator is assigned after the child-bounty is created by the parent bounty curator, to be delegated with the responsibility of assigning a payout address once the specified set of tasks is completed.

## Interface

### Dispatchable Functions

- `add_child_bounty` - Add a child-bounty for a parent-bounty to for dividing the work in smaller tasks.
- `propose_curator` - Assign an account to a child-bounty as candidate curator.
- `accept_curator` - Accept a child-bounty assignment from the parent-bounty curator, setting a curator deposit.
- `award_child_bounty` - Close and pay out the specified amount for the completed work.
- `claim_child_bounty` - Claim a specific child-bounty amount from the payout address.
- `unassign_curator` - Unassign an accepted curator from a specific child-bounty.
- `close_child_bounty` - Cancel the child-bounty for a specific treasury amount and close the bounty.
Loading