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
144 changes: 91 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,63 @@ 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
0xbigz marked this conversation as resolved.
Show resolved Hide resolved
|| spot_market.market_index == GOV_SPOT_MARKET_INDEX
|| spot_market.fuel_boost_insurance != 0
{
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 = user_stats
.last_fuel_bonus_update_ts
.max(now_u32)
.safe_sub(now_u32)?;

let fuel_bonus_insurance = if_stake_amount
.cast::<u128>()?
.safe_mul(since_last.cast()?)?
.safe_mul(spot_market.fuel_boost_deposits.cast()?)?
0xbigz marked this conversation as resolved.
Show resolved Hide resolved
.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_bonus_update_ts = now_u32;
}
}

Ok(())
}

pub fn add_insurance_fund_stake(
amount: u64,
insurance_vault_amount: u64,
Expand Down Expand Up @@ -77,19 +135,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 +290,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 +362,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 +458,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(
-(amount.cast()?),
insurance_vault_amount,
insurance_fund_stake,
user_stats,
spot_market,
now,
)?;

emit!(InsuranceFundStakeRecord {
ts: now,
Expand Down
64 changes: 38 additions & 26 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::u64;
use anchor_lang::prelude::*;
use solana_program::msg;

use crate::controller;
use crate::controller::funding::settle_funding_payment;
use crate::controller::lp::burn_lp_shares;
use crate::controller::position;
Expand Down Expand Up @@ -47,6 +46,7 @@ use crate::math::{amm, fees, margin::*, orders::*};
use crate::state::order_params::{
ModifyOrderParams, ModifyOrderPolicy, OrderParams, PlaceOrderOptions, PostOnlyParam,
};
use crate::{controller, FUEL_START_TS};

use crate::math::amm::calculate_amm_available_liquidity;
use crate::math::lp::calculate_lp_shares_to_burn_for_risk_reduction;
Expand Down Expand Up @@ -1720,12 +1720,15 @@ fn fulfill_perp_order(
.fuel_numerator(user, now),
)?;

user_stats.update_fuel_bonus(
taker_margin_calculation.fuel_deposits,
taker_margin_calculation.fuel_borrows,
taker_margin_calculation.fuel_positions,
)?;
user.last_fuel_bonus_update_ts = now;
// user hasnt recieved initial fuel or below global start time
if user.last_fuel_bonus_update_ts != 0 || now > FUEL_START_TS {
0xbigz marked this conversation as resolved.
Show resolved Hide resolved
user_stats.update_fuel_bonus(
taker_margin_calculation.fuel_deposits,
taker_margin_calculation.fuel_borrows,
taker_margin_calculation.fuel_positions,
)?;
user.last_fuel_bonus_update_ts = now.cast()?;
}

if !taker_margin_calculation.meets_margin_requirement() {
msg!(
Expand Down Expand Up @@ -1763,12 +1766,15 @@ fn fulfill_perp_order(
)?;

if let Some(mut maker_stats) = maker_stats {
maker_stats.update_fuel_bonus(
maker_margin_calculation.fuel_deposits,
maker_margin_calculation.fuel_borrows,
maker_margin_calculation.fuel_positions,
)?;
maker.last_fuel_bonus_update_ts = now;
// user hasnt recieved initial fuel
if maker.last_fuel_bonus_update_ts != 0 || now > FUEL_START_TS {
maker_stats.update_fuel_bonus(
maker_margin_calculation.fuel_deposits,
maker_margin_calculation.fuel_borrows,
maker_margin_calculation.fuel_positions,
)?;
maker.last_fuel_bonus_update_ts = now.cast()?;
}
}

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

user_stats.update_fuel_bonus(
taker_margin_calculation.fuel_deposits,
taker_margin_calculation.fuel_borrows,
taker_margin_calculation.fuel_positions,
)?;
user.last_fuel_bonus_update_ts = now;
// user hasnt recieved initial fuel or below global start time
if user.last_fuel_bonus_update_ts != 0 || now > FUEL_START_TS {
user_stats.update_fuel_bonus(
taker_margin_calculation.fuel_deposits,
taker_margin_calculation.fuel_borrows,
taker_margin_calculation.fuel_positions,
)?;
user.last_fuel_bonus_update_ts = now.cast()?;
}

if !taker_margin_calculation.meets_margin_requirement() {
msg!(
Expand Down Expand Up @@ -4155,7 +4164,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 @@ -4178,13 +4187,16 @@ fn fulfill_spot_order(
)?;

if let Some(mut maker_stats) = maker_stats {
maker_stats.update_fuel_bonus(
maker_margin_calculation.fuel_deposits,
maker_margin_calculation.fuel_borrows,
maker_margin_calculation.fuel_positions,
)?;
// user hasnt recieved initial fuel
if maker.last_fuel_bonus_update_ts != 0 || now > FUEL_START_TS {
maker_stats.update_fuel_bonus(
maker_margin_calculation.fuel_deposits,
maker_margin_calculation.fuel_borrows,
maker_margin_calculation.fuel_positions,
)?;

maker.last_fuel_bonus_update_ts = now;
maker.last_fuel_bonus_update_ts = now.cast()?;
}
}

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
Loading