mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 23:31:07 +00:00
Improve Bounties and Child Bounties Deposit Logic (#11014)
* basic idea * make tests better * update bounties pallet to also have similar logic * new test verifies logic for bounty pallet * add test for new child logic * better name * make `node` compile with bounties changes * * formatting * use uniform notion of parent and child, no "master" or "general" entity * README updated to match comments * Revert "* formatting" This reverts commit 1ab729e7c23b5db24a8e229d487bbc2ed81d38c3. * update bounties logic to use bounds * fix child * bounties test for max * update tests * check min bound * update node * remove stale comment * Update frame/bounties/src/lib.rs Co-authored-by: Dan Shields <nukemandan@protonmail.com>
This commit is contained in:
@@ -220,7 +220,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
|
||||
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 {}
|
||||
@@ -827,7 +827,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<Runtime>;
|
||||
type MaxProposals = MaxProposals;
|
||||
}
|
||||
@@ -929,17 +929,9 @@ 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 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;
|
||||
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 {
|
||||
@@ -966,12 +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 BountyCuratorDeposit = BountyCuratorDeposit;
|
||||
type CuratorDepositMultiplier = CuratorDepositMultiplier;
|
||||
type CuratorDepositMin = CuratorDepositMin;
|
||||
type CuratorDepositMax = CuratorDepositMax;
|
||||
type BountyValueMinimum = BountyValueMinimum;
|
||||
type DataDepositPerByte = DataDepositPerByte;
|
||||
type MaximumReasonLength = MaximumReasonLength;
|
||||
@@ -979,11 +984,14 @@ impl pallet_bounties::Config for Runtime {
|
||||
type ChildBountyManager = ChildBounties;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS;
|
||||
}
|
||||
|
||||
impl pallet_child_bounties::Config for Runtime {
|
||||
type Event = Event;
|
||||
type MaxActiveChildBountyCount = MaxActiveChildBountyCount;
|
||||
type MaxActiveChildBountyCount = ConstU32<5>;
|
||||
type ChildBountyValueMinimum = ChildBountyValueMinimum;
|
||||
type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase;
|
||||
type WeightInfo = pallet_child_bounties::weights::SubstrateWeight<Runtime>;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,10 +196,20 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type BountyUpdatePeriod: Get<Self::BlockNumber>;
|
||||
|
||||
/// Percentage of the curator fee that will be reserved upfront as deposit for bounty
|
||||
/// curator.
|
||||
/// 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 BountyCuratorDeposit: Get<Permill>;
|
||||
type CuratorDepositMultiplier: Get<Permill>;
|
||||
|
||||
/// Maximum amount of funds that should be placed in a deposit for making a proposal.
|
||||
#[pallet::constant]
|
||||
type CuratorDepositMax: Get<Option<BalanceOf<Self>>>;
|
||||
|
||||
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
||||
#[pallet::constant]
|
||||
type CuratorDepositMin: Get<Option<BalanceOf<Self>>>;
|
||||
|
||||
/// Minimum value for a bounty.
|
||||
#[pallet::constant]
|
||||
@@ -502,7 +512,7 @@ pub mod pallet {
|
||||
BountyStatus::CuratorProposed { ref curator } => {
|
||||
ensure!(signer == *curator, Error::<T>::RequireCurator);
|
||||
|
||||
let deposit = T::BountyCuratorDeposit::get() * bounty.fee;
|
||||
let deposit = Self::calculate_curator_deposit(&bounty.fee);
|
||||
T::Currency::reserve(curator, deposit)?;
|
||||
bounty.curator_deposit = deposit;
|
||||
|
||||
@@ -762,7 +772,19 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
// Add public immutables and private mutables.
|
||||
pub fn calculate_curator_deposit(fee: &BalanceOf<T>) -> BalanceOf<T> {
|
||||
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
|
||||
}
|
||||
|
||||
/// The account ID of the treasury pot.
|
||||
///
|
||||
|
||||
@@ -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>;
|
||||
@@ -125,15 +127,23 @@ impl pallet_treasury::Config for Test {
|
||||
type SpendFunds = Bounties;
|
||||
type MaxApprovals = ConstU32<100>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
|
||||
// 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 Config for Test {
|
||||
type Event = Event;
|
||||
type BountyDepositBase = ConstU64<80>;
|
||||
type BountyDepositPayoutDelay = ConstU64<3>;
|
||||
type BountyUpdatePeriod = ConstU64<20>;
|
||||
type BountyCuratorDeposit = BountyCuratorDeposit;
|
||||
type CuratorDepositMultiplier = CuratorDepositMultiplier;
|
||||
type CuratorDepositMax = CuratorDepositMax;
|
||||
type CuratorDepositMin = CuratorDepositMin;
|
||||
type BountyValueMinimum = ConstU64<1>;
|
||||
type DataDepositPerByte = ConstU64<1>;
|
||||
type MaximumReasonLength = ConstU32<16384>;
|
||||
@@ -543,13 +553,14 @@ fn assign_curator_works() {
|
||||
Error::<Test>::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,
|
||||
@@ -567,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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -596,17 +609,17 @@ fn unassign_curator_works() {
|
||||
System::set_block_number(2);
|
||||
<Treasury as OnInitialize<u64>>::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,
|
||||
@@ -614,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,
|
||||
@@ -634,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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -652,10 +663,12 @@ fn award_and_claim_bounty_works() {
|
||||
System::set_block_number(2);
|
||||
<Treasury as OnInitialize<u64>>::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),
|
||||
@@ -668,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 },
|
||||
@@ -1034,3 +1047,78 @@ 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);
|
||||
<Treasury as OnInitialize<u64>>::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 = CuratorDepositMultiplier::get() * fee;
|
||||
assert_eq!(Balances::free_balance(&user), 100 - expected_deposit);
|
||||
assert_eq!(Balances::reserved_balance(&user), expected_deposit);
|
||||
|
||||
// Case 2: Lower bound
|
||||
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);
|
||||
<Treasury as OnInitialize<u64>>::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 = 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);
|
||||
<Treasury as OnInitialize<u64>>::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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,11 +144,6 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type ChildBountyValueMinimum: Get<BalanceOf<Self>>;
|
||||
|
||||
/// Percentage of child-bounty value to be reserved as curator deposit
|
||||
/// when curator fee is zero.
|
||||
#[pallet::constant]
|
||||
type ChildBountyCuratorDepositBase: Get<Permill>;
|
||||
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
|
||||
|
||||
@@ -392,7 +387,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::<T>::try_mutate_exists(
|
||||
parent_bounty_id,
|
||||
@@ -406,11 +401,13 @@ pub mod pallet {
|
||||
{
|
||||
ensure!(signer == *curator, BountiesError::<T>::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.
|
||||
let deposit = T::ChildBountyCuratorDepositBase::get() * child_bounty.value;
|
||||
// Reserve child-bounty curator deposit.
|
||||
let deposit = Self::calculate_curator_deposit(
|
||||
&parent_curator,
|
||||
curator,
|
||||
&child_bounty.fee,
|
||||
);
|
||||
|
||||
T::Currency::reserve(curator, deposit)?;
|
||||
child_bounty.curator_deposit = deposit;
|
||||
|
||||
@@ -770,6 +767,20 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
// This function will calculate the deposit of a curator.
|
||||
fn calculate_curator_deposit(
|
||||
parent_curator: &T::AccountId,
|
||||
child_curator: &T::AccountId,
|
||||
bounty_fee: &BalanceOf<T>,
|
||||
) -> BalanceOf<T> {
|
||||
if parent_curator == child_curator {
|
||||
return Zero::zero()
|
||||
}
|
||||
|
||||
// We just use the same logic from the parent bounties pallet.
|
||||
pallet_bounties::Pallet::<T>::calculate_curator_deposit(bounty_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
|
||||
|
||||
@@ -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,28 +132,30 @@ impl pallet_treasury::Config for Test {
|
||||
type MaxApprovals = ConstU32<100>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
|
||||
// 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 BountyCuratorDeposit = BountyCuratorDeposit;
|
||||
type CuratorDepositMultiplier = CuratorDepositMultiplier;
|
||||
type CuratorDepositMax = CuratorDepositMax;
|
||||
type CuratorDepositMin = CuratorDepositMin;
|
||||
type BountyValueMinimum = ConstU64<5>;
|
||||
type DataDepositPerByte = ConstU64<1>;
|
||||
type MaximumReasonLength = ConstU32<300>;
|
||||
type WeightInfo = ();
|
||||
type ChildBountyManager = ChildBounties;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10);
|
||||
}
|
||||
impl pallet_child_bounties::Config for Test {
|
||||
type Event = Event;
|
||||
type MaxActiveChildBountyCount = ConstU32<2>;
|
||||
type ChildBountyValueMinimum = ConstU64<1>;
|
||||
type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
@@ -197,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,
|
||||
@@ -217,27 +221,30 @@ fn add_child_bounty() {
|
||||
System::set_block_number(2);
|
||||
<Treasury as OnInitialize<u64>>::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 = CuratorDepositMultiplier::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);
|
||||
|
||||
@@ -258,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.
|
||||
@@ -285,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.
|
||||
@@ -302,21 +309,22 @@ fn child_bounty_assign_curator() {
|
||||
System::set_block_number(2);
|
||||
<Treasury as OnInitialize<u64>>::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.
|
||||
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.
|
||||
assert_eq!(Balances::free_balance(4), 99);
|
||||
assert_eq!(Balances::reserved_balance(4), 2);
|
||||
// Check the balance of parent curator.
|
||||
// Curator deposit is reserved for parent curator on parent bounty.
|
||||
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 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 });
|
||||
@@ -329,22 +337,23 @@ 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 = 6u64;
|
||||
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);
|
||||
// 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),
|
||||
@@ -353,20 +362,22 @@ fn child_bounty_assign_curator() {
|
||||
|
||||
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 },
|
||||
}
|
||||
);
|
||||
|
||||
// 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_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);
|
||||
@@ -411,7 +422,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 = 8;
|
||||
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.
|
||||
@@ -423,13 +435,14 @@ fn award_claim_child_bounty() {
|
||||
|
||||
assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7));
|
||||
|
||||
let expected_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_deposit,
|
||||
status: ChildBountyStatus::PendingPayout {
|
||||
curator: 8,
|
||||
beneficiary: 7,
|
||||
@@ -450,11 +463,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.
|
||||
@@ -591,8 +604,8 @@ fn close_child_bounty_pending() {
|
||||
System::set_block_number(2);
|
||||
<Treasury as OnInitialize<u64>>::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.
|
||||
@@ -601,8 +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.
|
||||
assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2));
|
||||
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));
|
||||
|
||||
@@ -616,8 +631,8 @@ 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);
|
||||
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);
|
||||
@@ -755,7 +770,6 @@ fn child_bounty_active_unassign_curator() {
|
||||
<Treasury as OnInitialize<u64>>::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.
|
||||
@@ -766,16 +780,18 @@ fn child_bounty_active_unassign_curator() {
|
||||
<Treasury as OnInitialize<u64>>::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 },
|
||||
}
|
||||
);
|
||||
@@ -792,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 },
|
||||
}
|
||||
);
|
||||
@@ -820,7 +838,7 @@ fn child_bounty_active_unassign_curator() {
|
||||
System::set_block_number(5);
|
||||
<Treasury as OnInitialize<u64>>::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.
|
||||
@@ -836,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.
|
||||
@@ -848,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 },
|
||||
}
|
||||
);
|
||||
@@ -877,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 },
|
||||
}
|
||||
);
|
||||
@@ -920,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);
|
||||
});
|
||||
}
|
||||
@@ -960,16 +980,18 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
|
||||
<Treasury as OnInitialize<u64>>::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 },
|
||||
}
|
||||
);
|
||||
@@ -999,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);
|
||||
@@ -1020,16 +1042,18 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
|
||||
<Treasury as OnInitialize<u64>>::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 },
|
||||
}
|
||||
);
|
||||
@@ -1048,7 +1072,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
|
||||
System::set_block_number(9);
|
||||
<Treasury as OnInitialize<u64>>::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.
|
||||
@@ -1157,25 +1181,26 @@ fn children_curator_fee_calculation_test() {
|
||||
System::set_block_number(4);
|
||||
<Treasury as OnInitialize<u64>>::on_initialize(4);
|
||||
|
||||
let fee = 6;
|
||||
|
||||
// Propose curator for child-bounty.
|
||||
assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2));
|
||||
|
||||
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,
|
||||
@@ -1201,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.
|
||||
@@ -1209,3 +1234,176 @@ 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 = 1_000_000;
|
||||
let parent_fee = 10_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);
|
||||
<Treasury as OnInitialize<u64>>::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: Parent and child curator are not 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);
|
||||
<Treasury as OnInitialize<u64>>::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 = 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: 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 = 10;
|
||||
|
||||
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);
|
||||
<Treasury as OnInitialize<u64>>::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: Upper Limit
|
||||
|
||||
let child_index = 2;
|
||||
let child_curator = 2;
|
||||
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(
|
||||
Origin::signed(parent_curator),
|
||||
parent_index,
|
||||
child_value,
|
||||
b"12345-p1".to_vec()
|
||||
));
|
||||
System::set_block_number(5);
|
||||
<Treasury as OnInitialize<u64>>::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 = 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);
|
||||
<Treasury as OnInitialize<u64>>::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);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user