Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
463 changes: 409 additions & 54 deletions programs/drift/src/instructions/admin.rs

Large diffs are not rendered by default.

114 changes: 65 additions & 49 deletions programs/drift/src/instructions/lp_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
get_then_update_id,
math::{
casting::Cast,
constants::PRICE_PRECISION_I128,
constants::{PERCENTAGE_PRECISION_I128, PRICE_PRECISION_I128},
oracle::{is_oracle_valid_for_action, oracle_validity, DriftAction},
safe_math::SafeMath,
},
Expand Down Expand Up @@ -43,7 +43,6 @@ use crate::state::lp_pool::{

pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, UpdateConstituentTargetBase<'info>>,
lp_pool_name: [u8; 32],
constituent_indexes: Vec<u16>,
) -> Result<()> {
let lp_pool = &ctx.accounts.lp_pool.load()?;
Expand Down Expand Up @@ -71,22 +70,6 @@ pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
let constituent_target_base_key = &ctx.accounts.constituent_target_base.key();
let amm_mapping_key = &ctx.accounts.amm_constituent_mapping.key();

// Validate lp pool pda
let expected_lp_pda = &Pubkey::create_program_address(
&[
b"lp_pool",
lp_pool_name.as_ref(),
lp_pool.bump.to_le_bytes().as_ref(),
],
&crate::ID,
)
.map_err(|_| ErrorCode::InvalidPDA)?;
validate!(
expected_lp_pda.eq(lp_pool_key),
ErrorCode::InvalidPDA,
"Lp pool PDA does not match expected PDA"
)?;

let mut constituent_target_base: AccountZeroCopyMut<
'_,
TargetsDatum,
Expand Down Expand Up @@ -228,8 +211,31 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
"Constituent map length does not match lp pool constituent count"
)?;

let constituent_target_base_key = &ctx.accounts.constituent_target_base.key();
let mut constituent_target_base: AccountZeroCopyMut<
'_,
TargetsDatum,
ConstituentTargetBaseFixed,
> = ctx.accounts.constituent_target_base.load_zc_mut()?;
let expected_pda = &Pubkey::create_program_address(
&[
CONSTITUENT_TARGET_BASE_PDA_SEED.as_ref(),
lp_pool.pubkey.as_ref(),
constituent_target_base.fixed.bump.to_le_bytes().as_ref(),
],
&crate::ID,
)
.map_err(|_| ErrorCode::InvalidPDA)?;
validate!(
expected_pda.eq(constituent_target_base_key),
ErrorCode::InvalidPDA,
"Constituent target weights PDA does not match expected PDA"
)?;

let mut aum: u128 = 0;
let mut crypto_delta = 0_i128;
let mut oldest_slot = u64::MAX;
let mut stablecoin_constituent_indexes: Vec<usize> = vec![];
for i in 0..lp_pool.constituents as usize {
let mut constituent = constituent_map.get_ref_mut(&(i as u16))?;

Expand Down Expand Up @@ -286,6 +292,11 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
.safe_mul(oracle_price.unwrap() as i128)?
.safe_div(PRICE_PRECISION_I128)?
.max(0);
if constituent.stablecoin_weight == 0 {
crypto_delta = crypto_delta.safe_add(constituent_aum.cast()?)?;
} else {
stablecoin_constituent_indexes.push(i);
}
aum = aum.safe_add(constituent_aum.cast()?)?;
}

Expand All @@ -294,6 +305,16 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
lp_pool.last_aum_slot = slot;
lp_pool.last_aum_ts = Clock::get()?.unix_timestamp;

let total_stable_target_base = aum.cast::<i128>()?.safe_sub(crypto_delta.abs())?;
for index in stablecoin_constituent_indexes {
let constituent = constituent_map.get_ref(&(index as u16))?;
let stable_target = constituent_target_base.get_mut(index as u32);
stable_target.target_base = total_stable_target_base
.safe_mul(constituent.stablecoin_weight as i128)?
.safe_div(PERCENTAGE_PRECISION_I128)?
.cast::<i64>()?;
}

Ok(())
}

Expand Down Expand Up @@ -892,9 +913,6 @@ pub fn handle_lp_pool_remove_liquidity<'c: 'info, 'info>(
}

#[derive(Accounts)]
#[instruction(
lp_pool_name: [u8; 32],
)]
pub struct UpdateConstituentTargetBase<'info> {
pub state: Box<Account<'info, State>>,
#[account(mut)]
Expand All @@ -905,27 +923,19 @@ pub struct UpdateConstituentTargetBase<'info> {
pub constituent_target_base: AccountInfo<'info>,
/// CHECK: checked in AmmCacheZeroCopy checks
pub amm_cache: AccountInfo<'info>,
#[account(
seeds = [b"lp_pool", lp_pool_name.as_ref()],
bump = lp_pool.load()?.bump,
)]
pub lp_pool: AccountLoader<'info, LPPool>,
}

#[derive(Accounts)]
#[instruction(
lp_pool_name: [u8; 32],
)]
pub struct UpdateLPPoolAum<'info> {
pub state: Box<Account<'info, State>>,
#[account(mut)]
pub keeper: Signer<'info>,
#[account(
mut,
seeds = [b"lp_pool", lp_pool_name.as_ref()],
bump,
)]
#[account(mut)]
pub lp_pool: AccountLoader<'info, LPPool>,
/// CHECK: checked in ConstituentTargetBaseZeroCopy checks
#[account(mut)]
pub constituent_target_base: AccountInfo<'info>,
}

/// `in`/`out` is in the program's POV for this swap. So `user_in_token_account` is the user owned token account
Expand All @@ -947,9 +957,17 @@ pub struct LPPoolSwap<'info> {
/// CHECK: checked in ConstituentTargetBaseZeroCopy checks
pub constituent_target_base: AccountInfo<'info>,

#[account(mut)]
#[account(
mut,
seeds = ["CONSTITUENT_VAULT".as_ref(), lp_pool.key().as_ref(), in_market_index.to_le_bytes().as_ref()],
bump,
)]
pub constituent_in_token_account: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut)]
#[account(
mut,
seeds = ["CONSTITUENT_VAULT".as_ref(), lp_pool.key().as_ref(), out_market_index.to_le_bytes().as_ref()],
bump,
)]
pub constituent_out_token_account: Box<InterfaceAccount<'info, TokenAccount>>,

#[account(
Expand Down Expand Up @@ -995,18 +1013,13 @@ pub struct LPPoolSwap<'info> {

#[derive(Accounts)]
#[instruction(
lp_pool_name: [u8; 32],
in_market_index: u16,
)]
pub struct LPPoolAddLiquidity<'info> {
/// CHECK: forced drift_signer
pub drift_signer: AccountInfo<'info>,
pub state: Box<Account<'info, State>>,
#[account(
mut,
seeds = [b"lp_pool", lp_pool_name.as_ref()],
bump,
)]
#[account(mut)]
pub lp_pool: AccountLoader<'info, LPPool>,
pub authority: Signer<'info>,
pub in_market_mint: Box<InterfaceAccount<'info, Mint>>,
Expand All @@ -1025,7 +1038,11 @@ pub struct LPPoolAddLiquidity<'info> {
)]
pub user_in_token_account: Box<InterfaceAccount<'info, TokenAccount>>,

#[account(mut)]
#[account(
mut,
seeds = ["CONSTITUENT_VAULT".as_ref(), lp_pool.key().as_ref(), in_market_index.to_le_bytes().as_ref()],
bump,
)]
pub constituent_in_token_account: Box<InterfaceAccount<'info, TokenAccount>>,

#[account(
Expand Down Expand Up @@ -1058,18 +1075,13 @@ pub struct LPPoolAddLiquidity<'info> {

#[derive(Accounts)]
#[instruction(
lp_pool_name: [u8; 32],
in_market_index: u16,
)]
pub struct LPPoolRemoveLiquidity<'info> {
/// CHECK: forced drift_signer
pub drift_signer: AccountInfo<'info>,
pub state: Box<Account<'info, State>>,
#[account(
mut,
seeds = [b"lp_pool", lp_pool_name.as_ref()],
bump,
)]
#[account(mut)]
pub lp_pool: AccountLoader<'info, LPPool>,
pub authority: Signer<'info>,
pub out_market_mint: Box<InterfaceAccount<'info, Mint>>,
Expand All @@ -1087,7 +1099,11 @@ pub struct LPPoolRemoveLiquidity<'info> {
constraint = user_out_token_account.mint.eq(&constituent_out_token_account.mint)
)]
pub user_out_token_account: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut)]
#[account(
mut,
seeds = ["CONSTITUENT_VAULT".as_ref(), lp_pool.key().as_ref(), in_market_index.to_le_bytes().as_ref()],
bump,
)]
pub constituent_out_token_account: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(
mut,
Expand Down
32 changes: 20 additions & 12 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1739,15 +1739,14 @@ pub mod drift {

pub fn initialize_constituent<'info>(
ctx: Context<'_, '_, '_, 'info, InitializeConstituent<'info>>,
lp_pool_name: [u8; 32],
spot_market_index: u16,
decimals: u8,
max_weight_deviation: i64,
swap_fee_min: i64,
swap_fee_max: i64,
oracle_staleness_threshold: u64,
beta: i32,
cost_to_trade: i32,
stablecoin_weight: i64,
) -> Result<()> {
handle_initialize_constituent(
ctx,
Expand All @@ -1757,38 +1756,34 @@ pub mod drift {
swap_fee_min,
swap_fee_max,
oracle_staleness_threshold,
beta,
cost_to_trade,
stablecoin_weight,
)
}

pub fn update_constituent_params(
ctx: Context<UpdateConstituentParams>,
lp_pool_name: [u8; 32],
constituent_params: ConstituentParams,
) -> Result<()> {
handle_update_constituent_params(ctx, constituent_params)
}

pub fn add_amm_constituent_mapping_data(
ctx: Context<AddAmmConstituentMappingData>,
lp_pool_name: [u8; 32],
amm_constituent_mapping_data: Vec<AddAmmConstituentMappingDatum>,
) -> Result<()> {
handle_add_amm_constituent_data(ctx, amm_constituent_mapping_data)
}

pub fn update_amm_constituent_mapping_data(
ctx: Context<UpdateAmmConstituentMappingData>,
lp_pool_name: [u8; 32],
amm_constituent_mapping_data: Vec<AddAmmConstituentMappingDatum>,
) -> Result<()> {
handle_update_amm_constituent_mapping_data(ctx, amm_constituent_mapping_data)
}

pub fn remove_amm_constituent_mapping_data<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, RemoveAmmConstituentMappingData<'info>>,
lp_pool_name: [u8; 32],
perp_market_index: u16,
constituent_index: u16,
) -> Result<()> {
Expand All @@ -1797,15 +1792,13 @@ pub mod drift {

pub fn update_lp_constituent_target_base<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, UpdateConstituentTargetBase<'info>>,
lp_pool_name: [u8; 32],
constituent_indexes: Vec<u16>,
) -> Result<()> {
handle_update_constituent_target_base(ctx, lp_pool_name, constituent_indexes)
handle_update_constituent_target_base(ctx, constituent_indexes)
}

pub fn update_lp_pool_aum<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, UpdateLPPoolAum<'info>>,
lp_pool_name: [u8; 32],
) -> Result<()> {
handle_update_lp_pool_aum(ctx)
}
Expand Down Expand Up @@ -1834,7 +1827,6 @@ pub mod drift {

pub fn lp_pool_add_liquidity<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, LPPoolAddLiquidity<'info>>,
_lp_pool_name: [u8; 32],
in_market_index: u16,
in_amount: u64,
min_mint_amount: u64,
Expand All @@ -1844,13 +1836,29 @@ pub mod drift {

pub fn lp_pool_remove_liquidity<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, LPPoolRemoveLiquidity<'info>>,
_lp_pool_name: [u8; 32],
in_market_index: u16,
in_amount: u64,
min_out_amount: u64,
) -> Result<()> {
handle_lp_pool_remove_liquidity(ctx, in_market_index, in_amount, min_out_amount)
}

pub fn begin_lp_swap<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, LPTakerSwap<'info>>,
in_market_index: u16,
out_market_index: u16,
amount_in: u64,
) -> Result<()> {
handle_begin_lp_swap(ctx, in_market_index, out_market_index, amount_in)
}

pub fn end_lp_swap<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, LPTakerSwap<'info>>,
in_market_index: u16,
out_market_index: u16,
) -> Result<()> {
handle_end_lp_swap(ctx)
}
}

#[cfg(not(feature = "no-entrypoint"))]
Expand Down
Loading