Skip to content

SPL Stake Pool and CLI - v1.0.0

Compare
Choose a tag to compare
@joncinque joncinque released this 04 Dec 23:47
b7dd8fe

What's new

The SPL Stake Pool program graduates into its first major version with 1.0.0, over two years
after its first launch! There are any changes from the last version released to mainnet, 0.6.4, so
please read carefully.

Audits

All audits are hosted at https://github.com/solana-labs/security-audits#stake-pool. The
audits between this release and the previous are all of the ones conducted in 2023:

Verification

This build provided on the release uses solana-verifiable-build.

You can verify it by checking out the repo at commit b7dd8fe and running:

$ solana-verify build --library-name spl_stake_pool

Followed by:

$ solana-verify get-executable-hash target/deploy/spl_stake_pool.so
ef6cacb43ad5a4853f37c1254eb5ff9983bfdb77dfa9452a9dde375c5d762a37

Token Metadata

With two new instructions, CreateTokenMetadata and UpdateTokenMetadata,
a stake pool manager may manage Metaplex Token-Metadata for their pool token.
Only the name, symbol, and URI may be changed.

Relevant PRs:

  • Instruction to add metadata for pool token (#3335)
  • Update to newest token-metadata program (#4012)
  • Remove MPL crate dependency for 1.16 upgrade (#4588)

Token-2022

Stake pools may use mints on token-2022, including certain extensions:

  • transfer fees
  • confidential transfers
  • confidential transfers with fee
  • interest-bearing
  • metadata pointer
  • token metadata

Relevant PRs:

  • Support token-2022 (#3714)
  • Allow pool token mint to include metadata (#4770)
  • Allow mints with confidential transfer fee (#5610)

Minimum Delegation

With feature-gate
9onWzzvCzNC2jfhxxeqRgs5q7nFAAKpCUvkj6T6GJK9i,
the cluster may raise the required minimum stake delegation amount to 1 SOL.

Currently, the stake pool program requires stakers to pre-fund the rent-exempt
reserve and 0.001 SOL into any new validator stake account added to the pool.
When removing a validator stake account, the stake pool again requires that same
amount of lamports in the account. This behavior allows the staker to reclaim
the SOL they put into the pool, without taking any customer funds.

If the minimum delegation amount is raised to 1 SOL, however, then it will be
impossible for stakers to remove validators from the pool: stake accounts cannot
have a delegation of 0.001 SOL.

If the stake pool program just updates that number to 1 SOL whenever the cluster
decides, then the stake pool would actually be stealing 0.999 SOL from users for
each validator in the pool. The staker can bring a stake account to the new minimum
of 1 SOL, then take the whole account back.

The chosen solution funds all new validator stake accounts directly from the
stake pool's reserve, which means that stakers no longer need to put their own
SOL into the pool. On the other hand, this means that the pool will steal
rent-exemption (0.00228288 SOL) + 0.001 SOL from the staker for each validator
in the pool.

You can avoid losing these funds by removing validators from the pool prior to
the upgrade. Once the upgrade happens, then you can re-include them, and they
will be funded by the stake pool reserve.

Relevant PRs:

  • Update program to work with minimum delegation (#3127)
  • Use stake program minimum delegation (#3547)
  • Add / remove validators from the reserve (#3714)
  • Add tolerance for stake accounts at minimum (#3839)
  • Remove lamport minimum for validator removal by staker (#3999)
  • Update minimum reserve balance to 0 (#5031)

Force-Destaked Accounts

With the new DeactivateDelinquent instruction on the stake program, enabled with
437r62HoAdUb63amq3D7ENnBLDhHT2xY8eFkLJYVKK4x,
anyone may deactivate stake accounts on delinquent validators. The stake pool
program now handles this situation properly.

Relevant PRs:

  • Handle force destaked accounts (#3152)
  • Allow removal of force-destaked validator (#5439)

Redelegation

With feature
GUrp5BKMyDazsAp9mBoVD6orE5ihXNRPC3jkBRfx6Lq7,
the stake program allows direct redelegation from one stake account to another,
without losing any rewards. The stake pool program now exposes a similar
Redelegate instruction to allow moving from one validator to another.

Relevant PRs:

  • Support stake redelegation (#3856)
  • Document redelegate behavior better (#3986)
  • Add IncreaseAdditionalValidatorStake instruction (#3924)
  • Add DecreaseAdditionalValidatorStake instruction (#3925)
  • Check transient stake state (#3987)
  • Make activating / deactivating check stricter (#4002)

Pre-Funded Stake Destinations

With feature
D2aip4BBr8NPWtU9vLrwrBvbuaQ8w1zV38zFLxx4pfBV,
the destination stake account during a split must be rent-exempt. The stake pool
program will fund the rent-exempt reserve from the stake pool reserve, so managers
must keep some liquid SOL in the reserve to rebalance the pool.

Relevant PRs:

  • Prefund split account during redelegate (#5285)
  • Fund rent-exemption from reserve in decrease_additional (#5288)
  • Add new version of DecreaseValidatorStake to use reserve, add compatibility with master (#5322)

Fees

The stake pool program currently waits one epoch boundary before updating withdrawal
and epoch fees. To give depositors more safety, the program will wait two epoch
boundaries.

Additionally, there are new deposit and withdraw instructions that include
slippage, making it impossible for a user to be surprised by a fee.

Relevant PRs:

  • Wait at least two epoch boundaries to set fee (#3979)
  • Add slippage to all deposit and withdraw ixs (#3980)

Other Pull Requests

  • Bump Solana dependencies to 1.17 (#5575)
  • Specify the space used for new stake accounts (OS-SSP-SUG-00) (#4000)
  • Add comments about unnecessary ownership checks (HAL-01) (#5084)
  • Enforce that pool mint uses 9 decimal places (HAL-03) (#5085)
  • Remove some unwraps (#4003)
  • Use unaligned types for safe pointer cast (#5179)
  • Remove unsafe pointer casts via Pod types (#5185)
  • Truncate on withdrawal calculation (#3804)
  • Add lamports check for transient stake account on decrease (#3805)
  • Use to_writer API to serialize (#4228)