Skip to content

Commit 71db8bf

Browse files
Nour/gauntlet fee impl (#1698)
* added correlation matrix infra * refactor builds * mint redeem handled for usdc * remove liquidity also should work * all tests pass * bankrun tests pass too
1 parent feda828 commit 71db8bf

File tree

14 files changed

+1344
-383
lines changed

14 files changed

+1344
-383
lines changed

programs/drift/src/instructions/admin.rs

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use std::mem::size_of;
66
use crate::math::amm::calculate_net_user_pnl;
77
use crate::msg;
88
use crate::state::lp_pool::{
9-
AmmConstituentDatum, AmmConstituentMapping, Constituent, ConstituentTargetBase, LPPool,
10-
TargetsDatum, AMM_MAP_PDA_SEED, CONSTITUENT_PDA_SEED, CONSTITUENT_TARGET_BASE_PDA_SEED,
9+
AmmConstituentDatum, AmmConstituentMapping, Constituent, ConstituentCorrelations,
10+
ConstituentTargetBase, LPPool, TargetsDatum, AMM_MAP_PDA_SEED,
11+
CONSTITUENT_CORRELATIONS_PDA_SEED, CONSTITUENT_PDA_SEED, CONSTITUENT_TARGET_BASE_PDA_SEED,
1112
CONSTITUENT_VAULT_PDA_SEED,
1213
};
1314
use anchor_lang::prelude::*;
@@ -4555,7 +4556,9 @@ pub fn handle_initialize_lp_pool(
45554556
usdc_consituent_index: 0,
45564557
cumulative_usdc_sent_to_perp_markets: 0,
45574558
cumulative_usdc_received_from_perp_markets: 0,
4558-
_padding: [0; 10],
4559+
gamma_execution: 2,
4560+
volatility: 4,
4561+
xi: 2,
45594562
};
45604563

45614564
let amm_constituent_mapping = &mut ctx.accounts.amm_constituent_mapping;
@@ -4572,6 +4575,11 @@ pub fn handle_initialize_lp_pool(
45724575
.resize_with(0 as usize, TargetsDatum::default);
45734576
constituent_target_base.validate()?;
45744577

4578+
let consituent_correlations = &mut ctx.accounts.constituent_correlations;
4579+
consituent_correlations.bump = ctx.bumps.constituent_correlations;
4580+
consituent_correlations.correlations.resize(0 as usize, 0);
4581+
consituent_correlations.validate()?;
4582+
45754583
Ok(())
45764584
}
45774585
pub fn handle_update_high_leverage_mode_config(
@@ -4781,6 +4789,11 @@ pub fn handle_initialize_constituent<'info>(
47814789
cost_to_trade_bps: i32,
47824790
constituent_derivative_index: Option<i16>,
47834791
derivative_weight: u64,
4792+
volatility: u64,
4793+
gamma_execution: u8,
4794+
gamma_inventory: u8,
4795+
xi: u8,
4796+
new_constituent_correlations: Vec<i64>,
47844797
) -> Result<()> {
47854798
let mut constituent = ctx.accounts.constituent.load_init()?;
47864799
let mut lp_pool = ctx.accounts.lp_pool.load_mut()?;
@@ -4827,12 +4840,26 @@ pub fn handle_initialize_constituent<'info>(
48274840
constituent.next_swap_id = 1;
48284841
constituent.constituent_derivative_index = constituent_derivative_index.unwrap_or(-1);
48294842
constituent.derivative_weight = derivative_weight;
4843+
constituent.volatility = volatility;
4844+
constituent.gamma_execution = gamma_execution;
4845+
constituent.gamma_inventory = gamma_inventory;
4846+
constituent.xi = xi;
48304847
lp_pool.constituents += 1;
48314848

48324849
if constituent.mint.eq(&usdc_mint::ID) {
48334850
lp_pool.usdc_consituent_index = constituent.constituent_index;
48344851
}
48354852

4853+
let constituent_correlations = &mut ctx.accounts.constituent_correlations;
4854+
validate!(
4855+
new_constituent_correlations.len() as u16 == lp_pool.constituents - 1,
4856+
ErrorCode::InvalidConstituent,
4857+
"expected {} correlations, got {}",
4858+
lp_pool.constituents,
4859+
new_constituent_correlations.len()
4860+
)?;
4861+
constituent_correlations.add_new_constituent(&new_constituent_correlations)?;
4862+
48364863
Ok(())
48374864
}
48384865

@@ -4845,6 +4872,10 @@ pub struct ConstituentParams {
48454872
pub cost_to_trade_bps: Option<i32>,
48464873
pub constituent_derivative_index: Option<i16>,
48474874
pub derivative_weight: Option<u64>,
4875+
pub volatility: Option<u8>,
4876+
pub gamma_execution: Option<u8>,
4877+
pub gamma_inventory: Option<u8>,
4878+
pub xi: Option<u8>,
48484879
}
48494880

48504881
pub fn handle_update_constituent_params<'info>(
@@ -4924,6 +4955,29 @@ pub fn handle_update_constituent_params<'info>(
49244955
constituent_params.constituent_derivative_index.unwrap();
49254956
}
49264957

4958+
if constituent_params.gamma_execution.is_some() {
4959+
msg!(
4960+
"gamma_execution: {:?} -> {:?}",
4961+
constituent.gamma_execution,
4962+
constituent_params.gamma_execution
4963+
);
4964+
constituent.gamma_execution = constituent_params.gamma_execution.unwrap();
4965+
}
4966+
4967+
if constituent_params.gamma_inventory.is_some() {
4968+
msg!(
4969+
"gamma_inventory: {:?} -> {:?}",
4970+
constituent.gamma_inventory,
4971+
constituent_params.gamma_inventory
4972+
);
4973+
constituent.gamma_inventory = constituent_params.gamma_inventory.unwrap();
4974+
}
4975+
4976+
if constituent_params.xi.is_some() {
4977+
msg!("xi: {:?} -> {:?}", constituent.xi, constituent_params.xi);
4978+
constituent.xi = constituent_params.xi.unwrap();
4979+
}
4980+
49274981
Ok(())
49284982
}
49294983

@@ -6214,6 +6268,15 @@ pub struct InitializeLpPool<'info> {
62146268
)]
62156269
pub constituent_target_base: Box<Account<'info, ConstituentTargetBase>>,
62166270

6271+
#[account(
6272+
init,
6273+
seeds = [CONSTITUENT_CORRELATIONS_PDA_SEED.as_ref(), lp_pool.key().as_ref()],
6274+
bump,
6275+
space = ConstituentCorrelations::space(0 as usize),
6276+
payer = admin,
6277+
)]
6278+
pub constituent_correlations: Box<Account<'info, ConstituentCorrelations>>,
6279+
62176280
#[account(
62186281
has_one = admin
62196282
)]
@@ -6253,6 +6316,16 @@ pub struct InitializeConstituent<'info> {
62536316
)]
62546317
pub constituent_target_base: Box<Account<'info, ConstituentTargetBase>>,
62556318

6319+
#[account(
6320+
mut,
6321+
seeds = [CONSTITUENT_CORRELATIONS_PDA_SEED.as_ref(), lp_pool.key().as_ref()],
6322+
bump = constituent_correlations.bump,
6323+
realloc = ConstituentCorrelations::space(constituent_target_base.targets.len() + 1 as usize),
6324+
realloc::payer = admin,
6325+
realloc::zero = false,
6326+
)]
6327+
pub constituent_correlations: Box<Account<'info, ConstituentCorrelations>>,
6328+
62566329
#[account(
62576330
init,
62586331
seeds = [CONSTITUENT_PDA_SEED.as_ref(), lp_pool.key().as_ref(), spot_market_index.to_le_bytes().as_ref()],

programs/drift/src/instructions/lp_pool.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use crate::{
2828
events::{LPMintRedeemRecord, LPSwapRecord},
2929
lp_pool::{
3030
calculate_target_weight, AmmConstituentDatum, AmmConstituentMappingFixed, Constituent,
31-
ConstituentTargetBaseFixed, LPPool, TargetsDatum, WeightValidationFlags,
31+
ConstituentCorrelations, ConstituentCorrelationsFixed, ConstituentTargetBaseFixed,
32+
LPPool, TargetsDatum, WeightValidationFlags, CONSTITUENT_CORRELATIONS_PDA_SEED,
3233
},
3334
oracle::OraclePriceData,
3435
oracle_map::OracleMap,
@@ -480,6 +481,24 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
480481
"Constituent target weights PDA does not match expected PDA"
481482
)?;
482483

484+
let constituent_correlation_key = &ctx.accounts.constituent_correlations.key();
485+
let constituent_correlations: AccountZeroCopy<'_, i64, ConstituentCorrelationsFixed> =
486+
ctx.accounts.constituent_correlations.load_zc()?;
487+
let expected_correlation_pda = &Pubkey::create_program_address(
488+
&[
489+
CONSTITUENT_CORRELATIONS_PDA_SEED.as_ref(),
490+
lp_pool.pubkey.as_ref(),
491+
constituent_correlations.fixed.bump.to_le_bytes().as_ref(),
492+
],
493+
&crate::ID,
494+
)
495+
.map_err(|_| ErrorCode::InvalidPDA)?;
496+
validate!(
497+
expected_correlation_pda.eq(constituent_correlation_key),
498+
ErrorCode::InvalidPDA,
499+
"Constituent correlations PDA does not match expected PDA"
500+
)?;
501+
483502
let AccountMaps {
484503
perp_market_map: _,
485504
spot_market_map,
@@ -558,7 +577,11 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
558577
&out_spot_market,
559578
in_target_weight,
560579
out_target_weight,
561-
in_amount,
580+
in_amount as u128,
581+
constituent_correlations.get_correlation(
582+
in_constituent.constituent_index,
583+
out_constituent.constituent_index,
584+
)?,
562585
)?;
563586
msg!(
564587
"in_amount: {}, out_amount: {}, in_fee: {}, out_fee: {}",
@@ -568,13 +591,13 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
568591
out_fee
569592
);
570593
let out_amount_net_fees = if out_fee > 0 {
571-
out_amount.safe_sub(out_fee.unsigned_abs() as u64)?
594+
out_amount.safe_sub(out_fee.unsigned_abs())?
572595
} else {
573-
out_amount.safe_add(out_fee.unsigned_abs() as u64)?
596+
out_amount.safe_add(out_fee.unsigned_abs())?
574597
};
575598

576599
validate!(
577-
out_amount_net_fees >= min_out_amount,
600+
out_amount_net_fees.cast::<u64>()? >= min_out_amount,
578601
ErrorCode::SlippageOutsideLimit,
579602
format!(
580603
"Slippage outside limit: out_amount_net_fees({}) < min_out_amount({})",
@@ -584,7 +607,7 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
584607
)?;
585608

586609
validate!(
587-
out_amount_net_fees <= out_constituent.token_balance,
610+
out_amount_net_fees.cast::<u64>()? <= out_constituent.token_balance,
588611
ErrorCode::InsufficientConstituentTokenBalance,
589612
format!(
590613
"Insufficient out constituent balance: out_amount_net_fees({}) > out_constituent.token_balance({})",
@@ -640,7 +663,7 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
640663
&ctx.accounts.user_in_token_account,
641664
&ctx.accounts.constituent_in_token_account,
642665
&ctx.accounts.authority,
643-
in_amount,
666+
in_amount.cast::<u64>()?,
644667
&Some((*ctx.accounts.in_market_mint).clone()),
645668
)?;
646669

@@ -650,7 +673,7 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
650673
&ctx.accounts.user_out_token_account,
651674
&ctx.accounts.drift_signer,
652675
state.signer_nonce,
653-
out_amount_net_fees,
676+
out_amount_net_fees.cast::<u64>()?,
654677
&Some((*ctx.accounts.out_market_mint).clone()),
655678
)?;
656679

@@ -669,7 +692,7 @@ pub fn handle_lp_pool_swap<'c: 'info, 'info>(
669692
pub fn handle_lp_pool_add_liquidity<'c: 'info, 'info>(
670693
ctx: Context<'_, '_, 'c, 'info, LPPoolAddLiquidity<'info>>,
671694
in_market_index: u16,
672-
in_amount: u64,
695+
in_amount: u128,
673696
min_mint_amount: u64,
674697
) -> Result<()> {
675698
let slot = Clock::get()?.slot;
@@ -775,7 +798,7 @@ pub fn handle_lp_pool_add_liquidity<'c: 'info, 'info>(
775798
&ctx.accounts.user_in_token_account,
776799
&ctx.accounts.constituent_in_token_account,
777800
&ctx.accounts.authority,
778-
in_amount,
801+
in_amount.cast::<u64>()?,
779802
&Some((*ctx.accounts.in_market_mint).clone()),
780803
)?;
781804

@@ -857,7 +880,7 @@ pub fn handle_lp_pool_remove_liquidity<'c: 'info, 'info>(
857880
ctx: Context<'_, '_, 'c, 'info, LPPoolRemoveLiquidity<'info>>,
858881
out_market_index: u16,
859882
lp_to_burn: u64,
860-
min_amount_out: u64,
883+
min_amount_out: u128,
861884
) -> Result<()> {
862885
let slot = Clock::get()?.slot;
863886
let now = Clock::get()?.unix_timestamp;
@@ -941,9 +964,9 @@ pub fn handle_lp_pool_remove_liquidity<'c: 'info, 'info>(
941964
};
942965

943966
let out_amount_net_fees = if out_fee_amount > 0 {
944-
out_amount.safe_sub(out_fee_amount.unsigned_abs() as u64)?
967+
out_amount.safe_sub(out_fee_amount.unsigned_abs())?
945968
} else {
946-
out_amount.safe_add(out_fee_amount.unsigned_abs() as u64)?
969+
out_amount.safe_add(out_fee_amount.unsigned_abs())?
947970
};
948971

949972
validate!(
@@ -983,7 +1006,7 @@ pub fn handle_lp_pool_remove_liquidity<'c: 'info, 'info>(
9831006
&ctx.accounts.user_out_token_account,
9841007
&ctx.accounts.drift_signer,
9851008
state.signer_nonce,
986-
out_amount_net_fees,
1009+
out_amount_net_fees.cast::<u64>()?,
9871010
&None,
9881011
)?;
9891012

@@ -1284,13 +1307,13 @@ pub struct LPPoolSwap<'info> {
12841307
pub drift_signer: AccountInfo<'info>,
12851308
pub state: Box<Account<'info, State>>,
12861309
pub lp_pool: AccountLoader<'info, LPPool>,
1287-
#[account(
1288-
seeds = [CONSTITUENT_TARGET_BASE_PDA_SEED.as_ref(), lp_pool.key().as_ref()],
1289-
bump,
1290-
)]
1291-
/// CHECK: checked in ConstituentTargetBaseZeroCopy checks
1310+
1311+
/// CHECK: checked in ConstituentTargetBaseZeroCopy checks and in ix
12921312
pub constituent_target_base: AccountInfo<'info>,
12931313

1314+
/// CHECK: checked in ConstituentCorrelationsZeroCopy checks and in ix
1315+
pub constituent_correlations: AccountInfo<'info>,
1316+
12941317
#[account(
12951318
mut,
12961319
address = in_constituent.load()?.token_vault,

programs/drift/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,11 @@ pub mod drift {
17481748
cost_to_trade: i32,
17491749
constituent_derivative_index: Option<i16>,
17501750
derivative_weight: u64,
1751+
volatility: u64,
1752+
gamma_execution: u8,
1753+
gamma_inventory: u8,
1754+
xi: u8,
1755+
new_constituent_correlations: Vec<i64>,
17511756
) -> Result<()> {
17521757
handle_initialize_constituent(
17531758
ctx,
@@ -1760,6 +1765,11 @@ pub mod drift {
17601765
cost_to_trade,
17611766
constituent_derivative_index,
17621767
derivative_weight,
1768+
volatility,
1769+
gamma_execution,
1770+
gamma_inventory,
1771+
xi,
1772+
new_constituent_correlations,
17631773
)
17641774
}
17651775

@@ -1829,7 +1839,7 @@ pub mod drift {
18291839
pub fn lp_pool_add_liquidity<'c: 'info, 'info>(
18301840
ctx: Context<'_, '_, 'c, 'info, LPPoolAddLiquidity<'info>>,
18311841
in_market_index: u16,
1832-
in_amount: u64,
1842+
in_amount: u128,
18331843
min_mint_amount: u64,
18341844
) -> Result<()> {
18351845
handle_lp_pool_add_liquidity(ctx, in_market_index, in_amount, min_mint_amount)
@@ -1839,7 +1849,7 @@ pub mod drift {
18391849
ctx: Context<'_, '_, 'c, 'info, LPPoolRemoveLiquidity<'info>>,
18401850
in_market_index: u16,
18411851
in_amount: u64,
1842-
min_out_amount: u64,
1852+
min_out_amount: u128,
18431853
) -> Result<()> {
18441854
handle_lp_pool_remove_liquidity(ctx, in_market_index, in_amount, min_out_amount)
18451855
}

programs/drift/src/state/constituent_map.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::state::traits::Size;
1616
use crate::{msg, validate};
1717
use std::panic::Location;
1818

19-
use super::lp_pool::{Constituent, CONSTITUENT_PDA_SEED};
19+
use super::lp_pool::Constituent;
2020

2121
pub struct ConstituentMap<'a>(pub BTreeMap<u16, AccountLoader<'a, Constituent>>);
2222

@@ -125,15 +125,15 @@ impl<'a> ConstituentMap<'a> {
125125
}
126126

127127
// Pubkey
128-
let constituent_lp_key = Pubkey::from(*array_ref![data, 184, 32]);
128+
let constituent_lp_key = Pubkey::from(*array_ref![data, 72, 32]);
129129
validate!(
130130
&constituent_lp_key == lp_pool_key,
131131
ErrorCode::InvalidConstituent,
132132
"Constituent lp pool pubkey does not match lp pool pubkey"
133133
)?;
134134

135-
// constituent index 42 bytes from front of account
136-
let constituent_index = u16::from_le_bytes(*array_ref![data, 42, 2]);
135+
// constituent index 276 bytes from front of account
136+
let constituent_index = u16::from_le_bytes(*array_ref![data, 276, 2]);
137137
if constituent_map.0.contains_key(&constituent_index) {
138138
msg!(
139139
"Can not include same constituent index twice {}",

0 commit comments

Comments
 (0)