Skip to content

Commit

Permalink
Fixes for staked collat pricing
Browse files Browse the repository at this point in the history
  • Loading branch information
jgur-psyops committed Feb 3, 2025
1 parent bd7efda commit 02d005c
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions programs/marginfi/src/state/price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use enum_dispatch::enum_dispatch;
use fixed::types::I80F48;
use pyth_sdk_solana::{state::SolanaPriceAccount, Price, PriceFeed};
use pyth_solana_receiver_sdk::price_update::{self, FeedId, PriceUpdateV2};
use solana_program::{borsh1::try_from_slice_unchecked, stake::state::StakeStateV2};
use switchboard_on_demand::{CurrentResult, PullFeedAccountData, SPL_TOKEN_PROGRAM_ID};
use switchboard_solana::{
AggregatorAccountData, AggregatorResolutionMode, SwitchboardDecimal, SWITCHBOARD_PROGRAM_ID,
Expand Down Expand Up @@ -162,7 +163,20 @@ impl OraclePriceFeedAdapter {

let lst_mint = Account::<'info, Mint>::try_from(&ais[1]).unwrap();
let lst_supply = lst_mint.supply;
let sol_pool_balance = ais[2].lamports();
let stake_state = try_from_slice_unchecked::<StakeStateV2>(&ais[2].data.borrow())?;
let (_, stake) = match stake_state {
StakeStateV2::Stake(meta, stake, _) => (meta, stake),
_ => panic!("unsupported stake state"), // TODO emit more specific error
};
let sol_pool_balance = stake.delegation.stake;
// Note: When the pool is fresh, it has 1 SOL in it (an initial and non-refundable
// balance that will stay in the pool forever). We don't want to include that
// balance when reading the quantity of SOL that has been staked from actual
// depositors (i.e. the amount that can actually be redeemed again).
let lamports_per_sol: u64 = 1_000_000_000;
let sol_pool_adjusted_balance = sol_pool_balance
.checked_sub(lamports_per_sol)
.ok_or_else(math_error!())?;
// Note: exchange rate is `sol_pool_balance / lst_supply`, but we will do the
// division last to avoid precision loss. Division does not need to be
// decimal-adjusted because both SOL and stake positions use 9 decimals
Expand All @@ -188,14 +202,14 @@ impl OraclePriceFeedAdapter {
max_age,
)?;
let adjusted_price = (feed.price.price as i128)
.checked_mul(sol_pool_balance as i128)
.checked_mul(sol_pool_adjusted_balance as i128)
.ok_or_else(math_error!())?
.checked_div(lst_supply as i128)
.ok_or_else(math_error!())?;
feed.price.price = adjusted_price.try_into().unwrap();

let adjusted_ema_price = (feed.ema_price.price as i128)
.checked_mul(sol_pool_balance as i128)
.checked_mul(sol_pool_adjusted_balance as i128)
.ok_or_else(math_error!())?
.checked_div(lst_supply as i128)
.ok_or_else(math_error!())?;
Expand All @@ -218,14 +232,14 @@ impl OraclePriceFeedAdapter {
)?;

let adjusted_price = (feed.price.price as i128)
.checked_mul(sol_pool_balance as i128)
.checked_mul(sol_pool_adjusted_balance as i128)
.ok_or_else(math_error!())?
.checked_div(lst_supply as i128)
.ok_or_else(math_error!())?;
feed.price.price = adjusted_price.try_into().unwrap();

let adjusted_ema_price = (feed.ema_price.price as i128)
.checked_mul(sol_pool_balance as i128)
.checked_mul(sol_pool_adjusted_balance as i128)
.ok_or_else(math_error!())?
.checked_div(lst_supply as i128)
.ok_or_else(math_error!())?;
Expand Down

0 comments on commit 02d005c

Please sign in to comment.