Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

program: add-spot-insurance-activity-tracking #1127

Merged
merged 14 commits into from
Jul 15, 2024
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- program: add oracle id for wen ([#1129](https://github.com/drift-labs/protocol-v2/pull/1129))
- program: track fuel ([#1048](https://github.com/drift-labs/protocol-v2/pull/1048))
- program: track fuel for if staking ([#1127](https://github.com/drift-labs/protocol-v2/pull/1127))
- program: validate fee structure ([#1075](https://github.com/drift-labs/protocol-v2/pull/1075))

### Fixes
Expand Down
145 changes: 92 additions & 53 deletions programs/drift/src/controller/insurance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use crate::error::ErrorCode;
use crate::math::amm::calculate_net_user_pnl;
use crate::math::casting::Cast;
use crate::math::constants::{
MAX_APR_PER_REVENUE_SETTLE_TO_INSURANCE_FUND_VAULT, ONE_YEAR, PERCENTAGE_PRECISION,
FUEL_WINDOW_U128, MAX_APR_PER_REVENUE_SETTLE_TO_INSURANCE_FUND_VAULT, ONE_YEAR,
PERCENTAGE_PRECISION, QUOTE_PRECISION_U64,
SHARE_OF_REVENUE_ALLOCATED_TO_INSURANCE_FUND_VAULT_DENOMINATOR,
SHARE_OF_REVENUE_ALLOCATED_TO_INSURANCE_FUND_VAULT_NUMERATOR,
};
Expand All @@ -35,6 +36,64 @@ use crate::{emit, validate, GOV_SPOT_MARKET_INDEX, QUOTE_SPOT_MARKET_INDEX};
#[cfg(test)]
mod tests;

pub fn update_user_stats_if_stake_amount(
0xbigz marked this conversation as resolved.
Show resolved Hide resolved
amount: i64,
insurance_vault_amount: u64,
insurance_fund_stake: &mut InsuranceFundStake,
user_stats: &mut UserStats,
spot_market: &mut SpotMarket,
now: i64,
) -> DriftResult {
if spot_market.market_index != QUOTE_SPOT_MARKET_INDEX
&& spot_market.market_index != GOV_SPOT_MARKET_INDEX
&& spot_market.fuel_boost_insurance == 0
{
return Ok(());
}

let if_stake_amount = if amount >= 0 {
if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount.safe_add(amount.unsigned_abs())?,
)?
} else {
if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount.safe_sub(amount.unsigned_abs())?,
)?
};

if spot_market.market_index == QUOTE_SPOT_MARKET_INDEX {
user_stats.if_staked_quote_asset_amount = if_stake_amount;
} else if spot_market.market_index == GOV_SPOT_MARKET_INDEX {
user_stats.if_staked_gov_token_amount = if_stake_amount;
}

if spot_market.fuel_boost_insurance != 0 {
let now_u32: u32 = now.cast()?;
let since_last = now_u32.safe_sub(user_stats.last_fuel_if_bonus_update_ts)?;

// calculate their stake amount prior to update
let fuel_bonus_insurance = if_stake_amount
.saturating_sub(amount.unsigned_abs())
.cast::<u128>()?
.safe_mul(since_last.cast()?)?
.safe_mul(spot_market.fuel_boost_insurance.cast()?)?
.safe_div(FUEL_WINDOW_U128)?
.cast::<u64>()?
/ (QUOTE_PRECISION_U64 / 10);

user_stats.fuel_insurance = user_stats
.fuel_insurance
.saturating_add(fuel_bonus_insurance.cast()?);
user_stats.last_fuel_if_bonus_update_ts = now_u32;
}

Ok(())
}

pub fn add_insurance_fund_stake(
amount: u64,
insurance_vault_amount: u64,
Expand Down Expand Up @@ -77,19 +136,14 @@ pub fn add_insurance_fund_stake(
spot_market.insurance_fund.user_shares =
spot_market.insurance_fund.user_shares.safe_add(n_shares)?;

if spot_market.market_index == QUOTE_SPOT_MARKET_INDEX {
user_stats.if_staked_quote_asset_amount = if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount.safe_add(amount)?,
)?;
} else if spot_market.market_index == GOV_SPOT_MARKET_INDEX {
user_stats.if_staked_gov_token_amount = if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount.safe_add(amount)?,
)?;
}
update_user_stats_if_stake_amount(
amount.cast()?,
insurance_vault_amount,
insurance_fund_stake,
user_stats,
spot_market,
now,
)?;

let if_shares_after = insurance_fund_stake.checked_if_shares(spot_market)?;

Expand Down Expand Up @@ -237,19 +291,14 @@ pub fn request_remove_insurance_fund_stake(

let if_shares_after = insurance_fund_stake.checked_if_shares(spot_market)?;

if spot_market.market_index == QUOTE_SPOT_MARKET_INDEX {
user_stats.if_staked_quote_asset_amount = if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount,
)?;
} else if spot_market.market_index == GOV_SPOT_MARKET_INDEX {
user_stats.if_staked_gov_token_amount = if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount,
)?;
}
update_user_stats_if_stake_amount(
0,
insurance_vault_amount,
insurance_fund_stake,
user_stats,
spot_market,
now,
)?;

emit!(InsuranceFundStakeRecord {
ts: now,
Expand Down Expand Up @@ -314,19 +363,14 @@ pub fn cancel_request_remove_insurance_fund_stake(

let if_shares_after = insurance_fund_stake.checked_if_shares(spot_market)?;

if spot_market.market_index == 0 {
user_stats.if_staked_quote_asset_amount = if_shares_to_vault_amount(
if_shares_after,
spot_market.insurance_fund.total_shares,
insurance_vault_amount,
)?;
} else if spot_market.market_index == GOV_SPOT_MARKET_INDEX {
user_stats.if_staked_gov_token_amount = if_shares_to_vault_amount(
insurance_fund_stake.checked_if_shares(spot_market)?,
spot_market.insurance_fund.total_shares,
insurance_vault_amount,
)?;
}
update_user_stats_if_stake_amount(
0,
insurance_vault_amount,
insurance_fund_stake,
user_stats,
spot_market,
now,
)?;

emit!(InsuranceFundStakeRecord {
ts: now,
Expand Down Expand Up @@ -415,19 +459,14 @@ pub fn remove_insurance_fund_stake(

let if_shares_after = insurance_fund_stake.checked_if_shares(spot_market)?;

if spot_market.market_index == QUOTE_SPOT_MARKET_INDEX {
user_stats.if_staked_quote_asset_amount = if_shares_to_vault_amount(
if_shares_after,
spot_market.insurance_fund.total_shares,
insurance_vault_amount.safe_sub(amount)?,
)?;
} else if spot_market.market_index == GOV_SPOT_MARKET_INDEX {
user_stats.if_staked_gov_token_amount = if_shares_to_vault_amount(
if_shares_after,
spot_market.insurance_fund.total_shares,
insurance_vault_amount.safe_sub(amount)?,
)?;
}
update_user_stats_if_stake_amount(
-(withdraw_amount.cast()?),
insurance_vault_amount,
insurance_fund_stake,
user_stats,
spot_market,
now,
)?;

emit!(InsuranceFundStakeRecord {
ts: now,
Expand Down
16 changes: 10 additions & 6 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1725,11 +1725,12 @@ fn fulfill_perp_order(
)?;

user_stats.update_fuel_bonus(
user,
taker_margin_calculation.fuel_deposits,
taker_margin_calculation.fuel_borrows,
taker_margin_calculation.fuel_positions,
now,
)?;
user.last_fuel_bonus_update_ts = now;

if !taker_margin_calculation.meets_margin_requirement() {
msg!(
Expand Down Expand Up @@ -1768,11 +1769,12 @@ fn fulfill_perp_order(

if let Some(mut maker_stats) = maker_stats {
maker_stats.update_fuel_bonus(
&mut maker,
maker_margin_calculation.fuel_deposits,
maker_margin_calculation.fuel_borrows,
maker_margin_calculation.fuel_positions,
now,
)?;
maker.last_fuel_bonus_update_ts = now;
}

if !maker_margin_calculation.meets_margin_requirement() {
Expand Down Expand Up @@ -4091,12 +4093,14 @@ fn fulfill_spot_order(
.fuel_numerator(user, now),
)?;

// user hasnt recieved initial fuel or below global start time
user_stats.update_fuel_bonus(
user,
taker_margin_calculation.fuel_deposits,
taker_margin_calculation.fuel_borrows,
taker_margin_calculation.fuel_positions,
now,
)?;
user.last_fuel_bonus_update_ts = now;

if !taker_margin_calculation.meets_margin_requirement() {
msg!(
Expand Down Expand Up @@ -4159,7 +4163,7 @@ fn fulfill_spot_order(
drop(base_market);
drop(quote_market);

let maker_margin_calculation =
let maker_margin_calculation: MarginCalculation =
calculate_margin_requirement_and_total_collateral_and_liability_info(
&maker,
perp_market_map,
Expand All @@ -4183,12 +4187,12 @@ fn fulfill_spot_order(

if let Some(mut maker_stats) = maker_stats {
maker_stats.update_fuel_bonus(
&mut maker,
maker_margin_calculation.fuel_deposits,
maker_margin_calculation.fuel_borrows,
maker_margin_calculation.fuel_positions,
now,
)?;

maker.last_fuel_bonus_update_ts = now;
}

if !maker_margin_calculation.meets_margin_requirement() {
Expand Down
15 changes: 8 additions & 7 deletions programs/drift/src/controller/orders/fuel_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ pub mod fuel_scoring {
assert_eq!(maker_stats_after.fuel_maker, 5000);
assert_eq!(taker_stats.fuel_taker, 2500);

now += 1000000;
now += 100000;

let mut margin_context = MarginContext::standard(MarginRequirementType::Initial);

Expand All @@ -302,12 +302,13 @@ pub mod fuel_scoring {
)
.is_err();
assert!(is_errored_attempted);

assert_eq!(taker.last_fuel_bonus_update_ts as i64, 0);
taker.last_fuel_bonus_update_ts = FUEL_START_TS as u32;
margin_context.fuel_bonus_numerator = taker_stats
.get_fuel_bonus_numerator(taker.last_fuel_bonus_update_ts, now)
.get_fuel_bonus_numerator(taker.last_fuel_bonus_update_ts as i64, now)
.unwrap();
assert_eq!(margin_context.fuel_bonus_numerator, 1000000);
assert_eq!(taker.last_fuel_bonus_update_ts, FUEL_START_TS);
assert_eq!(margin_context.fuel_bonus_numerator, 100000);
assert_eq!(taker.last_fuel_bonus_update_ts as i64, FUEL_START_TS);

let margin_calc: MarginCalculation = taker
.calculate_margin_and_increment_fuel_bonus(
Expand All @@ -320,8 +321,8 @@ pub mod fuel_scoring {
)
.unwrap();

assert_eq!(margin_calc.fuel_positions, 51669);
// assert_eq!(taker_stats.fuel_positions, 25000000000 + margin_calc.fuel_positions);
assert_eq!(margin_calc.fuel_positions, 5166);
assert_eq!(taker_stats.fuel_positions, margin_calc.fuel_positions);
}

#[test]
Expand Down
5 changes: 5 additions & 0 deletions programs/drift/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,8 @@ pub mod usdt_pull_oracle {
use solana_program::declare_id;
declare_id!("BekJ3P5G3iFeC97sXHuKnUHofCFj9Sbo7uyF2fkKwvit");
}

pub mod fuel_airdrop_wallet {
use solana_program::declare_id;
declare_id!("5hMjmxexWu954pX9gB9jkHxMqdjpxArQS2XdvkaevRax");
}
Loading
Loading