Skip to content

Commit

Permalink
SPL Stake Pool extract yield to stake account. Add support to update …
Browse files Browse the repository at this point in the history
…the epoch report on yield extraction
  • Loading branch information
dankelleher committed Jan 25, 2024
1 parent 04dc9bb commit 919cd0b
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 32 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,7 @@ jobs:
target
key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('rust-toolchain.toml') }}
- name: run tests
run: |
ls target/deploy
cat packages/sdks/common/dist/cjs/types/spl_beam.js
cat node_modules/@sunrisestake/beams-common/dist/cjs/types/spl_beam.js
#yarn anchor test --skip-build packages/tests/src/functional/beams/core.test.ts
yarn test
run: yarn test

- name: upload program logs
uses: actions/upload-artifact@v3
Expand Down
48 changes: 38 additions & 10 deletions packages/sdks/common/src/types/spl_beam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export type SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -187,7 +187,7 @@ export type SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -321,7 +321,7 @@ export type SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -440,7 +440,7 @@ export type SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -504,7 +504,7 @@ export type SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -704,6 +704,15 @@ export type SplBeam = {
"isMut": true,
"isSigner": false
},
{
"name": "epochReport",
"isMut": true,
"isSigner": false,
"docs": [
"The epoch report account. This is updated with the latest extracted yield value.",
"It must be up to date with the current epoch. If not, run updateEpochReport before it."
]
},
{
"name": "sysvarClock",
"isMut": false,
Expand All @@ -719,6 +728,11 @@ export type SplBeam = {
"isMut": false,
"isSigner": false
},
{
"name": "sysvarInstructions",
"isMut": false,
"isSigner": false
},
{
"name": "sunriseProgram",
"isMut": false,
Expand Down Expand Up @@ -922,7 +936,7 @@ export const IDL: SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -1026,7 +1040,7 @@ export const IDL: SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -1160,7 +1174,7 @@ export const IDL: SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -1279,7 +1293,7 @@ export const IDL: SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -1343,7 +1357,7 @@ export const IDL: SplBeam = {
"accounts": [
{
"name": "state",
"isMut": true,
"isMut": false,
"isSigner": false
},
{
Expand Down Expand Up @@ -1543,6 +1557,15 @@ export const IDL: SplBeam = {
"isMut": true,
"isSigner": false
},
{
"name": "epochReport",
"isMut": true,
"isSigner": false,
"docs": [
"The epoch report account. This is updated with the latest extracted yield value.",
"It must be up to date with the current epoch. If not, run updateEpochReport before it."
]
},
{
"name": "sysvarClock",
"isMut": false,
Expand All @@ -1558,6 +1581,11 @@ export const IDL: SplBeam = {
"isMut": false,
"isSigner": false
},
{
"name": "sysvarInstructions",
"isMut": false,
"isSigner": false
},
{
"name": "sunriseProgram",
"isMut": false,
Expand Down
8 changes: 4 additions & 4 deletions packages/sdks/common/src/types/sunrise_core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,12 @@ export type SunriseCore = {
]
},
{
"name": "clock",
"name": "sysvarClock",
"isMut": false,
"isSigner": false
},
{
"name": "instructionsSysvar",
"name": "sysvarInstructions",
"isMut": false,
"isSigner": false
}
Expand Down Expand Up @@ -1136,12 +1136,12 @@ export const IDL: SunriseCore = {
]
},
{
"name": "clock",
"name": "sysvarClock",
"isMut": false,
"isSigner": false
},
{
"name": "instructionsSysvar",
"name": "sysvarInstructions",
"isMut": false,
"isSigner": false
}
Expand Down
1 change: 1 addition & 0 deletions packages/sdks/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ export class SunriseClient {

/** Gets the address of the epoch report account */
public get epochReport(): [PublicKey, number] {
console.log("this.stateAddress", this.stateAddress);
return SunriseClient.deriveEpochReport(
this.stateAddress,
this.program.programId,
Expand Down
4 changes: 4 additions & 0 deletions packages/sdks/spl/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
StakeProgram,
SystemProgram,
SYSVAR_CLOCK_PUBKEY,
SYSVAR_INSTRUCTIONS_PUBKEY,
SYSVAR_STAKE_HISTORY_PUBKEY,
Transaction,
type TransactionInstruction,
Expand Down Expand Up @@ -434,6 +435,7 @@ export class SplClient extends BeamInterface<SplBeam.SplBeam, StateAccount> {
this.program.programId,
this.stateAddress,
);

const accounts = {
state: this.stateAddress,
stakePool: this.spl.stakePoolAddress,
Expand All @@ -447,9 +449,11 @@ export class SplClient extends BeamInterface<SplBeam.SplBeam, StateAccount> {
validatorStakeList: this.spl.stakePoolState.validatorList,
stakeAccountToSplit: this.spl.stakePoolState.reserveStake,
managerFeeAccount: this.spl.stakePoolState.managerFeeAccount,
epochReport: this.sunrise.epochReport[0],
sysvarClock: SYSVAR_CLOCK_PUBKEY,
nativeStakeProgram: StakeProgram.programId,
sysvarStakeHistory: SYSVAR_STAKE_HISTORY_PUBKEY,
sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY,
sunriseProgram: this.sunrise.program.programId,
splStakePoolProgram: SPL_STAKE_POOL_PROGRAM_ID,
systemProgram: SystemProgram.programId,
Expand Down
43 changes: 43 additions & 0 deletions packages/tests/src/functional/beams/marinade-sp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe("Marinade stake pool beam", () => {
const failedDepositAmount = 5 * LAMPORTS_PER_SOL;
const liquidWithdrawalAmount = 5 * LAMPORTS_PER_SOL;
const delayedWithdrawalAmount = 5 * LAMPORTS_PER_SOL;
// const burnAmount = new BN(1 * LAMPORTS_PER_SOL);

before("Set up the sunrise state", async () => {
coreClient = await registerSunriseState();
Expand Down Expand Up @@ -296,4 +297,46 @@ describe("Marinade stake pool beam", () => {
100,
);
});

//
// it("can burn gsol", async () => {
// // burn some gsol to simulate the creation of yield
// await sendAndConfirmTransaction(
// stakerIdentity,
// await beamClient.burnGSol(burnAmount),
// );
//
// const expectedGsol = stakerGsolBalance.sub(burnAmount);
//
// await expectTokenBalance(
// beamClient.provider,
// beamClient.sunrise.gsolAssociatedTokenAccount(),
// expectedGsol,
// );
// });
//
// it("can extract yield into a stake account", async () => {
// // since we burned some sol - we now have yield to extract (the value of the LPs is higher than the value of the GSOL staked)
// // The beam performs a delayed unstake to reduce fees, so the result is a stake account with the yield in it.
//
// await sendAndConfirmTransaction(
// // anyone can extract yield to the yield account, but let's use the staker provider (rather than the admin provider) for this test
// // to show that it doesn't have to be an admin
// stakerIdentity,
// await beamClient.extractYield(),
// );
//
// // we burned `burnAmount` gsol, so we should have `burnAmount` - fee in the stake account
// const expectedFee = new BN(0); // TODO
// const expectedExtractedYield = burnAmount.sub(expectedFee);
//
// await expectSolBalance(
// beamClient.provider,
// beamClient.sunrise.state.yieldAccount,
// expectedExtractedYield,
// // // the calculation appears to be slightly inaccurate at present, but in our favour,
// // // so we can leave this as a low priority TODO to improve the accuracy
// // 3000,
// );
// });
});
39 changes: 37 additions & 2 deletions programs/spl-beam/src/cpi_interface/sunrise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::seeds::*;
use anchor_lang::prelude::*;
use sunrise_core as sunrise_core_cpi;
use sunrise_core_cpi::cpi::{
accounts::{BurnGsol, MintGsol},
burn_gsol as cpi_burn_gsol, mint_gsol as cpi_mint_gsol,
accounts::{BurnGsol, ExtractYield, MintGsol},
burn_gsol as cpi_burn_gsol, extract_yield as cpi_extract_yield, mint_gsol as cpi_mint_gsol,
};

pub fn mint_gsol<'a>(
Expand Down Expand Up @@ -120,3 +120,38 @@ impl<'a> From<&crate::Burn<'a>> for BurnGsol<'a> {
}
}
}

pub fn extract_yield<'a>(
accounts: impl Into<ExtractYield<'a>>,
cpi_program: AccountInfo<'a>,
sunrise_key: Pubkey,
stake_pool: Pubkey,
state_bump: u8,
lamports: u64,
) -> Result<()> {
let accounts: ExtractYield<'a> = accounts.into();
let seeds = [
STATE,
sunrise_key.as_ref(),
stake_pool.as_ref(),
&[state_bump],
];
let signer = &[&seeds[..]];

cpi_extract_yield(
CpiContext::new(cpi_program, accounts).with_signer(signer),
lamports,
)
}

impl<'a> From<&crate::ExtractYield<'a>> for ExtractYield<'a> {
fn from(accounts: &crate::ExtractYield<'a>) -> Self {
Self {
state: accounts.sunrise_state.to_account_info(),
beam: accounts.state.to_account_info(),
epoch_report: accounts.epoch_report.to_account_info(),
sysvar_clock: accounts.sysvar_clock.to_account_info(),
sysvar_instructions: accounts.sysvar_instructions.to_account_info(),
}
}
}
Loading

0 comments on commit 919cd0b

Please sign in to comment.