Skip to content

Commit 9ebb39a

Browse files
Nour/settle accounting (#1723)
* fixing the main settle test and settle function * all current tests pass * update msg occurrences
1 parent 84569d6 commit 9ebb39a

File tree

7 files changed

+383
-201
lines changed

7 files changed

+383
-201
lines changed

programs/drift/src/instructions/admin.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use anchor_spl::associated_token::AssociatedToken;
33
use std::convert::identity;
44
use std::mem::size_of;
55

6-
use crate::math::amm::{calculate_amm_available_liquidity, calculate_net_user_pnl};
6+
use crate::math::amm::calculate_net_user_pnl;
77
use crate::msg;
88
use crate::state::lp_pool::{
99
AmmConstituentDatum, AmmConstituentMapping, Constituent, ConstituentCorrelations,
@@ -31,13 +31,13 @@ use crate::instructions::constraints::*;
3131
use crate::instructions::optional_accounts::{load_maps, AccountMaps};
3232
use crate::math::casting::Cast;
3333
use crate::math::constants::{
34-
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO, AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO_I128,
35-
DEFAULT_LIQUIDATION_MARGIN_BUFFER_RATIO, FEE_POOL_TO_REVENUE_POOL_THRESHOLD,
36-
IF_FACTOR_PRECISION, INSURANCE_A_MAX, INSURANCE_B_MAX, INSURANCE_C_MAX,
37-
INSURANCE_SPECULATIVE_MAX, LIQUIDATION_FEE_PRECISION, MAX_CONCENTRATION_COEFFICIENT,
38-
MAX_SQRT_K, MAX_UPDATE_K_PRICE_CHANGE, PERCENTAGE_PRECISION, PERCENTAGE_PRECISION_I64,
39-
PRICE_PRECISION_U64, QUOTE_SPOT_MARKET_INDEX, SPOT_CUMULATIVE_INTEREST_PRECISION,
40-
SPOT_IMF_PRECISION, SPOT_WEIGHT_PRECISION, THIRTEEN_DAY, TWENTY_FOUR_HOUR,
34+
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO, DEFAULT_LIQUIDATION_MARGIN_BUFFER_RATIO,
35+
FEE_POOL_TO_REVENUE_POOL_THRESHOLD, IF_FACTOR_PRECISION, INSURANCE_A_MAX, INSURANCE_B_MAX,
36+
INSURANCE_C_MAX, INSURANCE_SPECULATIVE_MAX, LIQUIDATION_FEE_PRECISION,
37+
MAX_CONCENTRATION_COEFFICIENT, MAX_SQRT_K, MAX_UPDATE_K_PRICE_CHANGE, PERCENTAGE_PRECISION,
38+
PERCENTAGE_PRECISION_I64, PRICE_PRECISION_U64, QUOTE_SPOT_MARKET_INDEX,
39+
SPOT_CUMULATIVE_INTEREST_PRECISION, SPOT_IMF_PRECISION, SPOT_WEIGHT_PRECISION, THIRTEEN_DAY,
40+
TWENTY_FOUR_HOUR,
4141
};
4242
use crate::math::cp_curve::get_update_k_result;
4343
use crate::math::helpers::get_proportion_u128;

programs/drift/src/instructions/keeper.rs

Lines changed: 162 additions & 130 deletions
Large diffs are not rendered by default.

programs/drift/src/instructions/lp_pool.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
235235
)?;
236236

237237
let amm_cache_key: &Pubkey = &ctx.accounts.amm_cache.key();
238-
let amm_cache: AccountZeroCopy<'_, CacheInfo, AmmCacheFixed> =
239-
ctx.accounts.amm_cache.load_zc()?;
238+
let amm_cache: AccountZeroCopyMut<'_, CacheInfo, AmmCacheFixed> =
239+
ctx.accounts.amm_cache.load_zc_mut()?;
240240
let expected_amm_pda = &Pubkey::create_program_address(
241241
&[
242242
AMM_POSITIONS_CACHE.as_ref(),
@@ -323,13 +323,11 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
323323
aum = aum.safe_add(constituent_aum.cast()?)?;
324324
}
325325

326+
let mut aum_i128 = aum.cast::<i128>()?;
326327
for cache_datum in amm_cache.iter() {
327-
if cache_datum.quote_owed_from_lp > 0 {
328-
aum = aum.saturating_sub(cache_datum.quote_owed_from_lp.abs().cast::<u128>()?);
329-
} else {
330-
aum = aum.safe_add(cache_datum.quote_owed_from_lp.abs().cast::<u128>()?)?;
331-
}
328+
aum_i128 -= cache_datum.quote_owed_from_lp as i128;
332329
}
330+
aum = aum_i128.max(0i128).cast::<u128>()?;
333331

334332
lp_pool.oldest_oracle_slot = oldest_slot;
335333
lp_pool.last_aum = aum;
@@ -976,6 +974,8 @@ pub fn handle_lp_pool_remove_liquidity<'c: 'info, 'info>(
976974
} else {
977975
out_amount.safe_add(out_fee_amount.unsigned_abs())?
978976
};
977+
let out_amount_net_fees =
978+
out_amount_net_fees.min(ctx.accounts.constituent_out_token_account.amount as u128);
979979

980980
validate!(
981981
out_amount_net_fees >= min_amount_out,
@@ -1302,6 +1302,7 @@ pub struct UpdateLPPoolAum<'info> {
13021302
#[account(mut)]
13031303
pub constituent_target_base: AccountInfo<'info>,
13041304
/// CHECK: checked in AmmCacheZeroCopy checks
1305+
#[account(mut)]
13051306
pub amm_cache: AccountInfo<'info>,
13061307
}
13071308

programs/drift/src/state/lp_pool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ impl LPPool {
256256
token_amount_usd.safe_div(token_precision_denominator)?
257257
} else {
258258
token_amount_usd
259-
.safe_mul(dlp_total_supply as u128)?
259+
.safe_mul(dlp_total_supply.max(1) as u128)?
260260
.safe_div(self.last_aum.safe_mul(token_precision_denominator)?)?
261261
};
262262

programs/drift/src/state/perp_market.rs

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use crate::math::spot_balance::get_token_amount;
12
use crate::state::pyth_lazer_oracle::PythLazerOracle;
2-
use crate::state::zero_copy::AccountZeroCopy;
3+
use crate::state::zero_copy::{AccountZeroCopy, AccountZeroCopyMut};
34
use crate::{impl_zero_copy_loader, validate};
45
use anchor_lang::prelude::*;
56

@@ -9,7 +10,7 @@ use std::convert::TryFrom;
910

1011
use crate::controller::position::{PositionDelta, PositionDirection};
1112
use crate::error::{DriftResult, ErrorCode};
12-
use crate::math::amm;
13+
use crate::math::amm::{self, calculate_net_user_pnl};
1314
use crate::math::casting::Cast;
1415
#[cfg(test)]
1516
use crate::math::constants::{
@@ -38,15 +39,14 @@ use crate::state::oracle::{
3839
get_prelaunch_price, get_sb_on_demand_price, get_switchboard_price, HistoricalOracleData,
3940
OracleSource,
4041
};
41-
use crate::state::spot_market::{AssetTier, SpotBalance, SpotBalanceType};
42+
use crate::state::spot_market::{AssetTier, SpotBalance, SpotBalanceType, SpotMarket};
4243
use crate::state::traits::{MarketIndexOffset, Size};
4344
use borsh::{BorshDeserialize, BorshSerialize};
4445

4546
use crate::state::paused_operations::PerpOperation;
4647
use drift_macros::assert_no_slop;
4748
use static_assertions::const_assert_eq;
4849

49-
use super::oracle::OraclePriceData;
5050
use super::oracle_map::OracleIdentifier;
5151
use super::protected_maker_mode_config::ProtectedMakerParams;
5252
use super::zero_copy::HasLen;
@@ -1740,7 +1740,8 @@ pub struct CacheInfo {
17401740
pub oracle_delay: i64,
17411741
pub oracle_slot: u64,
17421742
pub oracle_source: u8,
1743-
_padding: [u8; 7],
1743+
pub lp_status: u8,
1744+
_padding: [u8; 6],
17441745
pub oracle: Pubkey,
17451746
}
17461747

@@ -1759,14 +1760,15 @@ impl Default for CacheInfo {
17591760
oracle_confidence: 0u64,
17601761
oracle_delay: 0i64,
17611762
oracle_slot: 0u64,
1762-
_padding: [0u8; 7],
1763+
_padding: [0u8; 6],
17631764
oracle: Pubkey::default(),
17641765
last_fee_pool_token_amount: 0u128,
17651766
last_net_pnl_pool_token_amount: 0i128,
17661767
last_settle_amount: 0u64,
17671768
last_settle_ts: 0i64,
17681769
oracle_source: 0u8,
17691770
quote_owed_from_lp: 0i64,
1771+
lp_status: 0u8,
17701772
}
17711773
}
17721774
}
@@ -1858,3 +1860,69 @@ impl<'a> AccountZeroCopy<'a, CacheInfo, AmmCacheFixed> {
18581860
Ok(())
18591861
}
18601862
}
1863+
1864+
impl<'a> AccountZeroCopyMut<'a, CacheInfo, AmmCacheFixed> {
1865+
pub fn update_amount_owed_from_lp_pool(
1866+
&mut self,
1867+
perp_market: &PerpMarket,
1868+
quote_market: &SpotMarket,
1869+
) -> DriftResult<()> {
1870+
if perp_market.lp_fee_transfer_scalar == 0 {
1871+
msg!(
1872+
"lp_fee_transfer_scalar is 0 for perp market {}. not updating quote amount owed in cache",
1873+
perp_market.market_index
1874+
);
1875+
return Ok(());
1876+
}
1877+
1878+
let cached_info = self.get_mut(perp_market.market_index as u32);
1879+
1880+
let fee_pool_token_amount = get_token_amount(
1881+
perp_market.amm.fee_pool.scaled_balance,
1882+
&quote_market,
1883+
perp_market.amm.fee_pool.balance_type(),
1884+
)?;
1885+
1886+
let net_pnl_pool_token_amount = get_token_amount(
1887+
perp_market.pnl_pool.scaled_balance,
1888+
&quote_market,
1889+
perp_market.pnl_pool.balance_type(),
1890+
)?
1891+
.cast::<i128>()?
1892+
.safe_sub(calculate_net_user_pnl(
1893+
&perp_market.amm,
1894+
cached_info.oracle_price,
1895+
)?)?;
1896+
1897+
let amm_amount_available =
1898+
net_pnl_pool_token_amount.safe_add(fee_pool_token_amount.cast::<i128>()?)?;
1899+
1900+
if cached_info.last_net_pnl_pool_token_amount == 0
1901+
&& cached_info.last_fee_pool_token_amount == 0
1902+
{
1903+
cached_info.last_fee_pool_token_amount = fee_pool_token_amount;
1904+
cached_info.last_net_pnl_pool_token_amount = net_pnl_pool_token_amount;
1905+
return Ok(());
1906+
}
1907+
1908+
let amount_to_send = amm_amount_available
1909+
.abs_diff(cached_info.get_last_available_amm_balance()?)
1910+
.safe_div_ceil(perp_market.lp_fee_transfer_scalar as u128)?
1911+
.cast::<u64>()?;
1912+
1913+
if amm_amount_available < cached_info.get_last_available_amm_balance()? {
1914+
cached_info.quote_owed_from_lp = cached_info
1915+
.quote_owed_from_lp
1916+
.safe_add(amount_to_send.cast::<i64>()?)?;
1917+
} else {
1918+
cached_info.quote_owed_from_lp = cached_info
1919+
.quote_owed_from_lp
1920+
.safe_sub(amount_to_send.cast::<i64>()?)?;
1921+
}
1922+
1923+
cached_info.last_fee_pool_token_amount = fee_pool_token_amount;
1924+
cached_info.last_net_pnl_pool_token_amount = net_pnl_pool_token_amount;
1925+
1926+
Ok(())
1927+
}
1928+
}

sdk/src/idl/drift.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8077,7 +8077,7 @@
80778077
},
80788078
{
80798079
"name": "ammCache",
8080-
"isMut": false,
8080+
"isMut": true,
80818081
"isSigner": false
80828082
}
80838083
],
@@ -13072,12 +13072,16 @@
1307213072
"name": "oracleSource",
1307313073
"type": "u8"
1307413074
},
13075+
{
13076+
"name": "lpStatus",
13077+
"type": "u8"
13078+
},
1307513079
{
1307613080
"name": "padding",
1307713081
"type": {
1307813082
"array": [
1307913083
"u8",
13080-
7
13084+
6
1308113085
]
1308213086
}
1308313087
},

0 commit comments

Comments
 (0)