From 9ca052221bc36544d186542fd3b8a0d1f95da131 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 11 Mar 2022 12:48:32 -0400 Subject: [PATCH 01/17] basic idea --- frame/child-bounties/src/lib.rs | 46 +++++++++++++++++++++++++++---- frame/child-bounties/src/tests.rs | 8 ++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 36acc7766bf61..575041aeadbe6 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -144,10 +144,21 @@ pub mod pallet { #[pallet::constant] type ChildBountyValueMinimum: Get>; - /// Percentage of child-bounty value to be reserved as curator deposit - /// when curator fee is zero. + + /// In the case a child bounty has a non-zero fee, the deposit for the curator + /// will be a fraction of that fee based on the multiplier below. + #[pallet::constant] + type ChildCuratorDepositMultiplierWithFee: Get; + + /// In the case a child bounty has no fee, we use this multiplier in the following logic: + /// - if the child curator is the same as the parent curator, we know they already made + /// a deposit, and thus we don't need to take another deposit here. + /// - if the child curator is different, since there is no fee, we use this multiplier + /// against the total value of the bounty, which should always be non-zero. + /// + /// When there is a fee set, we use `ChildCuratorDepositMultiplierWithFee`, see above. #[pallet::constant] - type ChildBountyCuratorDepositBase: Get; + type ChildCuratorDepositMultiplierWithNoFee: Get; /// The overarching event type. type Event: From> + IsType<::Event>; @@ -392,7 +403,7 @@ pub mod pallet { ) -> DispatchResult { let signer = ensure_signed(origin)?; - let _ = Self::ensure_bounty_active(parent_bounty_id)?; + let (parent_curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; // Mutate child-bounty. ChildBounties::::try_mutate_exists( parent_bounty_id, @@ -410,7 +421,13 @@ pub mod pallet { // is reserved based on a percentage of child-bounty // value instead of fee, to avoid no deposit in case the // fee is set as zero. - let deposit = T::ChildBountyCuratorDepositBase::get() * child_bounty.value; + let deposit = Self::calculate_curator_deposit( + &parent_curator, + curator, + &child_bounty.value, + &child_bounty.fee, + ); + T::Currency::reserve(curator, deposit)?; child_bounty.curator_deposit = deposit; @@ -770,6 +787,25 @@ pub mod pallet { } impl Pallet { + // This function will calculate the deposit of a curator. + fn calculate_curator_deposit( + parent_curator: &T::AccountId, + child_curator: &T::AccountId, + bounty_value: &BalanceOf, + bounty_fee: &BalanceOf, + ) -> BalanceOf { + let fee: BalanceOf = if bounty_fee.is_zero() { + if parent_curator == child_curator { + return Zero::zero() + } + T::ChildCuratorDepositMultiplierWithNoFee::get() * *bounty_value + } else { + T::ChildCuratorDepositMultiplierWithFee::get() * *bounty_fee + }; + + fee + } + /// The account ID of a child-bounty account. pub fn child_bounty_account_id(id: BountyIndex) -> T::AccountId { // This function is taken from the parent (bounties) pallet, but the diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index a6748c47b73d8..f94fd50e5fd42 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -145,13 +145,17 @@ impl pallet_bounties::Config for Test { type ChildBountyManager = ChildBounties; } parameter_types! { - pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); + // This will be 50% of the bounty fee. + pub const ChildCuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); + // This will be 1% of the bounty value. + pub const ChildCuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); } impl pallet_child_bounties::Config for Test { type Event = Event; type MaxActiveChildBountyCount = ConstU32<2>; type ChildBountyValueMinimum = ConstU64<1>; - type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; + type ChildCuratorDepositMultiplierWithFee = ChildCuratorDepositMultiplierWithFee; + type ChildCuratorDepositMultiplierWithNoFee = ChildCuratorDepositMultiplierWithNoFee; type WeightInfo = (); } From 25761d7561ca3fd5815f62c1f40bd328321cd03c Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 11 Mar 2022 13:14:10 -0400 Subject: [PATCH 02/17] make tests better --- frame/child-bounties/src/tests.rs | 80 +++++++++++++++++-------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index f94fd50e5fd42..0e5d7bdab13e9 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -201,10 +201,10 @@ fn minting_works() { fn add_child_bounty() { new_test_ext().execute_with(|| { // TestProcedure. - // 1, Create bounty & move to active state with enough bounty fund & master-curator. - // 2, Master-curator adds child-bounty child-bounty-1, test for error like RequireCurator + // 1, Create bounty & move to active state with enough bounty fund & parent curator. + // 2, Parent curator adds child-bounty child-bounty-1, test for error like RequireCurator // ,InsufficientProposersBalance, InsufficientBountyBalance with invalid arguments. - // 3, Master-curator adds child-bounty child-bounty-1, moves to "Approved" state & + // 3, Parent curator adds child-bounty child-bounty-1, moves to "Approved" state & // test for the event Added. // 4, Test for DB state of `Bounties` & `ChildBounties`. // 5, Observe fund transaction moment between Bounty, Child-bounty, @@ -221,27 +221,30 @@ fn add_child_bounty() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 8; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); Balances::make_free_balance_be(&4, 10); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - assert_eq!(Balances::free_balance(&4), 8); - assert_eq!(Balances::reserved_balance(&4), 2); + // This verifies that the accept curator logic took a deposit. + let expected_deposit = BountyCuratorDeposit::get() * fee; + assert_eq!(Balances::reserved_balance(&4), expected_deposit); + assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); // Add child-bounty. - // Acc-4 is the master curator. + // Acc-4 is the parent curator. // Call from invalid origin & check for error "RequireCurator". assert_noop!( ChildBounties::add_child_bounty(Origin::signed(0), 0, 10, b"12345-p1".to_vec()), BountiesError::RequireCurator, ); - // Update the master curator balance. + // Update the parent curator balance. Balances::make_free_balance_be(&4, 101); - // Master curator fee is reserved on parent bounty account. + // parent curator fee is reserved on parent bounty account. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); @@ -262,7 +265,7 @@ fn add_child_bounty() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); assert_eq!(Balances::free_balance(4), 101); - assert_eq!(Balances::reserved_balance(4), 2); + assert_eq!(Balances::reserved_balance(4), expected_deposit); // DB check. // Check the child-bounty status. @@ -289,8 +292,8 @@ fn add_child_bounty() { fn child_bounty_assign_curator() { new_test_ext().execute_with(|| { // TestProcedure - // 1, Create bounty & move to active state with enough bounty fund & master-curator. - // 2, Master-curator adds child-bounty child-bounty-1, moves to "Active" state. + // 1, Create bounty & move to active state with enough bounty fund & parent curator. + // 2, Parent curator adds child-bounty child-bounty-1, moves to "Active" state. // 3, Test for DB state of `ChildBounties`. // Make the parent bounty. @@ -314,13 +317,13 @@ fn child_bounty_assign_curator() { assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); - // Check the balance of master curator. - // Curator deposit is reserved for master curator on parent bounty. + // Check the balance of parent curator. + // Curator deposit is reserved for parent curator on parent bounty. assert_eq!(Balances::free_balance(4), 99); assert_eq!(Balances::reserved_balance(4), 2); // Add child-bounty. - // Acc-4 is the master curator & make sure enough deposit. + // Acc-4 is the parent curator & make sure enough deposit. assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); @@ -333,22 +336,25 @@ fn child_bounty_assign_curator() { assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 4u64; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, + fee, curator_deposit: 0, status: ChildBountyStatus::CuratorProposed { curator: 8 }, } ); - // Check the balance of master curator. - assert_eq!(Balances::free_balance(4), 99); - assert_eq!(Balances::reserved_balance(4), 2); + let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; + + // Check the balance of parent curator. + assert_eq!(Balances::free_balance(4), 101 - expected_deposit); + assert_eq!(Balances::reserved_balance(4), expected_deposit); assert_noop!( ChildBounties::accept_curator(Origin::signed(3), 0, 0), @@ -362,15 +368,15 @@ fn child_bounty_assign_curator() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); - // Deposit for child-bounty curator is reserved. - assert_eq!(Balances::free_balance(8), 100); - assert_eq!(Balances::reserved_balance(8), 1); + // Deposit for child-bounty curator deposit is reserved. + assert_eq!(Balances::free_balance(8), 101 - expected_deposit); + assert_eq!(Balances::reserved_balance(8), expected_deposit); // Bounty account status at exit. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 40); @@ -415,7 +421,8 @@ fn award_claim_child_bounty() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 4; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); // Award child-bounty. @@ -427,13 +434,14 @@ fn award_claim_child_bounty() { assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_deposit, status: ChildBountyStatus::PendingPayout { curator: 8, beneficiary: 7, @@ -454,11 +462,11 @@ fn award_claim_child_bounty() { assert_ok!(ChildBounties::claim_child_bounty(Origin::signed(7), 0, 0)); // Ensure child-bounty curator is paid with curator fee & deposit refund. - assert_eq!(Balances::free_balance(8), 103); + assert_eq!(Balances::free_balance(8), 101 + fee); assert_eq!(Balances::reserved_balance(8), 0); // Ensure executor is paid with beneficiary amount. - assert_eq!(Balances::free_balance(7), 8); + assert_eq!(Balances::free_balance(7), 10 - fee); assert_eq!(Balances::reserved_balance(7), 0); // Child-bounty account status. @@ -605,7 +613,8 @@ fn close_child_bounty_pending() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 4; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 4)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); @@ -620,8 +629,9 @@ fn close_child_bounty_pending() { assert_eq!(ChildBounties::parent_child_bounties(0), 1); // Ensure no changes in child-bounty curator balance. - assert_eq!(Balances::free_balance(8), 100); - assert_eq!(Balances::reserved_balance(8), 1); + let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; + assert_eq!(Balances::reserved_balance(8), expected_deposit); + assert_eq!(Balances::free_balance(8), 101 - expected_deposit); // Child-bounty account status. assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); @@ -824,7 +834,7 @@ fn child_bounty_active_unassign_curator() { System::set_block_number(5); >::on_initialize(5); - // Unassign curator again - from master curator. + // Unassign curator again - from parent curator. assert_ok!(ChildBounties::unassign_curator(Origin::signed(4), 0, 0)); // Verify updated child-bounty status. @@ -1052,7 +1062,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { System::set_block_number(9); >::on_initialize(9); - // Unassign curator again - from master curator. + // Unassign curator again - from parent curator. assert_ok!(ChildBounties::unassign_curator(Origin::signed(7), 0, 0)); // Verify updated child-bounty status. From 87c4a37d8a1580daa128ab5dcf7dc3357add1758 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 11 Mar 2022 13:25:37 -0400 Subject: [PATCH 03/17] update bounties pallet to also have similar logic --- frame/bounties/src/lib.rs | 27 ++++++++++++++++++++++----- frame/bounties/src/tests.rs | 6 ++++-- frame/child-bounties/src/lib.rs | 5 ++--- frame/child-bounties/src/tests.rs | 8 +++++--- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 988b15c58a13f..8cb857d97f97d 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -196,10 +196,19 @@ pub mod pallet { #[pallet::constant] type BountyUpdatePeriod: Get; - /// Percentage of the curator fee that will be reserved upfront as deposit for bounty - /// curator. + /// If the bounty has a fee, the curator deposit is a percentage of that fee. Otherwise, we + /// use the `CuratorDepositMultiplierWithNoFee` multiplied by the value of the bounty to + /// determine the deposit. #[pallet::constant] - type BountyCuratorDeposit: Get; + type CuratorDepositMultiplierWithFee: Get; + + /// If the bounty has no fee, we still want to make sure the curator has some non-zero + /// deposit, so then we use this multiplier along side the value (which should be non-zero) + /// to determine the curator deposit. + /// + /// If the bounty has a fee, see `CuratorDepositMultiplierWithFee` above. + #[pallet::constant] + type CuratorDepositMultiplierWithNoFee: Get; /// Minimum value for a bounty. #[pallet::constant] @@ -502,7 +511,7 @@ pub mod pallet { BountyStatus::CuratorProposed { ref curator } => { ensure!(signer == *curator, Error::::RequireCurator); - let deposit = T::BountyCuratorDeposit::get() * bounty.fee; + let deposit = Self::calculate_curator_deposit(bounty.value, bounty.fee); T::Currency::reserve(curator, deposit)?; bounty.curator_deposit = deposit; @@ -762,7 +771,15 @@ pub mod pallet { } impl Pallet { - // Add public immutables and private mutables. + fn calculate_curator_deposit(value: BalanceOf, fee: BalanceOf) -> BalanceOf { + let deposit = if fee.is_zero() { + T::CuratorDepositMultiplierWithNoFee::get() * value + } else { + T::CuratorDepositMultiplierWithFee::get() * fee + }; + + deposit + } /// The account ID of the treasury pot. /// diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 3206fce9912fa..f2b24c0d33917 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -126,14 +126,16 @@ impl pallet_treasury::Config for Test { type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); + pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); } impl Config for Test { type Event = Event; type BountyDepositBase = ConstU64<80>; type BountyDepositPayoutDelay = ConstU64<3>; type BountyUpdatePeriod = ConstU64<20>; - type BountyCuratorDeposit = BountyCuratorDeposit; + type CuratorDepositMultiplierWithFee = CuratorDepositMultiplierWithFee; + type CuratorDepositMultiplierWithNoFee = CuratorDepositMultiplierWithNoFee; type BountyValueMinimum = ConstU64<1>; type DataDepositPerByte = ConstU64<1>; type MaximumReasonLength = ConstU32<16384>; diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 575041aeadbe6..0e75c7ce561d9 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -144,15 +144,14 @@ pub mod pallet { #[pallet::constant] type ChildBountyValueMinimum: Get>; - /// In the case a child bounty has a non-zero fee, the deposit for the curator /// will be a fraction of that fee based on the multiplier below. #[pallet::constant] type ChildCuratorDepositMultiplierWithFee: Get; /// In the case a child bounty has no fee, we use this multiplier in the following logic: - /// - if the child curator is the same as the parent curator, we know they already made - /// a deposit, and thus we don't need to take another deposit here. + /// - if the child curator is the same as the parent curator, we know they already made a + /// deposit, and thus we don't need to take another deposit here. /// - if the child curator is different, since there is no fee, we use this multiplier /// against the total value of the bounty, which should always be non-zero. /// diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index 0e5d7bdab13e9..c55e98aa3b8df 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -130,14 +130,16 @@ impl pallet_treasury::Config for Test { type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); + pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); } impl pallet_bounties::Config for Test { type Event = Event; type BountyDepositBase = ConstU64<80>; type BountyDepositPayoutDelay = ConstU64<3>; type BountyUpdatePeriod = ConstU64<10>; - type BountyCuratorDeposit = BountyCuratorDeposit; + type CuratorDepositMultiplierWithFee = CuratorDepositMultiplierWithFee; + type CuratorDepositMultiplierWithNoFee = CuratorDepositMultiplierWithNoFee; type BountyValueMinimum = ConstU64<5>; type DataDepositPerByte = ConstU64<1>; type MaximumReasonLength = ConstU32<300>; @@ -229,7 +231,7 @@ fn add_child_bounty() { assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // This verifies that the accept curator logic took a deposit. - let expected_deposit = BountyCuratorDeposit::get() * fee; + let expected_deposit = CuratorDepositMultiplierWithFee::get() * fee; assert_eq!(Balances::reserved_balance(&4), expected_deposit); assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); From cf881f6ecb71c8808e09bea323c653537db4db01 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 11 Mar 2022 13:37:46 -0400 Subject: [PATCH 04/17] new test verifies logic for bounty pallet --- frame/bounties/src/tests.rs | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index f2b24c0d33917..24527cbb1061d 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -1036,3 +1036,54 @@ fn unassign_curator_self() { assert_eq!(Balances::reserved_balance(1), 0); // not slashed }); } + +#[test] +fn accept_curator_handles_different_deposit_calculations() { + // This test will verify that a bounty with and without a fee results + // in a different curator deposit: one using the value, and one using the fee. + new_test_ext().execute_with(|| { + // Case 1: With a fee + let user = 1; + let bounty_index = 0; + let value = 88; + let fee = 42; + + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + Balances::make_free_balance_be(&user, 100); + assert_ok!(Bounties::propose_bounty(Origin::signed(0), value, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), bounty_index)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); + assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); + + let expected_deposit = CuratorDepositMultiplierWithFee::get() * fee; + assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); + assert_eq!(Balances::reserved_balance(&user), expected_deposit); + + // Case 2: Without a fee + let user = 2; + let bounty_index = 1; + let value = 35; + let fee = 0; + + Balances::make_free_balance_be(&Treasury::account_id(), 101); + Balances::make_free_balance_be(&user, 100); + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), value, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), bounty_index)); + + System::set_block_number(3); + >::on_initialize(3); + + assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); + assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); + + let expected_deposit = CuratorDepositMultiplierWithNoFee::get() * value; + assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); + assert_eq!(Balances::reserved_balance(&user), expected_deposit); + }); +} From b88ddbafdb0ae30dac14d4f895c4979c1445e955 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 11 Mar 2022 14:14:34 -0400 Subject: [PATCH 05/17] add test for new child logic --- frame/child-bounties/src/tests.rs | 137 ++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index c55e98aa3b8df..86e8ae7177f39 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -1225,3 +1225,140 @@ fn children_curator_fee_calculation_test() { assert_eq!(Balances::reserved_balance(9), 0); }); } + +#[test] +fn accept_curator_handles_different_deposit_calculations() { + // This test will verify that a bounty with and without a fee results + // in a different curator deposit, and if the child curator matches the parent curator. + new_test_ext().execute_with(|| { + // Setup a parent bounty. + let parent_curator = 0; + let parent_index = 0; + let parent_value = 10_000; + let parent_fee = 1_000; + + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), parent_value * 3); + Balances::make_free_balance_be(&parent_curator, parent_fee * 100); + assert_ok!(Bounties::propose_bounty( + Origin::signed(parent_curator), + parent_value, + b"12345".to_vec() + )); + assert_ok!(Bounties::approve_bounty(Origin::root(), parent_index)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator( + Origin::root(), + parent_index, + parent_curator, + parent_fee + )); + assert_ok!(Bounties::accept_curator(Origin::signed(parent_curator), parent_index)); + + // Now we can start creating some child bounties. + // Case 1: There is a fee, we don't care if parent and child curator are the same. + + let child_index = 0; + let child_curator = 1; + let child_value = 1_000; + let child_fee = 100; + let starting_balance = 100 * child_fee + child_value; + + Balances::make_free_balance_be(&child_curator, starting_balance); + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(3); + >::on_initialize(3); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * child_fee; + assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); + + // Case 2: There is no fee, and the parent and child curator are the same. + + let child_index = 1; + let child_curator = parent_curator; // The same as parent bounty curator + let child_value = 1_000; + let child_fee = 0; // No fee + + let free_before = Balances::free_balance(&parent_curator); + let reserved_before = Balances::reserved_balance(&parent_curator); + + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(4); + >::on_initialize(4); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + // No expected deposit + assert_eq!(Balances::free_balance(child_curator), free_before); + assert_eq!(Balances::reserved_balance(child_curator), reserved_before); + + // Case 3: There is no fee, and the parent and child curator are not the same. + + let child_index = 2; + let child_curator = 2; + let child_value = 1_000; + let child_fee = 0; // No fee + + Balances::make_free_balance_be(&child_curator, starting_balance); + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(5); + >::on_initialize(5); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + let expected_deposit = ChildCuratorDepositMultiplierWithNoFee::get() * child_value; + assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); + }); +} From cf2cb45e0e5fdda0a0c40e46a6545368cacafdba Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 11 Mar 2022 14:25:59 -0400 Subject: [PATCH 06/17] better name --- frame/child-bounties/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 0e75c7ce561d9..5a37f6682c6b2 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -793,7 +793,7 @@ impl Pallet { bounty_value: &BalanceOf, bounty_fee: &BalanceOf, ) -> BalanceOf { - let fee: BalanceOf = if bounty_fee.is_zero() { + let deposit: BalanceOf = if bounty_fee.is_zero() { if parent_curator == child_curator { return Zero::zero() } @@ -802,7 +802,7 @@ impl Pallet { T::ChildCuratorDepositMultiplierWithFee::get() * *bounty_fee }; - fee + deposit } /// The account ID of a child-bounty account. From 5751738e564115d5ca58607f0c98563ac0955860 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Sat, 12 Mar 2022 01:44:42 -0700 Subject: [PATCH 07/17] make `node` compile with bounties changes --- bin/node/runtime/src/lib.rs | 23 +++++++++++++++-------- frame/bounties/src/tests.rs | 4 ++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 8c7a20af15683..83b66bfa259c4 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -217,7 +217,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = frame_system::weights::SubstrateWeight; type SS58Prefix = ConstU16<42>; type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Runtime {} @@ -829,7 +829,7 @@ impl pallet_democracy::Config for Runtime { type Slash = Treasury; type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; - type MaxVotes = frame_support::traits::ConstU32<100>; + type MaxVotes = ConstU32<100>; type WeightInfo = pallet_democracy::weights::SubstrateWeight; type MaxProposals = MaxProposals; } @@ -932,6 +932,8 @@ parameter_types! { pub const TipReportDepositBase: Balance = 1 * DOLLARS; pub const DataDepositPerByte: Balance = 1 * CENTS; pub const BountyDepositBase: Balance = 1 * DOLLARS; + pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); + pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; @@ -939,9 +941,6 @@ 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; - pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); } impl pallet_treasury::Config for Runtime { @@ -973,7 +972,8 @@ impl pallet_bounties::Config for Runtime { type BountyDepositBase = BountyDepositBase; type BountyDepositPayoutDelay = BountyDepositPayoutDelay; type BountyUpdatePeriod = BountyUpdatePeriod; - type BountyCuratorDeposit = BountyCuratorDeposit; + type CuratorDepositMultiplierWithFee = CuratorDepositMultiplierWithFee; + type CuratorDepositMultiplierWithNoFee = CuratorDepositMultiplierWithNoFee; type BountyValueMinimum = BountyValueMinimum; type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = MaximumReasonLength; @@ -981,11 +981,18 @@ impl pallet_bounties::Config for Runtime { type ChildBountyManager = ChildBounties; } +parameter_types! { + pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS; + pub const ChildCuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); + pub const ChildCuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); +} + impl pallet_child_bounties::Config for Runtime { type Event = Event; - type MaxActiveChildBountyCount = MaxActiveChildBountyCount; + type MaxActiveChildBountyCount = ConstU32<5>; type ChildBountyValueMinimum = ChildBountyValueMinimum; - type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; + type ChildCuratorDepositMultiplierWithFee = ChildCuratorDepositMultiplierWithFee; + type ChildCuratorDepositMultiplierWithNoFee = ChildCuratorDepositMultiplierWithNoFee; type WeightInfo = pallet_child_bounties::weights::SubstrateWeight; } diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 24527cbb1061d..30887579755f7 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -125,10 +125,14 @@ impl pallet_treasury::Config for Test { type SpendFunds = Bounties; type MaxApprovals = ConstU32<100>; } + parameter_types! { + // This will be 50% of the bounty fee. pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); + // This will be 1% of the bounty value. pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); } + impl Config for Test { type Event = Event; type BountyDepositBase = ConstU64<80>; From 1ab729e7c23b5db24a8e229d487bbc2ed81d38c3 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Sat, 12 Mar 2022 03:03:06 -0700 Subject: [PATCH 08/17] * formatting * use uniform notion of parent and child, no "master" or "general" entity * README updated to match comments --- frame/bounties/README.md | 46 ++++++++++------- frame/bounties/src/lib.rs | 24 ++++++--- frame/child-bounties/README.md | 30 +++++++---- frame/child-bounties/src/lib.rs | 89 +++++++++++++++++---------------- 4 files changed, 110 insertions(+), 79 deletions(-) diff --git a/frame/bounties/README.md b/frame/bounties/README.md index bf63fca5f34b2..232334cb1edd6 100644 --- a/frame/bounties/README.md +++ b/frame/bounties/README.md @@ -2,28 +2,38 @@ ## Bounty -**Note :: This pallet is tightly coupled with pallet-treasury** +> NOTE: This pallet is tightly coupled with pallet-treasury. -A Bounty Spending is a reward for a specified body of work - or specified set of objectives - that -needs to be executed for a predefined Treasury amount to be paid out. A curator is assigned after -the bounty is approved and funded by Council, to be delegated with the responsibility of assigning a -payout address once the specified set of objectives is completed. +A Bounty Spending is a reward for a specified body of work - or specified set of objectives - +that needs to be executed for a predefined Treasury amount to be paid out. A curator is assigned +after the bounty is approved and funded by Council, to be delegated with the responsibility of +assigning a payout address once the specified set of objectives is completed. -After the Council has activated a bounty, it delegates the work that requires expertise to a curator -in exchange of a deposit. Once the curator accepts the bounty, they get to close the active bounty. -Closing the active bounty enacts a delayed payout to the payout address, the curator fee and the -return of the curator deposit. The delay allows for intervention through regular democracy. The -Council gets to unassign the curator, resulting in a new curator election. The Council also gets to -cancel the bounty if deemed necessary before assigning a curator or once the bounty is active or -payout is pending, resulting in the slash of the curator's deposit. +After the Council has activated a bounty, it delegates the work that requires expertise to a +curator in exchange of a deposit. Once the curator accepts the bounty, they get to close the +active bounty. Closing the active bounty enacts a delayed payout to the payout address, the +curator fee and the return of the curator deposit. The delay allows for intervention through +regular democracy. The Council gets to unassign the curator, resulting in a new curator +election. The Council also gets to cancel the bounty if deemed necessary before assigning a +curator or once the bounty is active or payout is pending, resulting in the slash of the +curator's deposit. + +This pallet may opt into using a [`ChildBountyManager`] that enables bounties to be split into +sub-bounties, as children of anh established bounty (called the parent in the context of it's +children). + +> NOTE: The parent bounty cannot be closed if it has a non-zero number of it has active child +> bounties associated with it. ### Terminology -- **Bounty spending proposal:** A proposal to reward a predefined body of work upon completion by - the Treasury. +Bounty: + +- **Bounty spending proposal:** A proposal to reward a predefined body of work upon completion + by the Treasury. - **Proposer:** An account proposing a bounty spending. -- **Curator:** An account managing the bounty and assigning a payout address receiving the reward - for the completion of work. +- **Curator:** An account managing the bounty and assigning a payout address receiving the + reward for the completion of work. - **Deposit:** The amount held on deposit for placing a bounty proposal plus the amount held on deposit per byte within the bounty description. - **Curator deposit:** The payment from a candidate willing to curate an approved bounty. The @@ -31,7 +41,8 @@ payout is pending, resulting in the slash of the curator's deposit. - **Bounty value:** The total amount that should be paid to the Payout Address if the bounty is rewarded. - **Payout address:** The account to which the total or part of the bounty is assigned to. -- **Payout Delay:** The delay period for which a bounty beneficiary needs to wait before claiming. +- **Payout Delay:** The delay period for which a bounty beneficiary needs to wait before + claiming. - **Curator fee:** The reserved upfront payment for a curator for work related to the bounty. ## Interface @@ -39,6 +50,7 @@ payout is pending, resulting in the slash of the curator's deposit. ### Dispatchable Functions Bounty protocol: + - `propose_bounty` - Propose a specific treasury amount to be earmarked for a predefined set of tasks and stake the required deposit. - `approve_bounty` - Accept a specific treasury amount to be earmarked for a predefined body of diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 8cb857d97f97d..85e8051250945 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -35,10 +35,17 @@ //! curator or once the bounty is active or payout is pending, resulting in the slash of the //! curator's deposit. //! +//! This pallet may opt into using a [`ChildBountyManager`] that enables bounties to be split into +//! sub-bounties, as children of anh established bounty (called the parent in the context of it's +//! children). +//! +//! > NOTE: The parent bounty cannot be closed if it has a non-zero number of it has active child +//! > bounties associated with it. //! //! ### Terminology //! //! Bounty: +//! //! - **Bounty spending proposal:** A proposal to reward a predefined body of work upon completion //! by the Treasury. //! - **Proposer:** An account proposing a bounty spending. @@ -60,6 +67,7 @@ //! ### Dispatchable Functions //! //! Bounty protocol: +//! //! - `propose_bounty` - Propose a specific treasury amount to be earmarked for a predefined set of //! tasks and stake the required deposit. //! - `approve_bounty` - Accept a specific treasury amount to be earmarked for a predefined body of @@ -165,9 +173,9 @@ pub enum BountyStatus { }, } -/// The child-bounty manager. +/// The child bounty manager. pub trait ChildBountyManager { - /// Get the active child-bounties for a parent bounty. + /// 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. @@ -230,7 +238,7 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; - /// The child-bounty manager. + /// The child bounty manager. type ChildBountyManager: ChildBountyManager>; } @@ -255,7 +263,7 @@ 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. + /// The bounty cannot be closed because it has active child bounties. HasActiveChildBounty, /// Too many approvals are already queued. TooManyQueued, @@ -551,7 +559,7 @@ pub mod pallet { Bounties::::try_mutate_exists(bounty_id, |maybe_bounty| -> DispatchResult { let mut bounty = maybe_bounty.as_mut().ok_or(Error::::InvalidIndex)?; - // Ensure no active child-bounties before processing the call. + // Ensure no active child bounties before processing the call. ensure!( T::ChildBountyManager::child_bounties_count(bounty_id) == 0, Error::::HasActiveChildBounty @@ -609,8 +617,8 @@ pub mod pallet { let err_amount = T::Currency::unreserve(&curator, bounty.curator_deposit); debug_assert!(err_amount.is_zero()); - // Get total child-bounties curator fees, and subtract it from master curator - // fee. + // Get total child bounties curator fees, and subtract it from the parent + // curator fee (the fee in present referenced bounty, `self`). let children_fee = T::ChildBountyManager::children_curator_fees(bounty_id); debug_assert!(children_fee <= fee); @@ -662,7 +670,7 @@ pub mod pallet { |maybe_bounty| -> DispatchResultWithPostInfo { let bounty = maybe_bounty.as_ref().ok_or(Error::::InvalidIndex)?; - // Ensure no active child-bounties before processing the call. + // Ensure no active child bounties before processing the call. ensure!( T::ChildBountyManager::child_bounties_count(bounty_id) == 0, Error::::HasActiveChildBounty diff --git a/frame/child-bounties/README.md b/frame/child-bounties/README.md index e07996d54957a..607b6eb58f6a1 100644 --- a/frame/child-bounties/README.md +++ b/frame/child-bounties/README.md @@ -1,21 +1,29 @@ -# Child Bounties Pallet (pallet-child-bounties) +# Child Bounties Pallet ( `pallet-child-bounties` ) ## Child Bounty -> NOTE: This pallet is tightly coupled with pallet-treasury and pallet-bounties. +> 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. +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. +Child Bounty protocol: + +- `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. +- `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. diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 5a37f6682c6b2..053826b453657 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! # Child Bounties Pallet ( pallet-child-bounties ) +//! # Child Bounties Pallet ( `pallet-child-bounties` ) //! //! ## Child Bounty //! -//! > NOTE: This pallet is tightly coupled with pallet-treasury and pallet-bounties. +//! > 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, +//! 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. //! @@ -33,22 +33,22 @@ //! ### Dispatchable Functions //! //! Child Bounty protocol: -//! - `add_child_bounty` - Add a child-bounty for a parent-bounty to for dividing the work in +//! - `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 +//! - `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 +//! - `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. // Most of the business logic in this pallet has been // originally contributed by "https://github.com/shamb0", // as part of the PR - https://github.com/paritytech/substrate/pull/7965. // The code has been moved here and then refactored in order to -// extract child-bounties as a separate pallet. +// extract child bounties as a separate pallet. #![cfg_attr(not(feature = "std"), no_std)] @@ -101,7 +101,7 @@ pub struct ChildBounty { pub enum ChildBountyStatus { /// The child-bounty is added and waiting for curator assignment. Added, - /// A curator has been proposed by the parent-bounty curator. Waiting for + /// A curator has been proposed by the parent bounty curator. Waiting for /// acceptance from the child-bounty curator. CuratorProposed { /// The assigned child-bounty curator of this bounty. @@ -136,7 +136,7 @@ pub mod pallet { pub trait Config: frame_system::Config + pallet_treasury::Config + pallet_bounties::Config { - /// Maximum number of child-bounties that can be added to a parent bounty. + /// Maximum number of child bounties that can be added to a parent bounty. #[pallet::constant] type MaxActiveChildBountyCount: Get; @@ -172,7 +172,7 @@ pub mod pallet { ParentBountyNotActive, /// The bounty balance is not enough to add new child-bounty. InsufficientBountyBalance, - /// Number of child-bounties exceeds limit `MaxActiveChildBountyCount`. + /// Number of child bounties exceeds limit `MaxActiveChildBountyCount`. TooManyChildBounties, } @@ -180,18 +180,18 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// A child-bounty is added. - Added { index: BountyIndex, child_index: BountyIndex }, + Added { parent_index: BountyIndex, child_index: BountyIndex }, /// A child-bounty is awarded to a beneficiary. - Awarded { index: BountyIndex, child_index: BountyIndex, beneficiary: T::AccountId }, + Awarded { parent_index: BountyIndex, child_index: BountyIndex, beneficiary: T::AccountId }, /// A child-bounty is claimed by beneficiary. Claimed { - index: BountyIndex, + parent_index: BountyIndex, child_index: BountyIndex, payout: BalanceOf, beneficiary: T::AccountId, }, /// A child-bounty is cancelled. - Canceled { index: BountyIndex, child_index: BountyIndex }, + Canceled { parent_index: BountyIndex, child_index: BountyIndex }, } /// Number of total child bounties. @@ -199,14 +199,14 @@ pub mod pallet { #[pallet::getter(fn child_bounty_count)] pub type ChildBountyCount = StorageValue<_, BountyIndex, ValueQuery>; - /// Number of child-bounties per parent bounty. + /// Number of child bounties per parent bounty. /// Map of parent bounty index to number of child bounties. #[pallet::storage] #[pallet::getter(fn parent_child_bounties)] pub type ParentChildBounties = StorageMap<_, Twox64Concat, BountyIndex, u32, ValueQuery>; - /// Child-bounties that have been added. + /// child bounties that have been added. #[pallet::storage] #[pallet::getter(fn child_bounties)] pub type ChildBounties = StorageDoubleMap< @@ -241,7 +241,7 @@ pub mod pallet { /// parent bounty to child-bounty account, if parent bounty has enough /// funds, else the call fails. /// - /// Upper bound to maximum number of active child-bounties that can be + /// Upper bound to maximum number of active child bounties that can be /// added are managed via runtime trait config /// [`Config::MaxActiveChildBountyCount`]. /// @@ -420,7 +420,7 @@ pub mod pallet { // is reserved based on a percentage of child-bounty // value instead of fee, to avoid no deposit in case the // fee is set as zero. - let deposit = Self::calculate_curator_deposit( + let deposit = Self::calculate_child_curator_deposit( &parent_curator, curator, &child_bounty.value, @@ -446,12 +446,12 @@ pub mod pallet { /// the curator of the parent bounty, or any signed origin. /// /// For the origin other than T::RejectOrigin and the child-bounty - /// curator, parent-bounty must be in active state, for this call to + /// curator, parent bounty must be in active state, for this call to /// work. We allow child-bounty curator and T::RejectOrigin to execute - /// this call irrespective of the parent-bounty state. + /// this call irrespective of the parent bounty state. /// /// If this function is called by the `RejectOrigin` or the - /// parent-bounty curator, we assume that the child-bounty curator is + /// parent bounty curator, we assume that the child-bounty curator is /// malicious or inactive. As a result, child-bounty curator deposit is /// slashed. /// @@ -505,7 +505,7 @@ pub mod pallet { }, ChildBountyStatus::CuratorProposed { ref curator } => { // A child-bounty curator has been proposed, but not accepted yet. - // Either `RejectOrigin`, parent-bounty curator or the proposed + // Either `RejectOrigin`, parent bounty curator or the proposed // child-bounty curator can unassign the child-bounty curator. ensure!( maybe_sender.map_or(true, |sender| { @@ -543,7 +543,7 @@ pub mod pallet { update_due < frame_system::Pallet::::block_number() { // Slash the child-bounty curator if - // + the call is made by the parent-bounty curator. + // + the call is made by the parent bounty curator. // + or the curator is inactive. slash_curator(curator, &mut child_bounty.curator_deposit); // Continue to change bounty status below. @@ -575,7 +575,7 @@ pub mod pallet { /// /// The beneficiary will be able to claim the funds after a delay. /// - /// The dispatch origin for this call must be the master curator or + /// The dispatch origin for this call must be the parent curator or /// curator of this child-bounty. /// /// Parent bounty must be in active state, for this child-bounty call to @@ -630,7 +630,7 @@ pub mod pallet { // Trigger the event Awarded. Self::deposit_event(Event::::Awarded { - index: parent_bounty_id, + parent_index: parent_bounty_id, child_index: child_bounty_id, beneficiary, }); @@ -716,7 +716,7 @@ pub mod pallet { // Trigger the Claimed event. Self::deposit_event(Event::::Claimed { - index: parent_bounty_id, + parent_index: parent_bounty_id, child_index: child_bounty_id, payout, beneficiary: beneficiary.clone(), @@ -787,19 +787,19 @@ pub mod pallet { impl Pallet { // This function will calculate the deposit of a curator. - fn calculate_curator_deposit( + fn calculate_child_curator_deposit( parent_curator: &T::AccountId, child_curator: &T::AccountId, - bounty_value: &BalanceOf, - bounty_fee: &BalanceOf, + child_bounty_value: &BalanceOf, + child_bounty_fee: &BalanceOf, ) -> BalanceOf { - let deposit: BalanceOf = if bounty_fee.is_zero() { + let deposit: BalanceOf = if child_bounty_fee.is_zero() { if parent_curator == child_curator { return Zero::zero() } - T::ChildCuratorDepositMultiplierWithNoFee::get() * *bounty_value + T::ChildCuratorDepositMultiplierWithNoFee::get() * *child_bounty_value } else { - T::ChildCuratorDepositMultiplierWithFee::get() * *bounty_fee + T::ChildCuratorDepositMultiplierWithFee::get() * *child_bounty_fee }; deposit @@ -828,13 +828,16 @@ impl Pallet { }; ChildBounties::::insert(parent_bounty_id, child_bounty_id, &child_bounty); ChildBountyDescriptions::::insert(child_bounty_id, description); - Self::deposit_event(Event::Added { index: parent_bounty_id, child_index: child_bounty_id }); + Self::deposit_event(Event::Added { + parent_index: parent_bounty_id, + child_index: child_bounty_id, + }); } fn ensure_bounty_active( - bounty_id: BountyIndex, + parent_bounty_id: BountyIndex, ) -> Result<(T::AccountId, T::BlockNumber), DispatchError> { - let parent_bounty = pallet_bounties::Pallet::::bounties(bounty_id) + let parent_bounty = pallet_bounties::Pallet::::bounties(parent_bounty_id) .ok_or(BountiesError::::InvalidIndex)?; if let BountyStatus::Active { curator, update_due } = parent_bounty.get_status() { Ok((curator, update_due)) @@ -859,7 +862,7 @@ impl Pallet { // Nothing extra to do besides the removal of the child-bounty below. }, ChildBountyStatus::Active { curator } => { - // Cancelled by master curator or RejectOrigin, + // Cancelled by parent curator or RejectOrigin, // refund deposit of the working child-bounty curator. let _ = T::Currency::unreserve(curator, child_bounty.curator_deposit); // Then execute removal of the child-bounty below. @@ -874,7 +877,7 @@ impl Pallet { }, } - // Revert the curator fee back to parent-bounty curator & + // Revert the curator fee back to parent bounty curator & // reduce the active child-bounty count. ChildrenCuratorFees::::mutate(parent_bounty_id, |value| { *value = value.saturating_sub(child_bounty.fee) @@ -902,7 +905,7 @@ impl Pallet { *maybe_child_bounty = None; Self::deposit_event(Event::::Canceled { - index: parent_bounty_id, + parent_index: parent_bounty_id, child_index: child_bounty_id, }); Ok(()) @@ -912,7 +915,7 @@ impl Pallet { } // Implement ChildBountyManager to connect with the bounties pallet. This is -// where we pass the active child-bounties and child curator fees to the parent +// where we pass the active child bounties and child curator fees to the parent // bounty. impl pallet_bounties::ChildBountyManager> for Pallet { fn child_bounties_count( From 2cbf658d0a025f43307f90f76cae07e7f62c725d Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 12 Mar 2022 15:21:15 -0400 Subject: [PATCH 09/17] Revert "* formatting" This reverts commit 1ab729e7c23b5db24a8e229d487bbc2ed81d38c3. --- frame/bounties/README.md | 46 +++++++---------- frame/bounties/src/lib.rs | 24 +++------ frame/child-bounties/README.md | 30 ++++------- frame/child-bounties/src/lib.rs | 89 ++++++++++++++++----------------- 4 files changed, 79 insertions(+), 110 deletions(-) diff --git a/frame/bounties/README.md b/frame/bounties/README.md index 232334cb1edd6..bf63fca5f34b2 100644 --- a/frame/bounties/README.md +++ b/frame/bounties/README.md @@ -2,38 +2,28 @@ ## Bounty -> NOTE: This pallet is tightly coupled with pallet-treasury. +**Note :: This pallet is tightly coupled with pallet-treasury** -A Bounty Spending is a reward for a specified body of work - or specified set of objectives - -that needs to be executed for a predefined Treasury amount to be paid out. A curator is assigned -after the bounty is approved and funded by Council, to be delegated with the responsibility of -assigning a payout address once the specified set of objectives is completed. +A Bounty Spending is a reward for a specified body of work - or specified set of objectives - that +needs to be executed for a predefined Treasury amount to be paid out. A curator is assigned after +the bounty is approved and funded by Council, to be delegated with the responsibility of assigning a +payout address once the specified set of objectives is completed. -After the Council has activated a bounty, it delegates the work that requires expertise to a -curator in exchange of a deposit. Once the curator accepts the bounty, they get to close the -active bounty. Closing the active bounty enacts a delayed payout to the payout address, the -curator fee and the return of the curator deposit. The delay allows for intervention through -regular democracy. The Council gets to unassign the curator, resulting in a new curator -election. The Council also gets to cancel the bounty if deemed necessary before assigning a -curator or once the bounty is active or payout is pending, resulting in the slash of the -curator's deposit. - -This pallet may opt into using a [`ChildBountyManager`] that enables bounties to be split into -sub-bounties, as children of anh established bounty (called the parent in the context of it's -children). - -> NOTE: The parent bounty cannot be closed if it has a non-zero number of it has active child -> bounties associated with it. +After the Council has activated a bounty, it delegates the work that requires expertise to a curator +in exchange of a deposit. Once the curator accepts the bounty, they get to close the active bounty. +Closing the active bounty enacts a delayed payout to the payout address, the curator fee and the +return of the curator deposit. The delay allows for intervention through regular democracy. The +Council gets to unassign the curator, resulting in a new curator election. The Council also gets to +cancel the bounty if deemed necessary before assigning a curator or once the bounty is active or +payout is pending, resulting in the slash of the curator's deposit. ### Terminology -Bounty: - -- **Bounty spending proposal:** A proposal to reward a predefined body of work upon completion - by the Treasury. +- **Bounty spending proposal:** A proposal to reward a predefined body of work upon completion by + the Treasury. - **Proposer:** An account proposing a bounty spending. -- **Curator:** An account managing the bounty and assigning a payout address receiving the - reward for the completion of work. +- **Curator:** An account managing the bounty and assigning a payout address receiving the reward + for the completion of work. - **Deposit:** The amount held on deposit for placing a bounty proposal plus the amount held on deposit per byte within the bounty description. - **Curator deposit:** The payment from a candidate willing to curate an approved bounty. The @@ -41,8 +31,7 @@ Bounty: - **Bounty value:** The total amount that should be paid to the Payout Address if the bounty is rewarded. - **Payout address:** The account to which the total or part of the bounty is assigned to. -- **Payout Delay:** The delay period for which a bounty beneficiary needs to wait before - claiming. +- **Payout Delay:** The delay period for which a bounty beneficiary needs to wait before claiming. - **Curator fee:** The reserved upfront payment for a curator for work related to the bounty. ## Interface @@ -50,7 +39,6 @@ Bounty: ### Dispatchable Functions Bounty protocol: - - `propose_bounty` - Propose a specific treasury amount to be earmarked for a predefined set of tasks and stake the required deposit. - `approve_bounty` - Accept a specific treasury amount to be earmarked for a predefined body of diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 85e8051250945..8cb857d97f97d 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -35,17 +35,10 @@ //! curator or once the bounty is active or payout is pending, resulting in the slash of the //! curator's deposit. //! -//! This pallet may opt into using a [`ChildBountyManager`] that enables bounties to be split into -//! sub-bounties, as children of anh established bounty (called the parent in the context of it's -//! children). -//! -//! > NOTE: The parent bounty cannot be closed if it has a non-zero number of it has active child -//! > bounties associated with it. //! //! ### Terminology //! //! Bounty: -//! //! - **Bounty spending proposal:** A proposal to reward a predefined body of work upon completion //! by the Treasury. //! - **Proposer:** An account proposing a bounty spending. @@ -67,7 +60,6 @@ //! ### Dispatchable Functions //! //! Bounty protocol: -//! //! - `propose_bounty` - Propose a specific treasury amount to be earmarked for a predefined set of //! tasks and stake the required deposit. //! - `approve_bounty` - Accept a specific treasury amount to be earmarked for a predefined body of @@ -173,9 +165,9 @@ pub enum BountyStatus { }, } -/// The child bounty manager. +/// The child-bounty manager. pub trait ChildBountyManager { - /// Get the active child bounties for a parent bounty. + /// 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. @@ -238,7 +230,7 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; - /// The child bounty manager. + /// The child-bounty manager. type ChildBountyManager: ChildBountyManager>; } @@ -263,7 +255,7 @@ 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. + /// The bounty cannot be closed because it has active child-bounties. HasActiveChildBounty, /// Too many approvals are already queued. TooManyQueued, @@ -559,7 +551,7 @@ pub mod pallet { Bounties::::try_mutate_exists(bounty_id, |maybe_bounty| -> DispatchResult { let mut bounty = maybe_bounty.as_mut().ok_or(Error::::InvalidIndex)?; - // Ensure no active child bounties before processing the call. + // Ensure no active child-bounties before processing the call. ensure!( T::ChildBountyManager::child_bounties_count(bounty_id) == 0, Error::::HasActiveChildBounty @@ -617,8 +609,8 @@ pub mod pallet { let err_amount = T::Currency::unreserve(&curator, bounty.curator_deposit); debug_assert!(err_amount.is_zero()); - // Get total child bounties curator fees, and subtract it from the parent - // curator fee (the fee in present referenced bounty, `self`). + // 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); @@ -670,7 +662,7 @@ pub mod pallet { |maybe_bounty| -> DispatchResultWithPostInfo { let bounty = maybe_bounty.as_ref().ok_or(Error::::InvalidIndex)?; - // Ensure no active child bounties before processing the call. + // Ensure no active child-bounties before processing the call. ensure!( T::ChildBountyManager::child_bounties_count(bounty_id) == 0, Error::::HasActiveChildBounty diff --git a/frame/child-bounties/README.md b/frame/child-bounties/README.md index 607b6eb58f6a1..e07996d54957a 100644 --- a/frame/child-bounties/README.md +++ b/frame/child-bounties/README.md @@ -1,29 +1,21 @@ -# Child Bounties Pallet ( `pallet-child-bounties` ) +# Child Bounties Pallet (pallet-child-bounties) ## Child Bounty -> NOTE: This pallet is tightly coupled with `pallet-treasury` and `pallet-bounties`. +> 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. +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 -Child Bounty protocol: - -- `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. +- `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. +- `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. diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 053826b453657..5a37f6682c6b2 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! # Child Bounties Pallet ( `pallet-child-bounties` ) +//! # Child Bounties Pallet ( pallet-child-bounties ) //! //! ## Child Bounty //! -//! > NOTE: This pallet is tightly coupled with `pallet-treasury` and `pallet-bounties`. +//! > 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, +//! 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. //! @@ -33,22 +33,22 @@ //! ### Dispatchable Functions //! //! Child Bounty protocol: -//! - `add_child_bounty` - Add a child bounty for a parent bounty to for dividing the work in +//! - `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 +//! - `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 +//! - `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. // Most of the business logic in this pallet has been // originally contributed by "https://github.com/shamb0", // as part of the PR - https://github.com/paritytech/substrate/pull/7965. // The code has been moved here and then refactored in order to -// extract child bounties as a separate pallet. +// extract child-bounties as a separate pallet. #![cfg_attr(not(feature = "std"), no_std)] @@ -101,7 +101,7 @@ pub struct ChildBounty { pub enum ChildBountyStatus { /// The child-bounty is added and waiting for curator assignment. Added, - /// A curator has been proposed by the parent bounty curator. Waiting for + /// A curator has been proposed by the parent-bounty curator. Waiting for /// acceptance from the child-bounty curator. CuratorProposed { /// The assigned child-bounty curator of this bounty. @@ -136,7 +136,7 @@ pub mod pallet { pub trait Config: frame_system::Config + pallet_treasury::Config + pallet_bounties::Config { - /// Maximum number of child bounties that can be added to a parent bounty. + /// Maximum number of child-bounties that can be added to a parent bounty. #[pallet::constant] type MaxActiveChildBountyCount: Get; @@ -172,7 +172,7 @@ pub mod pallet { ParentBountyNotActive, /// The bounty balance is not enough to add new child-bounty. InsufficientBountyBalance, - /// Number of child bounties exceeds limit `MaxActiveChildBountyCount`. + /// Number of child-bounties exceeds limit `MaxActiveChildBountyCount`. TooManyChildBounties, } @@ -180,18 +180,18 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// A child-bounty is added. - Added { parent_index: BountyIndex, child_index: BountyIndex }, + Added { index: BountyIndex, child_index: BountyIndex }, /// A child-bounty is awarded to a beneficiary. - Awarded { parent_index: BountyIndex, child_index: BountyIndex, beneficiary: T::AccountId }, + Awarded { index: BountyIndex, child_index: BountyIndex, beneficiary: T::AccountId }, /// A child-bounty is claimed by beneficiary. Claimed { - parent_index: BountyIndex, + index: BountyIndex, child_index: BountyIndex, payout: BalanceOf, beneficiary: T::AccountId, }, /// A child-bounty is cancelled. - Canceled { parent_index: BountyIndex, child_index: BountyIndex }, + Canceled { index: BountyIndex, child_index: BountyIndex }, } /// Number of total child bounties. @@ -199,14 +199,14 @@ pub mod pallet { #[pallet::getter(fn child_bounty_count)] pub type ChildBountyCount = StorageValue<_, BountyIndex, ValueQuery>; - /// Number of child bounties per parent bounty. + /// Number of child-bounties per parent bounty. /// Map of parent bounty index to number of child bounties. #[pallet::storage] #[pallet::getter(fn parent_child_bounties)] pub type ParentChildBounties = StorageMap<_, Twox64Concat, BountyIndex, u32, ValueQuery>; - /// child bounties that have been added. + /// Child-bounties that have been added. #[pallet::storage] #[pallet::getter(fn child_bounties)] pub type ChildBounties = StorageDoubleMap< @@ -241,7 +241,7 @@ pub mod pallet { /// parent bounty to child-bounty account, if parent bounty has enough /// funds, else the call fails. /// - /// Upper bound to maximum number of active child bounties that can be + /// Upper bound to maximum number of active child-bounties that can be /// added are managed via runtime trait config /// [`Config::MaxActiveChildBountyCount`]. /// @@ -420,7 +420,7 @@ pub mod pallet { // is reserved based on a percentage of child-bounty // value instead of fee, to avoid no deposit in case the // fee is set as zero. - let deposit = Self::calculate_child_curator_deposit( + let deposit = Self::calculate_curator_deposit( &parent_curator, curator, &child_bounty.value, @@ -446,12 +446,12 @@ pub mod pallet { /// the curator of the parent bounty, or any signed origin. /// /// For the origin other than T::RejectOrigin and the child-bounty - /// curator, parent bounty must be in active state, for this call to + /// curator, parent-bounty must be in active state, for this call to /// work. We allow child-bounty curator and T::RejectOrigin to execute - /// this call irrespective of the parent bounty state. + /// this call irrespective of the parent-bounty state. /// /// If this function is called by the `RejectOrigin` or the - /// parent bounty curator, we assume that the child-bounty curator is + /// parent-bounty curator, we assume that the child-bounty curator is /// malicious or inactive. As a result, child-bounty curator deposit is /// slashed. /// @@ -505,7 +505,7 @@ pub mod pallet { }, ChildBountyStatus::CuratorProposed { ref curator } => { // A child-bounty curator has been proposed, but not accepted yet. - // Either `RejectOrigin`, parent bounty curator or the proposed + // Either `RejectOrigin`, parent-bounty curator or the proposed // child-bounty curator can unassign the child-bounty curator. ensure!( maybe_sender.map_or(true, |sender| { @@ -543,7 +543,7 @@ pub mod pallet { update_due < frame_system::Pallet::::block_number() { // Slash the child-bounty curator if - // + the call is made by the parent bounty curator. + // + the call is made by the parent-bounty curator. // + or the curator is inactive. slash_curator(curator, &mut child_bounty.curator_deposit); // Continue to change bounty status below. @@ -575,7 +575,7 @@ pub mod pallet { /// /// The beneficiary will be able to claim the funds after a delay. /// - /// The dispatch origin for this call must be the parent curator or + /// The dispatch origin for this call must be the master curator or /// curator of this child-bounty. /// /// Parent bounty must be in active state, for this child-bounty call to @@ -630,7 +630,7 @@ pub mod pallet { // Trigger the event Awarded. Self::deposit_event(Event::::Awarded { - parent_index: parent_bounty_id, + index: parent_bounty_id, child_index: child_bounty_id, beneficiary, }); @@ -716,7 +716,7 @@ pub mod pallet { // Trigger the Claimed event. Self::deposit_event(Event::::Claimed { - parent_index: parent_bounty_id, + index: parent_bounty_id, child_index: child_bounty_id, payout, beneficiary: beneficiary.clone(), @@ -787,19 +787,19 @@ pub mod pallet { impl Pallet { // This function will calculate the deposit of a curator. - fn calculate_child_curator_deposit( + fn calculate_curator_deposit( parent_curator: &T::AccountId, child_curator: &T::AccountId, - child_bounty_value: &BalanceOf, - child_bounty_fee: &BalanceOf, + bounty_value: &BalanceOf, + bounty_fee: &BalanceOf, ) -> BalanceOf { - let deposit: BalanceOf = if child_bounty_fee.is_zero() { + let deposit: BalanceOf = if bounty_fee.is_zero() { if parent_curator == child_curator { return Zero::zero() } - T::ChildCuratorDepositMultiplierWithNoFee::get() * *child_bounty_value + T::ChildCuratorDepositMultiplierWithNoFee::get() * *bounty_value } else { - T::ChildCuratorDepositMultiplierWithFee::get() * *child_bounty_fee + T::ChildCuratorDepositMultiplierWithFee::get() * *bounty_fee }; deposit @@ -828,16 +828,13 @@ impl Pallet { }; ChildBounties::::insert(parent_bounty_id, child_bounty_id, &child_bounty); ChildBountyDescriptions::::insert(child_bounty_id, description); - Self::deposit_event(Event::Added { - parent_index: parent_bounty_id, - child_index: child_bounty_id, - }); + Self::deposit_event(Event::Added { index: parent_bounty_id, child_index: child_bounty_id }); } fn ensure_bounty_active( - parent_bounty_id: BountyIndex, + bounty_id: BountyIndex, ) -> Result<(T::AccountId, T::BlockNumber), DispatchError> { - let parent_bounty = pallet_bounties::Pallet::::bounties(parent_bounty_id) + let parent_bounty = pallet_bounties::Pallet::::bounties(bounty_id) .ok_or(BountiesError::::InvalidIndex)?; if let BountyStatus::Active { curator, update_due } = parent_bounty.get_status() { Ok((curator, update_due)) @@ -862,7 +859,7 @@ impl Pallet { // Nothing extra to do besides the removal of the child-bounty below. }, ChildBountyStatus::Active { curator } => { - // Cancelled by parent curator or RejectOrigin, + // Cancelled by master curator or RejectOrigin, // refund deposit of the working child-bounty curator. let _ = T::Currency::unreserve(curator, child_bounty.curator_deposit); // Then execute removal of the child-bounty below. @@ -877,7 +874,7 @@ impl Pallet { }, } - // Revert the curator fee back to parent bounty curator & + // Revert the curator fee back to parent-bounty curator & // reduce the active child-bounty count. ChildrenCuratorFees::::mutate(parent_bounty_id, |value| { *value = value.saturating_sub(child_bounty.fee) @@ -905,7 +902,7 @@ impl Pallet { *maybe_child_bounty = None; Self::deposit_event(Event::::Canceled { - parent_index: parent_bounty_id, + index: parent_bounty_id, child_index: child_bounty_id, }); Ok(()) @@ -915,7 +912,7 @@ impl Pallet { } // Implement ChildBountyManager to connect with the bounties pallet. This is -// where we pass the active child bounties and child curator fees to the parent +// where we pass the active child-bounties and child curator fees to the parent // bounty. impl pallet_bounties::ChildBountyManager> for Pallet { fn child_bounties_count( From 4eeeb94fac87360cc7694f1c8e02a88836594199 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 22:32:51 -0400 Subject: [PATCH 10/17] update bounties logic to use bounds --- frame/bounties/src/lib.rs | 39 +++++++++++++---------- frame/bounties/src/tests.rs | 63 ++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 8cb857d97f97d..a828c8e1a4742 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -196,19 +196,20 @@ pub mod pallet { #[pallet::constant] type BountyUpdatePeriod: Get; - /// If the bounty has a fee, the curator deposit is a percentage of that fee. Otherwise, we - /// use the `CuratorDepositMultiplierWithNoFee` multiplied by the value of the bounty to - /// determine the deposit. + /// The curator deposit is calculated as a percentage of the curator fee. + /// + /// This deposit has optional upper and lower bounds with `CuratorDepositMax` and + /// `CuratorDepositMin`. #[pallet::constant] - type CuratorDepositMultiplierWithFee: Get; + type CuratorDepositMultiplier: Get; - /// If the bounty has no fee, we still want to make sure the curator has some non-zero - /// deposit, so then we use this multiplier along side the value (which should be non-zero) - /// to determine the curator deposit. - /// - /// If the bounty has a fee, see `CuratorDepositMultiplierWithFee` above. + /// Maximum amount of funds that should be placed in a deposit for making a proposal. #[pallet::constant] - type CuratorDepositMultiplierWithNoFee: Get; + type CuratorDepositMax: Get>>; + + /// Maximum amount of funds that should be placed in a deposit for making a proposal. + #[pallet::constant] + type CuratorDepositMin: Get>>; /// Minimum value for a bounty. #[pallet::constant] @@ -511,7 +512,7 @@ pub mod pallet { BountyStatus::CuratorProposed { ref curator } => { ensure!(signer == *curator, Error::::RequireCurator); - let deposit = Self::calculate_curator_deposit(bounty.value, bounty.fee); + let deposit = Self::calculate_curator_deposit(bounty.fee); T::Currency::reserve(curator, deposit)?; bounty.curator_deposit = deposit; @@ -771,12 +772,16 @@ pub mod pallet { } impl Pallet { - fn calculate_curator_deposit(value: BalanceOf, fee: BalanceOf) -> BalanceOf { - let deposit = if fee.is_zero() { - T::CuratorDepositMultiplierWithNoFee::get() * value - } else { - T::CuratorDepositMultiplierWithFee::get() * fee - }; + fn calculate_curator_deposit(fee: BalanceOf) -> BalanceOf { + let mut deposit = T::CuratorDepositMultiplier::get() * fee; + + if let Some(max_deposit) = T::CuratorDepositMax::get() { + deposit = deposit.min(max_deposit) + } + + if let Some(min_deposit) = T::CuratorDepositMin::get() { + deposit = deposit.max(min_deposit) + } deposit } diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 30887579755f7..bec11f3dcf2c0 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -60,6 +60,8 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } +type Balance = u64; + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -91,7 +93,7 @@ impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type Balance = u64; + type Balance = Balance; type Event = Event; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; @@ -128,9 +130,10 @@ impl pallet_treasury::Config for Test { parameter_types! { // This will be 50% of the bounty fee. - pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); - // This will be 1% of the bounty value. - pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub const CuratorDepositMax: Balance = 1_000; + pub const CuratorDepositMin: Balance = 3; + } impl Config for Test { @@ -138,8 +141,9 @@ impl Config for Test { type BountyDepositBase = ConstU64<80>; type BountyDepositPayoutDelay = ConstU64<3>; type BountyUpdatePeriod = ConstU64<20>; - type CuratorDepositMultiplierWithFee = CuratorDepositMultiplierWithFee; - type CuratorDepositMultiplierWithNoFee = CuratorDepositMultiplierWithNoFee; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMax = CuratorDepositMax; + type CuratorDepositMin = CuratorDepositMin; type BountyValueMinimum = ConstU64<1>; type DataDepositPerByte = ConstU64<1>; type MaximumReasonLength = ConstU32<16384>; @@ -549,13 +553,14 @@ fn assign_curator_works() { Error::::InvalidFee ); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, + fee, curator_deposit: 0, value: 50, bond: 85, @@ -573,20 +578,22 @@ fn assign_curator_works() { assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + let expected_deposit = Bounties::calculate_curator_deposit(fee); + assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, - curator_deposit: 2, + fee, + curator_deposit: expected_deposit, value: 50, bond: 85, status: BountyStatus::Active { curator: 4, update_due: 22 }, } ); - assert_eq!(Balances::free_balance(&4), 8); - assert_eq!(Balances::reserved_balance(&4), 2); + assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); + assert_eq!(Balances::reserved_balance(&4), expected_deposit); }); } @@ -602,17 +609,17 @@ fn unassign_curator_works() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_noop!(Bounties::unassign_curator(Origin::signed(1), 0), BadOrigin); - assert_ok!(Bounties::unassign_curator(Origin::signed(4), 0)); assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, + fee, curator_deposit: 0, value: 50, bond: 85, @@ -620,19 +627,17 @@ fn unassign_curator_works() { } ); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); - + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); Balances::make_free_balance_be(&4, 10); - assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - + let expected_deposit = Bounties::calculate_curator_deposit(fee); assert_ok!(Bounties::unassign_curator(Origin::root(), 0)); assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, + fee, curator_deposit: 0, value: 50, bond: 85, @@ -640,8 +645,8 @@ fn unassign_curator_works() { } ); - assert_eq!(Balances::free_balance(&4), 8); - assert_eq!(Balances::reserved_balance(&4), 0); // slashed 2 + assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); + assert_eq!(Balances::reserved_balance(&4), 0); // slashed curator deposit }); } @@ -658,10 +663,12 @@ fn award_and_claim_bounty_works() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - assert_eq!(Balances::free_balance(4), 8); // inital 10 - 2 deposit + let expected_deposit = Bounties::calculate_curator_deposit(fee); + assert_eq!(Balances::free_balance(4), 10 - expected_deposit); assert_noop!( Bounties::award_bounty(Origin::signed(1), 0, 3), @@ -674,8 +681,8 @@ fn award_and_claim_bounty_works() { Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, - curator_deposit: 2, + fee, + curator_deposit: expected_deposit, value: 50, bond: 85, status: BountyStatus::PendingPayout { curator: 4, beneficiary: 3, unlock_at: 5 }, @@ -1064,7 +1071,7 @@ fn accept_curator_handles_different_deposit_calculations() { assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); - let expected_deposit = CuratorDepositMultiplierWithFee::get() * fee; + let expected_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); assert_eq!(Balances::reserved_balance(&user), expected_deposit); @@ -1086,7 +1093,7 @@ fn accept_curator_handles_different_deposit_calculations() { assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); - let expected_deposit = CuratorDepositMultiplierWithNoFee::get() * value; + let expected_deposit = CuratorDepositMin::get(); assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); assert_eq!(Balances::reserved_balance(&user), expected_deposit); }); From 4db366a23d289ba642d15bdc9f13f40afcf33627 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 22:40:04 -0400 Subject: [PATCH 11/17] fix child --- frame/bounties/src/lib.rs | 2 +- frame/child-bounties/src/tests.rs | 37 ++++++++++++++++++------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index a828c8e1a4742..edcaff571ed01 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -772,7 +772,7 @@ pub mod pallet { } impl Pallet { - fn calculate_curator_deposit(fee: BalanceOf) -> BalanceOf { + pub fn calculate_curator_deposit(fee: BalanceOf) -> BalanceOf { let mut deposit = T::CuratorDepositMultiplier::get() * fee; if let Some(max_deposit) = T::CuratorDepositMax::get() { diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index 86e8ae7177f39..aab740cb9d801 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -65,6 +65,8 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } +type Balance = u64; + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -96,7 +98,7 @@ impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type Balance = u64; + type Balance = Balance; type Event = Event; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; @@ -130,16 +132,20 @@ impl pallet_treasury::Config for Test { type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); - pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); + // This will be 50% of the bounty fee. + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub const CuratorDepositMax: Balance = 1_000; + pub const CuratorDepositMin: Balance = 3; + } impl pallet_bounties::Config for Test { type Event = Event; type BountyDepositBase = ConstU64<80>; type BountyDepositPayoutDelay = ConstU64<3>; type BountyUpdatePeriod = ConstU64<10>; - type CuratorDepositMultiplierWithFee = CuratorDepositMultiplierWithFee; - type CuratorDepositMultiplierWithNoFee = CuratorDepositMultiplierWithNoFee; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMax = CuratorDepositMax; + type CuratorDepositMin = CuratorDepositMin; type BountyValueMinimum = ConstU64<5>; type DataDepositPerByte = ConstU64<1>; type MaximumReasonLength = ConstU32<300>; @@ -231,7 +237,7 @@ fn add_child_bounty() { assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // This verifies that the accept curator logic took a deposit. - let expected_deposit = CuratorDepositMultiplierWithFee::get() * fee; + let expected_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!(Balances::reserved_balance(&4), expected_deposit); assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); @@ -311,8 +317,8 @@ fn child_bounty_assign_curator() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); - + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // Bounty account status before adding child-bounty. @@ -321,8 +327,9 @@ fn child_bounty_assign_curator() { // Check the balance of parent curator. // Curator deposit is reserved for parent curator on parent bounty. - assert_eq!(Balances::free_balance(4), 99); - assert_eq!(Balances::reserved_balance(4), 2); + let expected_deposit = Bounties::calculate_curator_deposit(fee); + assert_eq!(Balances::free_balance(4), 101 - expected_deposit); + assert_eq!(Balances::reserved_balance(4), expected_deposit); // Add child-bounty. // Acc-4 is the parent curator & make sure enough deposit. @@ -352,8 +359,6 @@ fn child_bounty_assign_curator() { } ); - let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; - // Check the balance of parent curator. assert_eq!(Balances::free_balance(4), 101 - expected_deposit); assert_eq!(Balances::reserved_balance(4), expected_deposit); @@ -365,20 +370,22 @@ fn child_bounty_assign_curator() { assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; + assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, fee, - curator_deposit: expected_deposit, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); // Deposit for child-bounty curator deposit is reserved. - assert_eq!(Balances::free_balance(8), 101 - expected_deposit); - assert_eq!(Balances::reserved_balance(8), expected_deposit); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); + assert_eq!(Balances::reserved_balance(8), expected_child_deposit); // Bounty account status at exit. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 40); From 818ba1dbd344f38cce50e9256de5dbbe8351c0cc Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 22:49:52 -0400 Subject: [PATCH 12/17] bounties test for max --- frame/bounties/src/lib.rs | 6 +++--- frame/bounties/src/tests.rs | 32 ++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index edcaff571ed01..ad14c96f576c1 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -512,7 +512,7 @@ pub mod pallet { BountyStatus::CuratorProposed { ref curator } => { ensure!(signer == *curator, Error::::RequireCurator); - let deposit = Self::calculate_curator_deposit(bounty.fee); + let deposit = Self::calculate_curator_deposit(&bounty.fee); T::Currency::reserve(curator, deposit)?; bounty.curator_deposit = deposit; @@ -772,8 +772,8 @@ pub mod pallet { } impl Pallet { - pub fn calculate_curator_deposit(fee: BalanceOf) -> BalanceOf { - let mut deposit = T::CuratorDepositMultiplier::get() * fee; + pub fn calculate_curator_deposit(fee: &BalanceOf) -> BalanceOf { + let mut deposit = T::CuratorDepositMultiplier::get() * *fee; if let Some(max_deposit) = T::CuratorDepositMax::get() { deposit = deposit.min(max_deposit) diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index bec11f3dcf2c0..9a84bd687abc1 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -578,7 +578,7 @@ fn assign_curator_works() { assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - let expected_deposit = Bounties::calculate_curator_deposit(fee); + let expected_deposit = Bounties::calculate_curator_deposit(&fee); assert_eq!( Bounties::bounties(0).unwrap(), @@ -630,7 +630,7 @@ fn unassign_curator_works() { assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); Balances::make_free_balance_be(&4, 10); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - let expected_deposit = Bounties::calculate_curator_deposit(fee); + let expected_deposit = Bounties::calculate_curator_deposit(&fee); assert_ok!(Bounties::unassign_curator(Origin::root(), 0)); assert_eq!( @@ -667,7 +667,7 @@ fn award_and_claim_bounty_works() { assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - let expected_deposit = Bounties::calculate_curator_deposit(fee); + let expected_deposit = Bounties::calculate_curator_deposit(&fee); assert_eq!(Balances::free_balance(4), 10 - expected_deposit); assert_noop!( @@ -1075,7 +1075,7 @@ fn accept_curator_handles_different_deposit_calculations() { assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); assert_eq!(Balances::reserved_balance(&user), expected_deposit); - // Case 2: Without a fee + // Case 2: Lower bound let user = 2; let bounty_index = 1; let value = 35; @@ -1096,5 +1096,29 @@ fn accept_curator_handles_different_deposit_calculations() { let expected_deposit = CuratorDepositMin::get(); assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); assert_eq!(Balances::reserved_balance(&user), expected_deposit); + + // Case 3: Upper bound + let user = 3; + let bounty_index = 2; + let value = 1_000_000; + let fee = 50_000; + let starting_balance = fee * 2; + + Balances::make_free_balance_be(&Treasury::account_id(), value * 2); + Balances::make_free_balance_be(&user, starting_balance); + Balances::make_free_balance_be(&0, starting_balance); + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), value, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), bounty_index)); + + System::set_block_number(3); + >::on_initialize(3); + + assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); + assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); + + let expected_deposit = CuratorDepositMax::get(); + assert_eq!(Balances::free_balance(&user), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(&user), expected_deposit); }); } From a92af0bc5f88436edf8c877756a5eaaaa903e011 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 23:15:52 -0400 Subject: [PATCH 13/17] update tests --- frame/child-bounties/src/lib.rs | 33 ++------ frame/child-bounties/src/tests.rs | 126 +++++++++++++++--------------- 2 files changed, 70 insertions(+), 89 deletions(-) diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 5a37f6682c6b2..35d0e11c97d79 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -66,7 +66,7 @@ use frame_support::traits::{ use sp_runtime::{ traits::{AccountIdConversion, BadOrigin, CheckedSub, Saturating, StaticLookup, Zero}, - DispatchResult, Permill, RuntimeDebug, + DispatchResult, RuntimeDebug, }; use frame_support::pallet_prelude::*; @@ -144,21 +144,6 @@ pub mod pallet { #[pallet::constant] type ChildBountyValueMinimum: Get>; - /// In the case a child bounty has a non-zero fee, the deposit for the curator - /// will be a fraction of that fee based on the multiplier below. - #[pallet::constant] - type ChildCuratorDepositMultiplierWithFee: Get; - - /// In the case a child bounty has no fee, we use this multiplier in the following logic: - /// - if the child curator is the same as the parent curator, we know they already made a - /// deposit, and thus we don't need to take another deposit here. - /// - if the child curator is different, since there is no fee, we use this multiplier - /// against the total value of the bounty, which should always be non-zero. - /// - /// When there is a fee set, we use `ChildCuratorDepositMultiplierWithFee`, see above. - #[pallet::constant] - type ChildCuratorDepositMultiplierWithNoFee: Get; - /// The overarching event type. type Event: From> + IsType<::Event>; @@ -423,7 +408,6 @@ pub mod pallet { let deposit = Self::calculate_curator_deposit( &parent_curator, curator, - &child_bounty.value, &child_bounty.fee, ); @@ -790,19 +774,14 @@ impl Pallet { fn calculate_curator_deposit( parent_curator: &T::AccountId, child_curator: &T::AccountId, - bounty_value: &BalanceOf, bounty_fee: &BalanceOf, ) -> BalanceOf { - let deposit: BalanceOf = if bounty_fee.is_zero() { - if parent_curator == child_curator { - return Zero::zero() - } - T::ChildCuratorDepositMultiplierWithNoFee::get() * *bounty_value - } else { - T::ChildCuratorDepositMultiplierWithFee::get() * *bounty_fee - }; + if parent_curator == child_curator { + return Zero::zero() + } - deposit + // We just use the same logic from the parent bounties pallet. + pallet_bounties::Pallet::::calculate_curator_deposit(bounty_fee) } /// The account ID of a child-bounty account. diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index aab740cb9d801..82f8eb7c911a4 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -152,18 +152,10 @@ impl pallet_bounties::Config for Test { type WeightInfo = (); type ChildBountyManager = ChildBounties; } -parameter_types! { - // This will be 50% of the bounty fee. - pub const ChildCuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); - // This will be 1% of the bounty value. - pub const ChildCuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); -} impl pallet_child_bounties::Config for Test { type Event = Event; type MaxActiveChildBountyCount = ConstU32<2>; type ChildBountyValueMinimum = ConstU64<1>; - type ChildCuratorDepositMultiplierWithFee = ChildCuratorDepositMultiplierWithFee; - type ChildCuratorDepositMultiplierWithNoFee = ChildCuratorDepositMultiplierWithNoFee; type WeightInfo = (); } @@ -327,7 +319,7 @@ fn child_bounty_assign_curator() { // Check the balance of parent curator. // Curator deposit is reserved for parent curator on parent bounty. - let expected_deposit = Bounties::calculate_curator_deposit(fee); + let expected_deposit = Bounties::calculate_curator_deposit(&fee); assert_eq!(Balances::free_balance(4), 101 - expected_deposit); assert_eq!(Balances::reserved_balance(4), expected_deposit); @@ -345,7 +337,7 @@ fn child_bounty_assign_curator() { assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); - let fee = 4u64; + let fee = 6u64; assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_eq!( @@ -370,7 +362,7 @@ fn child_bounty_assign_curator() { assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); - let expected_child_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), @@ -430,7 +422,7 @@ fn award_claim_child_bounty() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); // Propose and accept curator for child-bounty. - let fee = 4; + let fee = 8; assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); @@ -443,7 +435,7 @@ fn award_claim_child_bounty() { assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); - let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; + let expected_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { @@ -612,8 +604,8 @@ fn close_child_bounty_pending() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); - + let parent_fee = 6; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, parent_fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // Child-bounty. @@ -622,9 +614,10 @@ fn close_child_bounty_pending() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); // Propose and accept curator for child-bounty. - let fee = 4; - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 4)); + let child_fee = 4; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, child_fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMin::get(); assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); @@ -638,9 +631,8 @@ fn close_child_bounty_pending() { assert_eq!(ChildBounties::parent_child_bounties(0), 1); // Ensure no changes in child-bounty curator balance. - let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * fee; - assert_eq!(Balances::reserved_balance(8), expected_deposit); - assert_eq!(Balances::free_balance(8), 101 - expected_deposit); + assert_eq!(Balances::reserved_balance(8), expected_child_deposit); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); // Child-bounty account status. assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); @@ -778,7 +770,6 @@ fn child_bounty_active_unassign_curator() { >::on_initialize(2); assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); - assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // Create Child-bounty. @@ -789,16 +780,18 @@ fn child_bounty_active_unassign_curator() { >::on_initialize(3); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 6; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); @@ -815,27 +808,29 @@ fn child_bounty_active_unassign_curator() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, + fee, curator_deposit: 0, status: ChildBountyStatus::Added, } ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); assert_eq!(Balances::reserved_balance(8), 0); // slashed // Propose and accept curator for child-bounty again. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 7, 2)); + let fee = 2; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 7, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(7), 0, 0)); + let expected_child_deposit = CuratorDepositMin::get(); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 7 }, } ); @@ -859,7 +854,7 @@ fn child_bounty_active_unassign_curator() { ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(7), 100); + assert_eq!(Balances::free_balance(7), 101 - expected_child_deposit); assert_eq!(Balances::reserved_balance(7), 0); // slashed // Propose and accept curator for child-bounty again. @@ -871,8 +866,8 @@ fn child_bounty_active_unassign_curator() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 6 }, } ); @@ -900,16 +895,18 @@ fn child_bounty_active_unassign_curator() { assert_eq!(Balances::reserved_balance(6), 0); // Propose and accept curator for child-bounty one last time. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 6, 2)); + let fee = 2; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 6, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(6), 0, 0)); + let expected_child_deposit = CuratorDepositMin::get(); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 6 }, } ); @@ -943,7 +940,7 @@ fn child_bounty_active_unassign_curator() { ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(6), 100); // slashed + assert_eq!(Balances::free_balance(6), 101 - expected_child_deposit); // slashed assert_eq!(Balances::reserved_balance(6), 0); }); } @@ -983,16 +980,18 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { >::on_initialize(3); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 8; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); @@ -1022,14 +1021,14 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, + fee, curator_deposit: 0, status: ChildBountyStatus::Added, } ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); assert_eq!(Balances::reserved_balance(8), 0); // slashed System::set_block_number(6); @@ -1043,16 +1042,18 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { >::on_initialize(7); // Propose and accept curator for child-bounty again. - assert_ok!(ChildBounties::propose_curator(Origin::signed(5), 0, 0, 7, 2)); + let fee = 2; + assert_ok!(ChildBounties::propose_curator(Origin::signed(5), 0, 0, 7, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(7), 0, 0)); + let expected_deposit = CuratorDepositMin::get(); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_deposit, status: ChildBountyStatus::Active { curator: 7 }, } ); @@ -1180,25 +1181,26 @@ fn children_curator_fee_calculation_test() { System::set_block_number(4); >::on_initialize(4); - // Propose curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 6; + // Propose curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); // Check curator fee added to the sum. - assert_eq!(ChildBounties::children_curator_fees(0), 2); - + assert_eq!(ChildBounties::children_curator_fees(0), fee); // Accept curator for child-bounty. assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); - // Award child-bounty. assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; + assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::PendingPayout { curator: 8, beneficiary: 7, @@ -1224,7 +1226,7 @@ fn children_curator_fee_calculation_test() { assert_ok!(Bounties::claim_bounty(Origin::signed(9), 0)); // Ensure parent-bounty curator received correctly reduced fee. - assert_eq!(Balances::free_balance(4), 105); // 101 + 6 - 2 + assert_eq!(Balances::free_balance(4), 101 + 6 - fee); // 101 + 6 - 2 assert_eq!(Balances::reserved_balance(4), 0); // Verify parent-bounty beneficiary balance. @@ -1241,8 +1243,8 @@ fn accept_curator_handles_different_deposit_calculations() { // Setup a parent bounty. let parent_curator = 0; let parent_index = 0; - let parent_value = 10_000; - let parent_fee = 1_000; + let parent_value = 1_000_000; + let parent_fee = 10_000; System::set_block_number(1); Balances::make_free_balance_be(&Treasury::account_id(), parent_value * 3); @@ -1266,7 +1268,7 @@ fn accept_curator_handles_different_deposit_calculations() { assert_ok!(Bounties::accept_curator(Origin::signed(parent_curator), parent_index)); // Now we can start creating some child bounties. - // Case 1: There is a fee, we don't care if parent and child curator are the same. + // Case 1: There is a fee, parent and child curator are not the same. let child_index = 0; let child_curator = 1; @@ -1296,16 +1298,16 @@ fn accept_curator_handles_different_deposit_calculations() { child_index )); - let expected_deposit = ChildCuratorDepositMultiplierWithFee::get() * child_fee; + let expected_deposit = CuratorDepositMultiplier::get() * child_fee; assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); - // Case 2: There is no fee, and the parent and child curator are the same. + // Case 2: Parent and child curator are the same. let child_index = 1; let child_curator = parent_curator; // The same as parent bounty curator let child_value = 1_000; - let child_fee = 0; // No fee + let child_fee = 10; let free_before = Balances::free_balance(&parent_curator); let reserved_before = Balances::reserved_balance(&parent_curator); @@ -1335,12 +1337,12 @@ fn accept_curator_handles_different_deposit_calculations() { assert_eq!(Balances::free_balance(child_curator), free_before); assert_eq!(Balances::reserved_balance(child_curator), reserved_before); - // Case 3: There is no fee, and the parent and child curator are not the same. + // Case 3: Upper Limit let child_index = 2; let child_curator = 2; - let child_value = 1_000; - let child_fee = 0; // No fee + let child_value = 10_000; + let child_fee = 5_000; Balances::make_free_balance_be(&child_curator, starting_balance); assert_ok!(ChildBounties::add_child_bounty( @@ -1364,7 +1366,7 @@ fn accept_curator_handles_different_deposit_calculations() { child_index )); - let expected_deposit = ChildCuratorDepositMultiplierWithNoFee::get() * child_value; + let expected_deposit = CuratorDepositMax::get(); assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); }); From abc5b23e08b83f932d35fb8497ad5b6478d2c528 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 23:19:01 -0400 Subject: [PATCH 14/17] check min bound --- frame/child-bounties/src/tests.rs | 38 ++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index 82f8eb7c911a4..61545561a26c3 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -1268,7 +1268,7 @@ fn accept_curator_handles_different_deposit_calculations() { assert_ok!(Bounties::accept_curator(Origin::signed(parent_curator), parent_index)); // Now we can start creating some child bounties. - // Case 1: There is a fee, parent and child curator are not the same. + // Case 1: Parent and child curator are not the same. let child_index = 0; let child_curator = 1; @@ -1369,5 +1369,41 @@ fn accept_curator_handles_different_deposit_calculations() { let expected_deposit = CuratorDepositMax::get(); assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); + + // There is a max number of child bounties at a time. + assert_ok!(ChildBounties::impl_close_child_bounty(parent_index, child_index)); + + // Case 4: Lower Limit + + let child_index = 3; + let child_curator = 3; + let child_value = 10_000; + let child_fee = 0; + + Balances::make_free_balance_be(&child_curator, starting_balance); + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(5); + >::on_initialize(5); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + let expected_deposit = CuratorDepositMin::get(); + assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); }); } From b307ee4195330cde84687249eb18ad6bafcd9574 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 23:27:47 -0400 Subject: [PATCH 15/17] update node --- bin/node/runtime/src/lib.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 1e2f4ffe991b4..df1e485ac44cd 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -929,15 +929,8 @@ parameter_types! { pub const TipFindersFee: Percent = Percent::from_percent(20); pub const TipReportDepositBase: Balance = 1 * DOLLARS; pub const DataDepositPerByte: Balance = 1 * CENTS; - pub const BountyDepositBase: Balance = 1 * DOLLARS; - pub const CuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); - pub const CuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); - pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); - pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; pub const MaximumReasonLength: u32 = 300; - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); - pub const BountyValueMinimum: Balance = 5 * DOLLARS; pub const MaxApprovals: u32 = 100; } @@ -965,13 +958,25 @@ impl pallet_treasury::Config for Runtime { type MaxApprovals = MaxApprovals; } +parameter_types! { + pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub const BountyValueMinimum: Balance = 5 * DOLLARS; + pub const BountyDepositBase: Balance = 1 * DOLLARS; + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub const CuratorDepositMin: Balance = 1 * DOLLARS; + pub const CuratorDepositMax: Balance = 100 * DOLLARS; + pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; + pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; +} + impl pallet_bounties::Config for Runtime { type Event = Event; type BountyDepositBase = BountyDepositBase; type BountyDepositPayoutDelay = BountyDepositPayoutDelay; type BountyUpdatePeriod = BountyUpdatePeriod; - type CuratorDepositMultiplierWithFee = CuratorDepositMultiplierWithFee; - type CuratorDepositMultiplierWithNoFee = CuratorDepositMultiplierWithNoFee; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMin = CuratorDepositMin; + type CuratorDepositMax = CuratorDepositMax; type BountyValueMinimum = BountyValueMinimum; type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = MaximumReasonLength; @@ -981,16 +986,12 @@ impl pallet_bounties::Config for Runtime { parameter_types! { pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS; - pub const ChildCuratorDepositMultiplierWithFee: Permill = Permill::from_percent(50); - pub const ChildCuratorDepositMultiplierWithNoFee: Permill = Permill::from_percent(1); } impl pallet_child_bounties::Config for Runtime { type Event = Event; type MaxActiveChildBountyCount = ConstU32<5>; type ChildBountyValueMinimum = ChildBountyValueMinimum; - type ChildCuratorDepositMultiplierWithFee = ChildCuratorDepositMultiplierWithFee; - type ChildCuratorDepositMultiplierWithNoFee = ChildCuratorDepositMultiplierWithNoFee; type WeightInfo = pallet_child_bounties::weights::SubstrateWeight; } From 3e7ad95e3bfa12c81f86f18b0f37f12650beb6ca Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 22 Mar 2022 23:41:36 -0400 Subject: [PATCH 16/17] remove stale comment --- frame/child-bounties/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 35d0e11c97d79..2fea61c045cf6 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -401,10 +401,7 @@ pub mod pallet { { ensure!(signer == *curator, BountiesError::::RequireCurator); - // Reserve child-bounty curator deposit. Curator deposit - // is reserved based on a percentage of child-bounty - // value instead of fee, to avoid no deposit in case the - // fee is set as zero. + // Reserve child-bounty curator deposit. let deposit = Self::calculate_curator_deposit( &parent_curator, curator, From c02d524f51444182c34ed110eede291ab8fc4fb2 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 23 Mar 2022 08:15:55 -0400 Subject: [PATCH 17/17] Update frame/bounties/src/lib.rs --- frame/bounties/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index ad14c96f576c1..98f2da305a06d 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -207,7 +207,7 @@ pub mod pallet { #[pallet::constant] type CuratorDepositMax: Get>>; - /// Maximum amount of funds that should be placed in a deposit for making a proposal. + /// Minimum amount of funds that should be placed in a deposit for making a proposal. #[pallet::constant] type CuratorDepositMin: Get>>;