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

Nomination Pool Commission #13128

Merged
merged 105 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
b0cd680
+ nomination pool commission
Jan 12, 2023
a5da2ad
fmt
Jan 12, 2023
09dedb0
use register_update()
Jan 13, 2023
ffb4dde
Update frame/nomination-pools/src/lib.rs
Jan 13, 2023
7d81de2
Update frame/nomination-pools/src/lib.rs
Jan 13, 2023
6aaf195
fmt
Jan 13, 2023
b9eae6e
amend comments
Jan 14, 2023
cd46c39
+ test for set_commission
Jan 14, 2023
ae44646
fix
Jan 15, 2023
6b424e7
Update frame/nomination-pools/fuzzer/src/call.rs
Jan 15, 2023
39bf064
rm comment
Jan 15, 2023
9d0d65a
use PalletError
Feb 3, 2023
acad3e4
some feedback item amendments
Feb 3, 2023
ff54e1a
Merge branch 'master' into rb-nomination-pool-commission-2
Feb 19, 2023
e25b79c
update weights
Feb 19, 2023
c1a4207
revert PalletError stuff
Feb 19, 2023
2d539e7
".git/.scripts/commands/fmt/fmt.sh"
Feb 19, 2023
f56227f
make pool_events_since_last_call more modular
Feb 20, 2023
42af0fb
fmt
Feb 20, 2023
a08862c
Merge branch 'master' into rb-nomination-pool-commission-2
Feb 23, 2023
339f2c1
fix call indexes + test
Feb 23, 2023
3955de0
add payout teste
Feb 23, 2023
29e5c75
add event to max_commisson updating current
Feb 23, 2023
9cbeee1
begin refactor
Feb 23, 2023
f4db6b3
some debugging
Feb 23, 2023
f3fdbb4
update
Feb 23, 2023
1537684
more tests
Feb 23, 2023
0b48dd1
rewardpol not working
Feb 23, 2023
91001fb
commission refactor
Feb 24, 2023
36d647c
pending rewards returns commission
Feb 24, 2023
65e1480
fmt
Feb 24, 2023
f30585e
add claim_commission call
Feb 24, 2023
bd192d3
+ claim_commission
Feb 24, 2023
1c803b7
fix benchmarks
Feb 24, 2023
3197e62
weight 0 for now
Feb 24, 2023
d27f56f
+ claim_commission benchmark
Feb 24, 2023
50658b3
fmt
Feb 24, 2023
9da0c58
apply commission to benchmarks
Feb 24, 2023
13943a7
Merge branch 'master' of https://github.com/paritytech/substrate into…
Feb 24, 2023
b6ad6a6
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nomination_…
Feb 24, 2023
2600637
".git/.scripts/commands/fmt/fmt.sh"
Feb 24, 2023
ee5ec6d
clippy
Feb 24, 2023
18f2df1
+ pending
Feb 24, 2023
6d4431c
add RewardPool.total_rewards_acounted
Feb 24, 2023
84d8bf0
fixes
Feb 24, 2023
20d9af8
println
Feb 25, 2023
26d5f77
more logs
Feb 25, 2023
5addf17
Fix plus cleanups
bkchr Feb 25, 2023
5006164
fix assert
Feb 25, 2023
d4e3a69
tidy up
Feb 25, 2023
61e3d75
tests work + tidy up
Feb 25, 2023
501f65f
rm unused
Feb 25, 2023
87e3f50
clippy fix
Feb 25, 2023
0f560f0
persist reward_pool update
Feb 25, 2023
990d38d
claim_commission_works tests
Feb 25, 2023
f4395ea
.
Feb 25, 2023
0842996
some test formatting
Feb 25, 2023
81e91b7
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Feb 25, 2023
2a9d39f
add high level docs
Feb 26, 2023
7de3ec2
add calls
Feb 26, 2023
8f773a1
docs
Feb 26, 2023
5df778f
rename
Feb 27, 2023
7639372
rename
Feb 27, 2023
7f2ab90
docs
Feb 27, 2023
6022d07
rename
Feb 27, 2023
d1d2695
fmt
Feb 27, 2023
b2d9197
use matches!
Feb 27, 2023
668e297
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Feb 28, 2023
b9526b6
Update frame/nomination-pools/src/lib.rs
Mar 1, 2023
20c53cf
Update frame/nomination-pools/src/lib.rs
Mar 1, 2023
700904c
Update frame/nomination-pools/src/tests.rs
Mar 1, 2023
c766ffa
comment
Mar 1, 2023
99b741c
Update frame/nomination-pools/src/lib.rs
Mar 1, 2023
356f75e
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 1, 2023
049b399
.
Mar 1, 2023
1b0e6eb
weights order
Mar 1, 2023
f4c0166
Merge branch 'master' of https://github.com/paritytech/substrate into…
Mar 1, 2023
8fd1038
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nomination_…
Mar 1, 2023
00daccc
Merge branch 'master' into rb-nomination-pool-commission-2
Mar 4, 2023
e3d5b53
use from_parts
Mar 4, 2023
08b4081
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 5, 2023
eb819da
comment
Mar 6, 2023
68f6706
".git/.scripts/commands/fmt/fmt.sh"
Mar 6, 2023
84730ec
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 8, 2023
41b8278
revert clippy suggestions on old migrations
Mar 8, 2023
a9d247f
Merge branch 'master' of https://github.com/paritytech/substrate into…
Mar 8, 2023
5969769
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nomination_…
Mar 8, 2023
6fdca9f
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 11, 2023
ecedcb8
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 13, 2023
14519c3
add InitialGlobalMaxCommission
Mar 13, 2023
d30b5a1
fix migration
Mar 13, 2023
8dcca04
reward counter comments & explanations
Mar 13, 2023
d0c4768
format
Mar 13, 2023
0a59245
add commission implementation note
Mar 13, 2023
ca3261e
fmt
Mar 13, 2023
c8968c9
revert InitialGlobalMaxCommission
Mar 13, 2023
669c3c8
global max commission migration generic
Mar 13, 2023
0a7e368
text
Mar 13, 2023
1c876bb
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 14, 2023
ecab0c0
100% commission no payout test
Mar 14, 2023
566a78e
add commission_accumulates_on_multiple_rewards
Mar 14, 2023
6480108
non-zero fuzzer GlobalMaxCommission
Mar 14, 2023
bbea2d2
add last_recorded_total_payouts_needs_commission
Mar 14, 2023
70f7769
commission event fix + claim commission test
Mar 14, 2023
34e2b71
Merge remote-tracking branch 'origin/master' into rb-nomination-pool-…
Mar 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 107 additions & 23 deletions frame/nomination-pools/benchmarking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ use frame_election_provider_support::SortedListProvider;
use frame_support::{assert_ok, ensure, traits::Get};
use frame_system::RawOrigin as RuntimeOrigin;
use pallet_nomination_pools::{
BalanceOf, BondExtra, BondedPoolInner, BondedPools, ConfigOp, MaxPoolMembers,
MaxPoolMembersPerPool, MaxPools, Metadata, MinCreateBond, MinJoinBond, Pallet as Pools,
PoolMembers, PoolRoles, PoolState, RewardPools, SubPoolsStorage,
BalanceOf, BondExtra, BondedPoolInner, BondedPools, Commission, CommissionChangeRate, ConfigOp,
GlobalMaxCommission, LastPoolId, MaxPoolMembers, MaxPoolMembersPerPool, MaxPools, Metadata,
MinCreateBond, MinJoinBond, Pallet as Pools, PoolMembers, PoolRoles, PoolState, RewardPools,
SubPoolsStorage,
};
use sp_runtime::{
traits::{Bounded, StaticLookup, Zero},
Perbill,
};
use sp_runtime::traits::{Bounded, StaticLookup, Zero};
use sp_staking::{EraIndex, StakingInterface};
// `frame_benchmarking::benchmarks!` macro needs this
use pallet_nomination_pools::Call;
Expand Down Expand Up @@ -67,6 +71,7 @@ fn create_funded_user_with_balance<T: pallet_nomination_pools::Config>(
fn create_pool_account<T: pallet_nomination_pools::Config>(
n: u32,
balance: BalanceOf<T>,
commission: Option<Perbill>,
) -> (T::AccountId, T::AccountId) {
let ed = CurrencyOf::<T>::minimum_balance();
let pool_creator: T::AccountId =
Expand All @@ -82,6 +87,16 @@ fn create_pool_account<T: pallet_nomination_pools::Config>(
)
.unwrap();

if let Some(c) = commission {
let pool_id = LastPoolId::<T>::get();
Pools::<T>::set_commission(
RuntimeOrigin::Signed(pool_creator.clone()).into(),
pool_id,
Some((c, pool_creator.clone())),
)
.expect("pool just created, commission can be set by root; qed");
}

let pool_account = pallet_nomination_pools::BondedPools::<T>::iter()
.find(|(_, bonded_pool)| bonded_pool.roles.depositor == pool_creator)
.map(|(pool_id, _)| Pools::<T>::create_bonded_account(pool_id))
Expand Down Expand Up @@ -132,14 +147,18 @@ impl<T: Config> ListScenario<T> {
sp_std::mem::forget(i);

// Create accounts with the origin weight
let (pool_creator1, pool_origin1) = create_pool_account::<T>(USER_SEED + 1, origin_weight);
let (pool_creator1, pool_origin1) =
create_pool_account::<T>(USER_SEED + 1, origin_weight, Some(Perbill::from_percent(50)));

T::Staking::nominate(
&pool_origin1,
// NOTE: these don't really need to be validators.
vec![account("random_validator", 0, USER_SEED)],
)?;

let (_, pool_origin2) = create_pool_account::<T>(USER_SEED + 2, origin_weight);
let (_, pool_origin2) =
create_pool_account::<T>(USER_SEED + 2, origin_weight, Some(Perbill::from_percent(50)));

T::Staking::nominate(
&pool_origin2,
vec![account("random_validator", 0, USER_SEED)].clone(),
Expand All @@ -155,7 +174,9 @@ impl<T: Config> ListScenario<T> {
dest_weight_as_vote.try_into().map_err(|_| "could not convert u64 to Balance")?;

// Create an account with the worst case destination weight
let (_, pool_dest1) = create_pool_account::<T>(USER_SEED + 3, dest_weight);
let (_, pool_dest1) =
create_pool_account::<T>(USER_SEED + 3, dest_weight, Some(Perbill::from_percent(50)));

T::Staking::nominate(&pool_dest1, vec![account("random_validator", 0, USER_SEED)])?;

let weight_of = pallet_staking::Pallet::<T>::weight_of_fn();
Expand Down Expand Up @@ -262,16 +283,17 @@ frame_benchmarking::benchmarks! {

}: bond_extra(RuntimeOrigin::Signed(scenario.creator1.clone()), BondExtra::Rewards)
verify {
// commission of 50% deducted here.
assert!(
T::Staking::active_stake(&scenario.origin1).unwrap() >=
scenario.dest_weight
scenario.dest_weight / 2u32.into()
);
}

claim_payout {
let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
let ed = CurrencyOf::<T>::minimum_balance();
let (depositor, pool_account) = create_pool_account::<T>(0, origin_weight);
let (depositor, pool_account) = create_pool_account::<T>(0, origin_weight, Some(Perbill::from_percent(50)));
let reward_account = Pools::<T>::create_reward_account(1);

// Send funds to the reward account of the pool
Expand Down Expand Up @@ -331,7 +353,7 @@ frame_benchmarking::benchmarks! {
let s in 0 .. MAX_SPANS;

let min_create_bond = Pools::<T>::depositor_min_bond();
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond);
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);

// Add a new member
let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
Expand Down Expand Up @@ -373,7 +395,7 @@ frame_benchmarking::benchmarks! {
let s in 0 .. MAX_SPANS;

let min_create_bond = Pools::<T>::depositor_min_bond();
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond);
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);

// Add a new member
let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
Expand Down Expand Up @@ -419,7 +441,7 @@ frame_benchmarking::benchmarks! {
let s in 0 .. MAX_SPANS;

let min_create_bond = Pools::<T>::depositor_min_bond();
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond);
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
let depositor_lookup = T::Lookup::unlookup(depositor.clone());

// We set the pool to the destroying state so the depositor can leave
Expand Down Expand Up @@ -509,15 +531,16 @@ frame_benchmarking::benchmarks! {
assert_eq!(
new_pool,
BondedPoolInner {
points: min_create_bond,
state: PoolState::Open,
commission: Commission::default(),
member_counter: 1,
points: min_create_bond,
roles: PoolRoles {
depositor: depositor.clone(),
root: Some(depositor.clone()),
nominator: Some(depositor.clone()),
state_toggler: Some(depositor.clone()),
},
state: PoolState::Open,
}
);
assert_eq!(
Expand All @@ -531,7 +554,7 @@ frame_benchmarking::benchmarks! {

// Create a pool
let min_create_bond = Pools::<T>::depositor_min_bond() * 2u32.into();
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond);
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);

// Create some accounts to nominate. For the sake of benchmarking they don't need to be
// actual validators
Expand All @@ -548,15 +571,16 @@ frame_benchmarking::benchmarks! {
assert_eq!(
new_pool,
BondedPoolInner {
points: min_create_bond,
state: PoolState::Open,
commission: Commission::default(),
member_counter: 1,
points: min_create_bond,
roles: PoolRoles {
depositor: depositor.clone(),
root: Some(depositor.clone()),
nominator: Some(depositor.clone()),
state_toggler: Some(depositor.clone()),
}
},
state: PoolState::Open,
}
);
assert_eq!(
Expand All @@ -568,7 +592,7 @@ frame_benchmarking::benchmarks! {
set_state {
// Create a pool
let min_create_bond = Pools::<T>::depositor_min_bond();
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond);
let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
BondedPools::<T>::mutate(&1, |maybe_pool| {
// Force the pool into an invalid state
maybe_pool.as_mut().map(|mut pool| pool.points = min_create_bond * 10u32.into());
Expand All @@ -585,7 +609,7 @@ frame_benchmarking::benchmarks! {
let n in 1 .. <T as pallet_nomination_pools::Config>::MaxMetadataLen::get();

// Create a pool
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into());
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);

// Create metadata of the max possible size
let metadata: Vec<u8> = (0..n).map(|_| 42).collect();
Expand All @@ -603,18 +627,20 @@ frame_benchmarking::benchmarks! {
ConfigOp::Set(BalanceOf::<T>::max_value()),
ConfigOp::Set(u32::MAX),
ConfigOp::Set(u32::MAX),
ConfigOp::Set(u32::MAX)
ConfigOp::Set(u32::MAX),
ConfigOp::Set(Perbill::max_value())
) verify {
assert_eq!(MinJoinBond::<T>::get(), BalanceOf::<T>::max_value());
assert_eq!(MinCreateBond::<T>::get(), BalanceOf::<T>::max_value());
assert_eq!(MaxPools::<T>::get(), Some(u32::MAX));
assert_eq!(MaxPoolMembers::<T>::get(), Some(u32::MAX));
assert_eq!(MaxPoolMembersPerPool::<T>::get(), Some(u32::MAX));
assert_eq!(GlobalMaxCommission::<T>::get(), Some(Perbill::max_value()));
}

update_roles {
let first_id = pallet_nomination_pools::LastPoolId::<T>::get() + 1;
let (root, _) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into());
let (root, _) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
let random: T::AccountId = account("but is anything really random in computers..?", 0, USER_SEED);
}:_(
RuntimeOrigin::Signed(root.clone()),
Expand All @@ -636,7 +662,7 @@ frame_benchmarking::benchmarks! {

chill {
// Create a pool
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into());
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);

// Nominate with the pool.
let validators: Vec<_> = (0..T::MaxNominations::get())
Expand All @@ -652,6 +678,64 @@ frame_benchmarking::benchmarks! {
assert!(T::Staking::nominations(Pools::<T>::create_bonded_account(1)).is_none());
}

set_commission {
// Create a pool - do not set a commission yet.
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
// set a max commission
Pools::<T>::set_commission_max(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into(), Perbill::from_percent(50)).unwrap();
// set a change rate
Pools::<T>::set_commission_change_rate(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into(), CommissionChangeRate {
max_increase: Perbill::from_percent(20),
min_delay: 0u32.into(),
}).unwrap();

}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Some((Perbill::from_percent(20), depositor.clone())))
verify {
assert_eq!(BondedPools::<T>::get(1).unwrap().commission, Commission {
current: Some((Perbill::from_percent(20), depositor)),
max: Some(Perbill::from_percent(50)),
change_rate: Some(CommissionChangeRate {
max_increase: Perbill::from_percent(20),
min_delay: 0u32.into()
}),
throttle_from: Some(1u32.into()),
});
}

set_commission_max {
// Create a pool, setting a commission that will update when max commission is set.
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), Some(Perbill::from_percent(50)));
}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Perbill::from_percent(50))
verify {
assert_eq!(
BondedPools::<T>::get(1).unwrap().commission, Commission {
current: Some((Perbill::from_percent(50), depositor)),
max: Some(Perbill::from_percent(50)),
change_rate: None,
throttle_from: Some(0u32.into()),
});
}

set_commission_change_rate {
// Create a pool
let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), CommissionChangeRate {
max_increase: Perbill::from_percent(50),
min_delay: 1000u32.into(),
})
verify {
assert_eq!(
BondedPools::<T>::get(1).unwrap().commission, Commission {
current: None,
max: None,
change_rate: Some(CommissionChangeRate {
max_increase: Perbill::from_percent(50),
min_delay: 1000u32.into(),
}),
throttle_from: Some(1_u32.into()),
});
}

impl_benchmark_test_suite!(
Pallet,
crate::mock::new_test_ext(),
Expand Down
3 changes: 2 additions & 1 deletion frame/nomination-pools/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use frame_election_provider_support::VoteWeight;
use frame_support::{pallet_prelude::*, parameter_types, traits::ConstU64, PalletId};
use sp_runtime::{
traits::{Convert, IdentityLookup},
FixedU128,
FixedU128, Perbill,
};

type AccountId = u128;
Expand Down Expand Up @@ -195,6 +195,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
max_pools: Some(3),
max_members_per_pool: Some(3),
max_members: Some(3 * 3),
global_max_commission: Some(Perbill::from_percent(500)),
rossbulat marked this conversation as resolved.
Show resolved Hide resolved
}
.assimilate_storage(&mut storage);
sp_io::TestExternalities::from(storage)
Expand Down
7 changes: 4 additions & 3 deletions frame/nomination-pools/fuzzer/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ use pallet_nomination_pools::{
mock::*,
pallet as pools,
pallet::{BondedPools, Call as PoolsCall, Event as PoolsEvents, PoolMembers},
BondExtra, BondedPool, LastPoolId, MaxPoolMembers, MaxPoolMembersPerPool, MaxPools,
MinCreateBond, MinJoinBond, PoolId,
BondExtra, BondedPool, GlobalMaxCommission, LastPoolId, MaxPoolMembers, MaxPoolMembersPerPool,
MaxPools, MinCreateBond, MinJoinBond, PoolId,
};
use rand::{seq::SliceRandom, Rng};
use sp_runtime::{assert_eq_error_rate, Perquintill};
use sp_runtime::{assert_eq_error_rate, Perbill, Perquintill};

const ERA: BlockNumber = 1000;
const MAX_ED_MULTIPLE: Balance = 10_000;
Expand Down Expand Up @@ -224,6 +224,7 @@ fn main() {
MaxPoolMembers::<T>::set(Some(10_000));
MaxPoolMembersPerPool::<T>::set(Some(1000));
MaxPools::<T>::set(Some(1_000));
GlobalMaxCommission::<T>::set(Some(Perbill::from_percent(90)));
rossbulat marked this conversation as resolved.
Show resolved Hide resolved

MinCreateBond::<T>::set(10 * ExistentialDeposit::get());
MinJoinBond::<T>::set(5 * ExistentialDeposit::get());
Expand Down
Loading