Skip to content

Commit

Permalink
Merge pull request #13 from sunrise-stake/epoch_report_refactor
Browse files Browse the repository at this point in the history
Epoch report refactor
  • Loading branch information
dankelleher authored Feb 29, 2024
2 parents 3b3e861 + 7a74040 commit 92d03d3
Show file tree
Hide file tree
Showing 57 changed files with 2,701 additions and 1,306 deletions.
3 changes: 3 additions & 0 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ wallet = "packages/tests/fixtures/provider.json"
[scripts]
test = "packages/tests/run.sh"

[test]
startup_wait = 3000

[test.validator]
slots_per_epoch = "32"
#url = "https://api.mainnet-beta.solana.com"
Expand Down
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions lib/marinade-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "marinade-common"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anchor-lang = '0.29.0'
marinade-cpi = { git = "https://github.com/sunrise-stake/anchor-gen", branch = "update/anchor-v0.29" }
num-traits = "0.2.17"
95 changes: 95 additions & 0 deletions lib/marinade-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
pub mod vault_authority_seed;

use marinade_cpi::state::State as MarinadeState;
use num_traits::{NumCast, PrimInt};
use std::fmt::Debug;
use std::ops::{Div, Mul};

/// calculate amount*numerator/denominator
/// as value = shares * share_price where share_price=total_value/total_shares
/// or shares = amount_value / share_price where share_price=total_value/total_shares
/// => shares = amount_value * 1/share_price where 1/share_price=total_shares/total_value
pub fn proportional<T>(amount: T, numerator: T, denominator: T) -> T
where
T: PrimInt + Mul<Output = T> + Div<Output = T> + TryInto<i128>,
<T as TryInto<i128>>::Error: Debug,
{
proportional_with_rounding(amount, numerator, denominator, RoundingMode::Down)
}

pub enum RoundingMode {
Up,
Down,
}

pub fn proportional_with_rounding<T>(
amount: T,
numerator: T,
denominator: T,
rounding_mode: RoundingMode,
) -> T
where
T: PrimInt + Mul<Output = T> + Div<Output = T> + TryInto<i128>,
<T as TryInto<i128>>::Error: Debug,
{
if denominator == T::zero() {
return amount;
}

let amount_i128: i128 = amount.try_into().unwrap();
let numerator_i128: i128 = numerator.try_into().unwrap();
let denominator_i128: i128 = denominator.try_into().unwrap();

match rounding_mode {
RoundingMode::Up => {
// Round up by adding (denominator - 1) before dividing
let result = (amount_i128 * numerator_i128 + (denominator_i128 - 1)) / denominator_i128;
<T as NumCast>::from(result).unwrap()
}
RoundingMode::Down => {
// Default behavior (round down)
let result = amount_i128 * numerator_i128 / denominator_i128;
<T as NumCast>::from(result).unwrap()
}
}
}

// All lifted from https://github.com/marinade-finance/liquid-staking-program/blob/447f9607a8c755cac7ad63223febf047142c6c8f/programs/marinade-finance/src/state.rs#L227
pub fn calc_msol_from_lamports(marinade_state: &MarinadeState, stake_lamports: u64) -> u64 {
proportional(
stake_lamports,
marinade_state.msol_supply,
total_virtual_staked_lamports(marinade_state),
)
}
pub fn calc_lamports_from_msol_amount(marinade_state: &MarinadeState, msol_amount: u64) -> u64 {
proportional(
msol_amount,
total_virtual_staked_lamports(marinade_state),
marinade_state.msol_supply,
)
}

fn total_cooling_down(marinade_state: &MarinadeState) -> u64 {
marinade_state
.stake_system
.delayed_unstake_cooling_down
.checked_add(marinade_state.emergency_cooling_down)
.expect("Total cooling down overflow")
}

fn total_lamports_under_control(marinade_state: &MarinadeState) -> u64 {
marinade_state
.validator_system
.total_active_balance
.checked_add(total_cooling_down(marinade_state))
.expect("Stake balance overflow")
.checked_add(marinade_state.available_reserve_balance) // reserve_pda.lamports() - self.rent_exempt_for_token_acc
.expect("Total SOLs under control overflow")
}

fn total_virtual_staked_lamports(marinade_state: &MarinadeState) -> u64 {
// if we get slashed it may be negative but we must use 0 instead
total_lamports_under_control(marinade_state)
.saturating_sub(marinade_state.circulating_ticket_balance) //tickets created -> cooling down lamports or lamports already in reserve and not claimed yet
}
33 changes: 33 additions & 0 deletions lib/marinade-common/src/vault_authority_seed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use anchor_lang::prelude::{Account, Key};
use anchor_lang::{AccountDeserialize, AccountSerialize};

// NOTE: this must match the constant used by the programs themselves
const VAULT_AUTHORITY: &[u8] = b"vault-authority";

pub struct VaultAuthoritySeed<'a> {
state_address: Vec<u8>,
vault_authority: &'a [u8],
bump: Vec<u8>,
}

pub trait HasVaultAuthority: AccountSerialize + AccountDeserialize + Clone {
fn vault_authority_bump(&self) -> u8;
}

impl<'a> VaultAuthoritySeed<'a> {
pub fn new<'info>(state: &'a Account<'info, impl HasVaultAuthority>) -> Self {
let state_address = state.key().to_bytes().to_vec();
let vault_authority = VAULT_AUTHORITY;
let bump = vec![state.vault_authority_bump()];

VaultAuthoritySeed {
state_address,
vault_authority,
bump,
}
}

pub fn as_slices(&self) -> [&[u8]; 3] {
[&self.state_address, self.vault_authority, &self.bump]
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"prettier": "^3.0.3",
"ts-node": "^10.9.1",
"turbo": "^1.10.16",
"typedoc": "^0.25.1",
"typedoc": "^0.25.8",
"typescript": "^5.3.2"
}
}
Loading

0 comments on commit 92d03d3

Please sign in to comment.