The Wayback Machine - http://web.archive.org/web/20230210005241/https://github.com/paritytech/substrate/pull/13128
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nomination Pool Commission #13128

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open

Conversation

rossbulat
Copy link
Contributor

@rossbulat rossbulat commented Jan 12, 2023

This PR adds commission functionality to Nomination Pools (was #12511).

New structs:

Commission and CommissionChangeRate.

New storage item:

GlobalMaxCommission: Option<Perbill>.

New calls:

set_commission, set_max_commission, and set_commission_change_rate.

polkadot companion: paritytech/polkadot#6264
fixes #11672.

@github-actions github-actions bot added the A0-pleasereview Pull request needs code review. label Jan 12, 2023
@rossbulat rossbulat added B3-apinoteworthy Changes should be mentioned in the release notes of the next minor version release. E1-runtimemigration PR introduces code that might require downstream chains to run a runtime upgrade. C1-low 📌 Does not elevate a release containing this beyond "low priority". D9-needsaudit 👮 PR contains changes to fund-managing logic that should be properly reviewed and externally audited labels Jan 12, 2023
@kianenigma kianenigma added B7-runtimenoteworthy Changes should be noted in any runtime-upgrade release notes and removed B3-apinoteworthy Changes should be mentioned in the release notes of the next minor version release. labels Jan 12, 2023
frame/nomination-pools/src/lib.rs Outdated Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Outdated Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Show resolved Hide resolved
// Test for `max_increase` throttling.
//
// Throttled if the attempted increase in commission is greater than `max_increase`.
if (*to).saturating_sub(commission_as_percent) > t.max_increase {
Copy link
Contributor

@Ank4n Ank4n Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check against global max as well?

Copy link
Contributor Author

@rossbulat rossbulat Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need, the commission is bounded to global max on 754. The "true" commission is determined here in commission_and_payee() as a payout is being made.

Copy link
Contributor Author

@rossbulat rossbulat Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing the work on runtime APIs by @gpestana , maybe we can introduce another one to get the "true" commission capped at the global max.

Copy link
Contributor

@gpestana gpestana Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that runtime API would be useful yes. Happy to implement it once we merge this PR, or even include the runtime API in #13119 returning always 0 until this PR is merged. If PR#13119 is merged before this one (which I think it will be the case), you could merge and implement the logic in this PR.

The call_state method could be something along the lines of NominationPoolsApi_pool_comission(pool_id) -> Perbill

frame/nomination-pools/src/lib.rs Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Outdated Show resolved Hide resolved
// Test for `max_increase` throttling.
//
// Throttled if the attempted increase in commission is greater than `max_increase`.
if (*to).saturating_sub(commission_as_percent) > t.max_increase {
Copy link
Contributor

@gpestana gpestana Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that runtime API would be useful yes. Happy to implement it once we merge this PR, or even include the runtime API in #13119 returning always 0 until this PR is merged. If PR#13119 is merged before this one (which I think it will be the case), you could merge and implement the logic in this PR.

The call_state method could be something along the lines of NominationPoolsApi_pool_comission(pool_id) -> Perbill

frame/nomination-pools/src/lib.rs Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Outdated Show resolved Hide resolved
frame/nomination-pools/src/lib.rs Show resolved Hide resolved
///
/// If `current.0` is larger than the updated max commission value, `current.0` will also be
/// updated to the new maximum. This will also register a `throttle_from` update.
fn try_update_max(&mut self, new_max: Perbill) -> DispatchResult {
Copy link
Contributor

@gpestana gpestana Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit but I wonder if it would be cleaner to return a pallet error here instead of a DispatchError and then transform to dispatch error in the callable.

(this suggestion is valid for all the other method impls that return a dispatch error)

Copy link
Contributor Author

@rossbulat rossbulat Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess either way would work, I noticed in the staking pallet DispatchError is also used in "do" functions outside the callable function.

If this convention is worthwhile perhaps a separate issue that covers all the staking-related pallets might be good?

Copy link
Contributor

@kianenigma kianenigma Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think returning DispatchError in functions that have #[pallet::call] and pallet error otherwise is slightly better.

frame/nomination-pools/src/lib.rs Show resolved Hide resolved
rossbulat and others added 4 commits January 13, 2023 17:01
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
Ank4n
Ank4n approved these changes Jan 14, 2023
.unwrap_or(Perbill::zero());
assert_eq!(commission_as_percent, Perbill::from_percent(50));

// update commission only.
Copy link
Contributor

@kianenigma kianenigma Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect to see a payout after each variation here in order to fully test this.

Some((Perbill::from_percent(10), 901))
));

assert_eq!(
Copy link
Contributor

@kianenigma kianenigma Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be better to call this after each test or bundle of related tests.

// Run to block 3
run_blocks(2);

// Now try to increase commission by 1% and provide an initial payee. This should
Copy link
Contributor

@kianenigma kianenigma Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can always change the payee regardless of max and throttle, right? basically, we if the commission value is not changed, all other checks can be bypassed.

Copy link
Contributor Author

@rossbulat rossbulat Feb 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throttling yes - it will always allow a payee update if the current commission is provided along with it. throttling() returns false early on in the function if the commission is unchanged.

It would however fail if a new commission higher than max (or subject to being throttled) is provided along with a new payee.

Error::<Runtime>::CommissionExceedsMaximum
);

assert_eq!(
Copy link
Contributor

@kianenigma kianenigma Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto, I think checking events at the end of the tests is reasonable when the tests is by all means a "unti" tests, testing one scenario. Your tests tend to me much longer, and at least I find it hard to connect the events with everything that happened in the test.

Copy link
Contributor Author

@rossbulat rossbulat Feb 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, will amend.

pool_id: 1,
current: Some((Perbill::from_percent(75), 900)),
},
Event::PoolMaxCommissionUpdated {
Copy link
Contributor

@kianenigma kianenigma Jan 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now, I kinda see that we are missing a PoolCommissionUpdated to 50?

Copy link
Contributor Author

@rossbulat rossbulat Feb 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An event for that was left out as UIs could determine there was a commission change just be listening to the max commission changed event (then compare with current commission in the UI). But yes I can see now there is an argument for including it here too.

Copy link
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No major issues found, perhaps https://github.com/paritytech/substrate/pull/13128/files?diff=unified&w=0#r1070602032 is the only one.

Some suggestions about docs:

  1. try and avoid writing duplicate facts. For example, the fact that the commission can be changed by root should ideally be mentioned in the description of root role, and perhaps the top level Commission struct. I don't have better examples here, but the ideas is that it is almost always better to say: "Read X to see who can change the commission" rather than saying it on the spot.
  2. We should update the top level crate doc with all the detailed information that pool operators want to know about the commission as well so that it can act as a source of truth.

@Polkadot-Forum
Copy link

Polkadot-Forum commented Jan 27, 2023

This pull request has been mentioned on Polkadot Forum. There might be relevant details there:

https://forum.polkadot.network/t/the-future-of-polkadot-staking/1848/1

@rossbulat rossbulat changed the title Nomination Pool Commission [Final] Nomination Pool Commission Feb 3, 2023
@rossbulat rossbulat force-pushed the rb-nomination-pool-commission-2 branch from 9ee6fcf to acad3e4 Compare February 3, 2023 07:36
@paritytech-cicd-pr
Copy link

paritytech-cicd-pr commented Feb 3, 2023

The CI pipeline was cancelled due to failure one of the required jobs.
Job name: cargo-check-each-crate
Logs: https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/2349007

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A0-pleasereview Pull request needs code review. B7-runtimenoteworthy Changes should be noted in any runtime-upgrade release notes C1-low 📌 Does not elevate a release containing this beyond "low priority". D9-needsaudit 👮 PR contains changes to fund-managing logic that should be properly reviewed and externally audited E1-runtimemigration PR introduces code that might require downstream chains to run a runtime upgrade.
Projects
Status: ✂️ In progress.
Development

Successfully merging this pull request may close these issues.

nomination-pools: add optional commission
6 participants