diff --git a/packages/sdks/common/src/types/marinade_beam.ts b/packages/sdks/common/src/types/marinade_beam.ts index aedc258..3772ded 100644 --- a/packages/sdks/common/src/types/marinade_beam.ts +++ b/packages/sdks/common/src/types/marinade_beam.ts @@ -646,123 +646,6 @@ export type MarinadeBeam = { ], "args": [] }, - { - "name": "initEpochReport", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "sunriseState", - "isMut": false, - "isSigner": false - }, - { - "name": "marinadeState", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "updateAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "epochReportAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "msolMint", - "isMut": true, - "isSigner": false - }, - { - "name": "msolVault", - "isMut": true, - "isSigner": false - }, - { - "name": "vaultAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "clock", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "extractedYield", - "type": "u64" - } - ] - }, - { - "name": "updateEpochReport", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "sunriseState", - "isMut": false, - "isSigner": false - }, - { - "name": "marinadeState", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "epochReportAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "msolMint", - "isMut": true, - "isSigner": false - }, - { - "name": "msolVault", - "isMut": true, - "isSigner": false - }, - { - "name": "vaultAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "clock", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, { "name": "extractYield", "accounts": [ @@ -924,42 +807,6 @@ export type MarinadeBeam = { } ] } - }, - { - "name": "epochReport", - "type": { - "kind": "struct", - "fields": [ - { - "name": "state", - "type": "publicKey" - }, - { - "name": "epoch", - "type": "u64" - }, - { - "name": "tickets", - "type": "u64" - }, - { - "name": "totalOrderedLamports", - "type": "u64" - }, - { - "name": "extractableYield", - "type": "u64" - }, - { - "name": "extractedYield", - "type": "u64" - }, - { - "name": "bump", - "type": "u8" - } - ] - } } ], "types": [ @@ -1670,123 +1517,6 @@ export const IDL: MarinadeBeam = { ], "args": [] }, - { - "name": "initEpochReport", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "sunriseState", - "isMut": false, - "isSigner": false - }, - { - "name": "marinadeState", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "updateAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "epochReportAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "msolMint", - "isMut": true, - "isSigner": false - }, - { - "name": "msolVault", - "isMut": true, - "isSigner": false - }, - { - "name": "vaultAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "clock", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "extractedYield", - "type": "u64" - } - ] - }, - { - "name": "updateEpochReport", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "sunriseState", - "isMut": false, - "isSigner": false - }, - { - "name": "marinadeState", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "epochReportAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "msolMint", - "isMut": true, - "isSigner": false - }, - { - "name": "msolVault", - "isMut": true, - "isSigner": false - }, - { - "name": "vaultAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "clock", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, { "name": "extractYield", "accounts": [ @@ -1948,42 +1678,6 @@ export const IDL: MarinadeBeam = { } ] } - }, - { - "name": "epochReport", - "type": { - "kind": "struct", - "fields": [ - { - "name": "state", - "type": "publicKey" - }, - { - "name": "epoch", - "type": "u64" - }, - { - "name": "tickets", - "type": "u64" - }, - { - "name": "totalOrderedLamports", - "type": "u64" - }, - { - "name": "extractableYield", - "type": "u64" - }, - { - "name": "extractedYield", - "type": "u64" - }, - { - "name": "bump", - "type": "u8" - } - ] - } } ], "types": [ diff --git a/packages/sdks/marinade-sp/src/index.ts b/packages/sdks/marinade-sp/src/index.ts index 88a1fb1..e79b53f 100644 --- a/packages/sdks/marinade-sp/src/index.ts +++ b/packages/sdks/marinade-sp/src/index.ts @@ -353,6 +353,7 @@ export class MarinadeClient extends BeamInterface< sunriseState: this.state.sunriseState, burner, gsolTokenAccount: burnGsolFrom, + vaultAuthority: this.vaultAuthority[0], systemProgram: SystemProgram.programId, tokenProgram: TOKEN_PROGRAM_ID, gsolMint, @@ -485,24 +486,29 @@ export class MarinadeClient extends BeamInterface< * Return a transaction to extract any yield from this beam into the yield account */ public async extractYield(): Promise { + const accounts = { + state: this.stateAddress, + marinadeState: this.state.proxyState, + sunriseState: this.state.sunriseState, + msolMint: this.marinade.state.mSolMint.address, + msolVault: this.marinade.beamMsolVault, + vaultAuthority: this.vaultAuthority[0], + liqPoolSolLegPda: await this.marinade.state.solLeg(), + liqPoolMsolLeg: this.marinade.state.mSolLeg, + treasuryMsolAccount: this.marinade.state.treasuryMsolAccount, + yieldAccount: this.sunrise.state.yieldAccount, + epochReport: this.sunrise.epochReport[0], + sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY, + sysvarClock: SYSVAR_CLOCK_PUBKEY, + sunriseProgram: this.sunrise.program.programId, + marinadeProgram: MARINADE_FINANCE_PROGRAM_ID, + systemProgram: SystemProgram.programId, + tokenProgram: TOKEN_PROGRAM_ID, + }; + console.log(accounts); const instruction = await this.program.methods .extractYield() - .accounts({ - state: this.stateAddress, - marinadeState: this.state.proxyState, - sunriseState: this.state.sunriseState, - msolMint: this.marinade.state.mSolMint.address, - msolVault: this.marinade.beamMsolVault, - vaultAuthority: this.vaultAuthority[0], - liqPoolSolLegPda: await this.marinade.state.solLeg(), - liqPoolMsolLeg: this.marinade.state.mSolLeg, - treasuryMsolAccount: this.marinade.state.treasuryMsolAccount, - sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY, - sunriseProgram: this.sunrise.program.programId, - marinadeProgram: MARINADE_FINANCE_PROGRAM_ID, - systemProgram: SystemProgram.programId, - tokenProgram: TOKEN_PROGRAM_ID, - }) + .accounts(accounts) .instruction(); return new Transaction().add(instruction); diff --git a/packages/tests/src/functional/beams/marinade-sp.test.ts b/packages/tests/src/functional/beams/marinade-sp.test.ts index 1a05380..b40d45c 100644 --- a/packages/tests/src/functional/beams/marinade-sp.test.ts +++ b/packages/tests/src/functional/beams/marinade-sp.test.ts @@ -41,7 +41,7 @@ describe("Marinade stake pool beam", () => { const depositAmount = 10 * LAMPORTS_PER_SOL; const failedDepositAmount = 5 * LAMPORTS_PER_SOL; const liquidWithdrawalAmount = 5 * LAMPORTS_PER_SOL; - const delayedWithdrawalAmount = 5 * LAMPORTS_PER_SOL; + const delayedWithdrawalAmount = 1 * LAMPORTS_PER_SOL; const burnAmount = new BN(1 * LAMPORTS_PER_SOL); before("Set up the sunrise state", async () => { @@ -315,7 +315,14 @@ describe("Marinade stake pool beam", () => { ); }); - it("can extract yield into a stake account", async () => { + // TODO - we are going to restructure the epoch reports before enabling this + it.skip("can update the epoch report", async () => { + // fail + expect(false).to.equal(true); + }); + + // TODO - we are going to restructure the epoch reports before enabling this + it.skip("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. diff --git a/programs/marinade-beam/src/lib.rs b/programs/marinade-beam/src/lib.rs index ee252ee..3d2fcf7 100644 --- a/programs/marinade-beam/src/lib.rs +++ b/programs/marinade-beam/src/lib.rs @@ -16,12 +16,13 @@ mod system; use cpi_interface::marinade as marinade_interface; use cpi_interface::sunrise as sunrise_interface; use state::{State, StateEntry}; -use system::accounts::{EpochReport, ProxyTicket}; +use system::accounts::ProxyTicket; use system::utils; // TODO: Use actual CPI crate. use crate::cpi_interface::program::Marinade; use sunrise_core as sunrise_core_cpi; +use sunrise_core::EpochReport; declare_id!("G9nMA5HvMa1HLXy1DBA3biH445Zxb2dkqsG4eDfcvgjm"); @@ -205,60 +206,6 @@ pub mod marinade_beam { Ok(()) } - pub fn init_epoch_report(ctx: Context, extracted_yield: u64) -> Result<()> { - let extractable_yield = utils::calculate_extractable_yield( - &ctx.accounts.sunrise_state, - &ctx.accounts.state, - &ctx.accounts.marinade_state, - &ctx.accounts.msol_vault, - )?; - let mut epoch_report = EpochReport { - state: ctx.accounts.state.key(), - epoch: ctx.accounts.clock.epoch, - tickets: 0, - total_ordered_lamports: 0, - extractable_yield, - extracted_yield: 0, // modified below with remarks - bump: ctx.bumps.epoch_report_account, - }; - // we have to trust that the extracted amount is accurate, - // as extracted yield is no longer managed by the program. - // This is why this instruction is only callable by the update authority - epoch_report.extracted_yield = extracted_yield; - - ctx.accounts.epoch_report_account.set_inner(epoch_report); - Ok(()) - } - - pub fn update_epoch_report(ctx: Context) -> Result<()> { - // we can update the epoch report if either - // a) the account is at the current epoch or - // b) the account is at the previous epoch and there are no open tickets - - let current_epoch = ctx.accounts.clock.epoch; - let is_previous_epoch = ctx.accounts.epoch_report_account.epoch == current_epoch - 1; - let is_current_epoch = ctx.accounts.epoch_report_account.epoch == current_epoch; - let is_previous_epoch_and_no_open_tickets = - is_previous_epoch && ctx.accounts.epoch_report_account.tickets == 0; - - require!( - is_current_epoch || is_previous_epoch_and_no_open_tickets, - MarinadeBeamError::RemainingUnclaimableTicketAmount - ); - - ctx.accounts.epoch_report_account.epoch = ctx.accounts.clock.epoch; - - let extractable_yield = utils::calculate_extractable_yield( - &ctx.accounts.sunrise_state, - &ctx.accounts.state, - &ctx.accounts.marinade_state, - &ctx.accounts.msol_vault, - )?; - msg!("Extractable yield: {}", extractable_yield); - ctx.accounts.epoch_report_account.extractable_yield = extractable_yield; - Ok(()) - } - pub fn extract_yield(ctx: Context) -> Result<()> { let yield_lamports = utils::calculate_extractable_yield( &ctx.accounts.sunrise_state, @@ -266,9 +213,6 @@ pub mod marinade_beam { &ctx.accounts.marinade_state, &ctx.accounts.msol_vault, )?; - ctx.accounts - .epoch_report - .add_extracted_yield(yield_lamports); let yield_msol = utils::calc_msol_from_lamports(&ctx.accounts.marinade_state, yield_lamports)?; @@ -744,7 +688,7 @@ pub struct ExtractYield<'info> { /// 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. - /// CHECK: Address checked by CIP to the core Sunrise program. + /// CHECK: Address checked by CPI to the core Sunrise program. #[account(mut)] pub epoch_report: Box>, @@ -759,95 +703,6 @@ pub struct ExtractYield<'info> { pub token_program: Program<'info, Token>, } -#[derive(Accounts, Clone)] -pub struct InitEpochReport<'info> { - #[account( - has_one = marinade_state, - has_one = sunrise_state, - has_one = update_authority - )] - pub state: Box>, - pub sunrise_state: Box>, - #[account(has_one = msol_mint)] - pub marinade_state: Box>, - - #[account(mut)] - pub payer: Signer<'info>, - pub update_authority: Signer<'info>, - - #[account( - init, - space = EpochReport::SPACE, - payer = payer, - seeds = [state.key().as_ref(), constants::EPOCH_REPORT], - bump, - )] - pub epoch_report_account: Box>, - - #[account(mut)] - pub msol_mint: Box>, - #[account( - mut, - token::mint = msol_mint, - token::authority = vault_authority, - )] - pub msol_vault: Box>, - /// CHECK: Seeds of the MSOL vault authority. - #[account( - seeds = [ - state.key().as_ref(), - constants::VAULT_AUTHORITY - ], - bump = state.vault_authority_bump - )] - pub vault_authority: UncheckedAccount<'info>, - - pub clock: Sysvar<'info, Clock>, - pub system_program: Program<'info, System>, -} - -#[derive(Accounts)] -pub struct UpdateEpochReport<'info> { - #[account( - has_one = marinade_state, - has_one = sunrise_state - )] - pub state: Box>, - pub sunrise_state: Box>, - #[account(has_one = msol_mint)] - pub marinade_state: Box>, - - #[account(mut)] - pub payer: Signer<'info>, - - #[account( - mut, - seeds = [state.key().as_ref(), constants::EPOCH_REPORT], - bump = epoch_report_account.bump, - )] - pub epoch_report_account: Box>, - - #[account(mut)] - pub msol_mint: Box>, - #[account( - mut, - token::mint = msol_mint, - token::authority = vault_authority, - )] - pub msol_vault: Box>, - /// CHECK: Seeds of the MSOL vault authority. - #[account( - seeds = [ - state.key().as_ref(), - constants::VAULT_AUTHORITY - ], - bump = state.vault_authority_bump - )] - pub vault_authority: UncheckedAccount<'info>, - - pub clock: Sysvar<'info, Clock>, -} - #[error_code] pub enum MarinadeBeamError { #[msg("No delegation for stake account deposit")] diff --git a/programs/marinade-beam/src/system/accounts.rs b/programs/marinade-beam/src/system/accounts.rs index 1b057d8..648b91c 100644 --- a/programs/marinade-beam/src/system/accounts.rs +++ b/programs/marinade-beam/src/system/accounts.rs @@ -1,4 +1,3 @@ -use crate::MarinadeBeamError; use anchor_lang::prelude::*; /// Maps a Marinade ticket account to a GSOL token holder @@ -11,47 +10,3 @@ pub struct ProxyTicket { impl ProxyTicket { pub const SPACE: usize = 32 + 32 + 32 + 8 /* DISCRIMINATOR */; } - -#[account] -pub struct EpochReport { - pub state: Pubkey, - pub epoch: u64, - pub tickets: u64, - pub total_ordered_lamports: u64, - pub extractable_yield: u64, - pub extracted_yield: u64, - pub bump: u8, -} - -impl EpochReport { - pub const SPACE: usize = 32 + 8 + 8 + 8 + 8 + 8 + 1 + 8 /* DISCRIMINATOR */ ; - - pub fn all_extractable_yield(&self) -> u64 { - self.extractable_yield - .checked_add(self.extracted_yield) - .unwrap() - } - - pub fn add_ticket(&mut self, ticket_amount_lamports: u64, clock: &Sysvar) -> Result<()> { - require_eq!( - self.epoch, - clock.epoch, - MarinadeBeamError::InvalidEpochReportAccount - ); - self.tickets = self.tickets.checked_add(1).unwrap(); - self.total_ordered_lamports = self - .total_ordered_lamports - .checked_add(ticket_amount_lamports) - .unwrap(); - Ok(()) - } - - pub fn add_extracted_yield(&mut self, extracted_yield: u64) { - self.extracted_yield = self.extracted_yield.checked_add(extracted_yield).unwrap(); - } - - pub fn update_report(&mut self, extractable_yield: u64, add_extracted_yield: u64) { - self.extractable_yield = extractable_yield; - self.add_extracted_yield(add_extracted_yield); - } -} diff --git a/programs/spl-beam/src/lib.rs b/programs/spl-beam/src/lib.rs index ec07df5..99be5c7 100644 --- a/programs/spl-beam/src/lib.rs +++ b/programs/spl-beam/src/lib.rs @@ -605,7 +605,7 @@ pub struct ExtractYield<'info> { /// 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. - /// CHECK: Address checked by CIP to the core Sunrise program. + /// CHECK: Address checked by CPI to the core Sunrise program. #[account(mut)] pub epoch_report: UncheckedAccount<'info>,