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

Staking rewards distribution #269

Merged
merged 11 commits into from
Oct 10, 2023
Merged

Conversation

nanocryk
Copy link
Contributor

@nanocryk nanocryk commented Sep 18, 2023

Add staking reward distribution to the Auto Compounding and Manual Rewards pools.
The function is not called automatically and must be called by another pallet to manage the inflation and other details.

@nanocryk nanocryk changed the title Jeremy-staking-rewards-distribution Staking rewards distribution Sep 18, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Sep 20, 2023

Master coverage: 72.48%
Coverage generated "Mon Oct 9 14:59:28 UTC 2023":
https://d3gkbsry1ehhqi.cloudfront.net/tanssi-coverage/pulls/269/index.html
Pull coverage: 73.23%

@nanocryk nanocryk marked this pull request as ready for review September 21, 2023 08:02
Copy link
Contributor

@librelois librelois left a comment

Choose a reason for hiding this comment

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

Looks good to me

@girazoki
Copy link
Collaborator

Can we add description to the PR? it helps devrel categorize important/non-breaking prs etc


let rewards_per_share = rewards
.0
.checked_div(&supply)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here it is important that our rewards never surpass the supply of shares right? how do we control that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is the opposite, it should be at least equal to the supply of shares to distribute 1 unit per share.

That's why T::InitialManualClaimShareValue should be big enough so that the supply is somewhat low and allow rewards to be properly distributed.

manual_claim_rewards: delegators_manual_rewards,
});

Ok(candidate_manual_rewards)
Copy link
Collaborator

Choose a reason for hiding this comment

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

this function is very well documented and is easy to follow, congrats!

Copy link
Collaborator

@girazoki girazoki left a comment

Choose a reason for hiding this comment

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

The only thing missing is integration tests, but you need some sort of inflation for that. Let's not forget to add them later!

@librelois
Copy link
Contributor

you need some sort of inflation for that.

I'm working on the inflation mechanism in the branch elois-pallet-rewards, when it's advanced enough I'll open the PR against jeremy-staking-rewards-distribution (or against master if thgis PR is merged in the meantime).

@@ -96,3 +99,7 @@ pub mod well_known_keys {
pub const SESSION_INDEX: &[u8] =
&hex_literal::hex!["cec5070d609dd3497f72bde07fc96ba072763800a36a99fdfc7c10f6415f6ee6"];
}

pub trait DistributeRewards<AccountId, Balance> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Even if trivial, lets try to add some doc to the trait too

@girazoki
Copy link
Collaborator

you need some sort of inflation for that.

I'm working on the inflation mechanism in the branch elois-pallet-rewards, when it's advanced enough I'll open the PR against jeremy-staking-rewards-distribution (or against master if thgis PR is merged in the meantime).

Yep I think is fine, we can merge this as is and work on integration tests once your PR is ready

@girazoki
Copy link
Collaborator

Also ideally, we should benchmark the reward distribution so that we can at least report the utilized weight

/// AutoCompounding shares. This can lead to some rounding, which will be
/// absorbed in the ManualRewards distribution, which simply consist of
/// transfering the funds to the candidate account.
#[allow(dead_code)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#[allow(dead_code)]

@tmpolaczyk
Copy link
Contributor

tmpolaczyk commented Oct 3, 2023

Not sure if intended, but this test passes:

#[test]
fn candidate_only_no_stake() {
    // Rewarding a candidate that does not have any stake works
    ExtBuilder::default().build().execute_with(|| {
        test_distribution(
            &[],
            RewardRequest {
                collator: ACCOUNT_CANDIDATE_1,
                rewards: 1_000_000,
            },
            &[],
            Distribution {
                collator_auto: 0,
                collator_manual: 1_000_000, // 100% of rewards
                delegators_auto: 0,
                delegators_manual: 0, // 0% of rewards
            },
        )
    });
}

You can add that test if that's intended, or add a check that the candidate has enough shares if this should be an error.

Also these is the case where the candidate does not have any shares but some delegator does, not sure what should happen in that case:

Expand
#[test]
fn delegator_only_candidate_zero() {
    // Rewarding a candidate that does not have any stake works
    ExtBuilder::default().build().execute_with(|| {
        test_distribution(
            &[Delegation {
                    candidate: ACCOUNT_CANDIDATE_1,
                    delegator: ACCOUNT_DELEGATOR_1,
                    pool: TargetPool::ManualRewards,
                    stake: 250_000_000,
            }],
            RewardRequest {
                collator: ACCOUNT_CANDIDATE_1,
                rewards: 1_000_000,
            },
            &[],
            Distribution {
                collator_auto: 0,
                collator_manual: 200_000, // 20% of rewards
                delegators_auto: 0,
                delegators_manual: 800_000, // 80% of rewards
            },
        )
    });
}

Also another related test case that results in a division by zero:

Expand
#[test]
fn delegator_only_candidate_no_stake_auto_compounding() {
    // Rewarding a candidate that does not have any stake, while some delegator has stake for that candidate
    ExtBuilder::default().build().execute_with(|| {
        test_distribution(
            &[Delegation {
                candidate: ACCOUNT_CANDIDATE_1,
                delegator: ACCOUNT_DELEGATOR_1,
                pool: TargetPool::AutoCompounding,
                stake: 250_000_000,
            }],
            RewardRequest {
                collator: ACCOUNT_CANDIDATE_1,
                rewards: 1_000_000,
            },
            &[],
            Distribution {
                collator_auto: 0,
                collator_manual: 200_000, // 20% of rewards
                delegators_auto: 0,
                delegators_manual: 800_000, // 80% of rewards
            },
        )
    });
}

@nanocryk nanocryk merged commit bc2e01f into master Oct 10, 2023
22 checks passed
@nanocryk nanocryk deleted the jeremy-staking-rewards-distribution branch October 10, 2023 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants