-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
stake: Allow initialized stakes to be below the min delegation #24670
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused as to why there are changes to initialize
and split
here. Both would allow new sub-limit delegations to be created. Aren't we just providing an escape hatch for existing sub-limit delegations here? That is, deactivate
and withdraw
.
|
I believe this behavior (esp for split) will retain the accounts in the stakes cache and add work to the rewards calculation. Both of which are the motivation for instating a minimum stake limit. cc/ @jstarry @behzadnouri |
The stakes cache doesn't do anything with solana/runtime/src/stake_account.rs Line 80 in 412a5a0
Your point is well-taken for the future work on split + deactivate on small stakes, since those definitely need to exist in the cache to get their rewards for the deactivation epoch. For those, it might be time to finally add a new stake account type that doesn't get its rewards paid out at the epoch boundary, and add a new instruction to harvest it from the vote account! Unless it's acceptable for small deactivating stakes to exist in the cache. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I need to finish going through the test cases in stake_instruction.rs; here's a few thoughts/nits in the meantime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, finished a first pass. Looks good to me. Comments below.
Thanks for the review! This should be ready for another look |
I also had to update the frozen abi digest on |
There was a problem hiding this 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! I think I'm also a little biased so it's probably valuable to have another person sign off on this as well.
Codecov Report
@@ Coverage Diff @@
## master #24670 +/- ##
=========================================
+ Coverage 81.8% 82.0% +0.1%
=========================================
Files 632 598 -34
Lines 167499 165628 -1871
Branches 322 0 -322
=========================================
- Hits 137169 135904 -1265
+ Misses 30217 29724 -493
+ Partials 113 0 -113 |
Pull request has been modified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic looks correct to me, just the one question about error type
programs/stake/src/stake_state.rs
Outdated
if feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) | ||
&& stake_amount < crate::get_minimum_delegation(feature_set) | ||
{ | ||
return Err(InstructionError::InsufficientStakeDelegation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this needs to be a new InstructionError variant instead of a new StakeError variant?
We did similar for ActiveVoteAccountClose
, but that was because VoteError
is really specific to Vote instructions, whereas StakeError
covers a variety of Stake instructions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good call, I'll make this a new StakeError
) -> Result<ValidatedDelegatedInfo, InstructionError> { | ||
let stake_amount = account | ||
.get_lamports() | ||
.saturating_sub(meta.rent_exempt_reserve); // can't stake the rent | ||
if feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add a comment about the behavior change here?
Maybe something like this (but moar better): Previously, all StakeState::Initialize accounts were required to have a balance greater than the minimum delegation amount. After feature stake_allow_zero_undelegated_amount
, StakeState::Initialize accounts may have a lower balance, so the minimum must be checked on delegation via this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this feature gate actually necessary? It's not currently possible to initialize a stake account which doesn't already hit the minimum delegation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, I see it was possible to withdraw and then delegate again. Will make sure this behavior gets documented here: #24603
This should be ready for another look, thanks for the careful eyes! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
…a-labs#24670) * stake: Allow initialized stakes to be below the min delegation * Add PR number in feature * Fixup RPC subscription test * Address feedback pt 1 * Address feedback pt 2 * Update FrozenAbi Digest * Address feedback: no new error type, more comments
Problem
The economics of stake pools will change as a result of a higher minimum delegation. First, some background on pools:
When the minimum stake delegation is raised to a larger number, the minimums when calculating the usable amount of SOL in the pool will change from 0.001 SOL to 1 SOL for delegated stakes, and from 1 lamport to 1 SOL for the reserve. In this way, existing stake pools essentially co-opt the new minimums from depositors. 1 SOL in each stake account (including the reserve) will be completely untouchable by both the pool manager and by depositors.
With a minimum delegation of 1 SOL, users with less than 1 SOL must withdraw from the reserve -- for stakes, they need to provide enough stake pool tokens to equal 1 SOL + rent-exemption.
Summary of Changes
It makes sense for delegated stake accounts to adhere to these rules, but initialized stake accounts can live apart, since they aren't present in the runtime's stakes cache.
Allow initialized stakes to be below the minimum delegation amount, while still forcing that all other stake types adhere to the minimum stake delegation. A lot of the changes were cribbed from #24603 (thanks @brooksprumo !)
With this, the whole reserve (minus rent exemption) will be usable for user withdrawals and manager delegations.
Also, for whenever stake v2 is created, with lower or no minimum delegation, their initialized state can still interoperate with initialized stake v1 accounts.
Feature Gate Issue: #24669