Skip to content

Commit 1c24027

Browse files
authored
add passthrough account logic (#1602)
* add passthrough account logic * cant read yet * fix all zc alignment issues * make oracle source a u8 on zc struct
1 parent 420b85f commit 1c24027

File tree

14 files changed

+817
-80
lines changed

14 files changed

+817
-80
lines changed

programs/drift/src/instructions/admin.rs

Lines changed: 148 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ use crate::state::oracle::{
5757
use crate::state::oracle_map::OracleMap;
5858
use crate::state::paused_operations::{InsuranceFundOperation, PerpOperation, SpotOperation};
5959
use crate::state::perp_market::{
60-
ContractTier, ContractType, InsuranceClaim, MarketStatus, PerpMarket, PoolBalance, AMM,
60+
AmmCache, CacheInfo, ContractTier, ContractType, InsuranceClaim, MarketStatus, PerpMarket,
61+
PoolBalance, AMM, AMM_POSITIONS_CACHE,
6162
};
62-
use crate::state::perp_market_map::get_writable_perp_market_set;
63+
use crate::state::perp_market_map::{get_writable_perp_market_set, MarketSet};
6364
use crate::state::protected_maker_mode_config::ProtectedMakerModeConfig;
6465
use crate::state::pyth_lazer_oracle::{PythLazerOracle, PYTH_LAZER_ORACLE_SEED};
6566
use crate::state::spot_market::{
@@ -1055,6 +1056,22 @@ pub fn handle_initialize_perp_market(
10551056

10561057
safe_increment!(state.number_of_markets, 1);
10571058

1059+
let amm_cache = &mut ctx.accounts.amm_cache;
1060+
let current_len = amm_cache.cache.len();
1061+
amm_cache
1062+
.cache
1063+
.resize_with(current_len + 1, CacheInfo::default);
1064+
let current_market_info = amm_cache.cache.get_mut(current_len).unwrap();
1065+
current_market_info.slot = clock_slot;
1066+
1067+
current_market_info.oracle = perp_market.amm.oracle;
1068+
current_market_info.oracle_source = u8::from(perp_market.amm.oracle_source);
1069+
current_market_info.last_oracle_price_twap = perp_market
1070+
.amm
1071+
.historical_oracle_data
1072+
.last_oracle_price_twap;
1073+
amm_cache.validate(state)?;
1074+
10581075
controller::amm::update_concentration_coef(perp_market, concentration_coef_scale)?;
10591076
crate::dlog!(oracle_price);
10601077

@@ -1070,6 +1087,48 @@ pub fn handle_initialize_perp_market(
10701087
Ok(())
10711088
}
10721089

1090+
pub fn handle_initialize_amm_cache(ctx: Context<InitializeAmmCache>) -> Result<()> {
1091+
let amm_cache = &mut ctx.accounts.amm_cache;
1092+
let state = &ctx.accounts.state;
1093+
amm_cache
1094+
.cache
1095+
.resize_with(state.number_of_markets as usize, CacheInfo::default);
1096+
1097+
Ok(())
1098+
}
1099+
1100+
pub fn handle_update_init_amm_cache_info<'c: 'info, 'info>(
1101+
ctx: Context<'_, '_, 'c, 'info, UpdateInitAmmCacheInfo<'info>>,
1102+
) -> Result<()> {
1103+
let amm_cache = &mut ctx.accounts.amm_cache;
1104+
1105+
let AccountMaps {
1106+
perp_market_map,
1107+
spot_market_map: _,
1108+
oracle_map: _,
1109+
} = load_maps(
1110+
&mut ctx.remaining_accounts.iter().peekable(),
1111+
&MarketSet::new(),
1112+
&MarketSet::new(),
1113+
Clock::get()?.slot,
1114+
None,
1115+
)?;
1116+
1117+
for (_, perp_market_loader) in perp_market_map.0 {
1118+
let perp_market = perp_market_loader.load()?;
1119+
let market_index = perp_market.market_index as usize;
1120+
let cache = amm_cache.cache.get_mut(market_index).unwrap();
1121+
cache.oracle = perp_market.amm.oracle;
1122+
cache.oracle_source = u8::from(perp_market.amm.oracle_source);
1123+
cache.last_oracle_price_twap = perp_market
1124+
.amm
1125+
.historical_oracle_data
1126+
.last_oracle_price_twap;
1127+
}
1128+
1129+
Ok(())
1130+
}
1131+
10731132
#[access_control(
10741133
perp_market_valid(&ctx.accounts.perp_market)
10751134
)]
@@ -3128,10 +3187,11 @@ pub fn handle_update_perp_market_paused_operations(
31283187
perp_market_valid(&ctx.accounts.perp_market)
31293188
)]
31303189
pub fn handle_update_perp_market_contract_tier(
3131-
ctx: Context<AdminUpdatePerpMarket>,
3190+
ctx: Context<AdminUpdatePerpMarketContractTier>,
31323191
contract_tier: ContractTier,
31333192
) -> Result<()> {
31343193
let perp_market = &mut load_mut!(ctx.accounts.perp_market)?;
3194+
let amm_cache = &mut ctx.accounts.amm_cache;
31353195
msg!("perp market {}", perp_market.market_index);
31363196

31373197
msg!(
@@ -3141,6 +3201,14 @@ pub fn handle_update_perp_market_contract_tier(
31413201
);
31423202

31433203
perp_market.contract_tier = contract_tier;
3204+
let max_confidence_interval_multiplier =
3205+
perp_market.get_max_confidence_interval_multiplier()?;
3206+
amm_cache
3207+
.cache
3208+
.get_mut(perp_market.market_index as usize)
3209+
.expect("value should exist for market index")
3210+
.max_confidence_interval_multiplier = max_confidence_interval_multiplier;
3211+
31443212
Ok(())
31453213
}
31463214

@@ -3488,6 +3556,7 @@ pub fn handle_update_perp_market_oracle(
34883556
skip_invariant_check: bool,
34893557
) -> Result<()> {
34903558
let perp_market = &mut load_mut!(ctx.accounts.perp_market)?;
3559+
let amm_cache = &mut ctx.accounts.amm_cache;
34913560
msg!("perp market {}", perp_market.market_index);
34923561

34933562
let clock = Clock::get()?;
@@ -3566,6 +3635,14 @@ pub fn handle_update_perp_market_oracle(
35663635
perp_market.amm.oracle = oracle;
35673636
perp_market.amm.oracle_source = oracle_source;
35683637

3638+
let amm_position_cache_info = amm_cache
3639+
.cache
3640+
.get_mut(perp_market.market_index as usize)
3641+
.expect("value should exist for market index");
3642+
3643+
amm_position_cache_info.oracle = oracle;
3644+
amm_position_cache_info.oracle_source = u8::from(oracle_source);
3645+
35693646
Ok(())
35703647
}
35713648

@@ -4890,12 +4967,57 @@ pub struct InitializePerpMarket<'info> {
48904967
payer = admin
48914968
)]
48924969
pub perp_market: AccountLoader<'info, PerpMarket>,
4970+
#[account(
4971+
mut,
4972+
seeds = [AMM_POSITIONS_CACHE.as_ref()],
4973+
bump,
4974+
realloc = AmmCache::space(amm_cache.cache.len() + 1 as usize),
4975+
realloc::payer = admin,
4976+
realloc::zero = false,
4977+
)]
4978+
pub amm_cache: Box<Account<'info, AmmCache>>,
48934979
/// CHECK: checked in `initialize_perp_market`
48944980
pub oracle: AccountInfo<'info>,
48954981
pub rent: Sysvar<'info, Rent>,
48964982
pub system_program: Program<'info, System>,
48974983
}
48984984

4985+
#[derive(Accounts)]
4986+
pub struct InitializeAmmCache<'info> {
4987+
#[account(
4988+
mut,
4989+
constraint = admin.key() == admin_hot_wallet::id() || admin.key() == state.admin
4990+
)]
4991+
pub admin: Signer<'info>,
4992+
pub state: Box<Account<'info, State>>,
4993+
#[account(
4994+
init,
4995+
seeds = [AMM_POSITIONS_CACHE.as_ref()],
4996+
space = AmmCache::space(state.number_of_markets as usize),
4997+
bump,
4998+
payer = admin
4999+
)]
5000+
pub amm_cache: Box<Account<'info, AmmCache>>,
5001+
pub rent: Sysvar<'info, Rent>,
5002+
pub system_program: Program<'info, System>,
5003+
}
5004+
5005+
#[derive(Accounts)]
5006+
pub struct UpdateInitAmmCacheInfo<'info> {
5007+
#[account(
5008+
mut,
5009+
constraint = admin.key() == admin_hot_wallet::id() || admin.key() == state.admin
5010+
)]
5011+
pub state: Box<Account<'info, State>>,
5012+
pub admin: Signer<'info>,
5013+
#[account(
5014+
mut,
5015+
seeds = [AMM_POSITIONS_CACHE.as_ref()],
5016+
bump,
5017+
)]
5018+
pub amm_cache: Box<Account<'info, AmmCache>>,
5019+
}
5020+
48995021
#[derive(Accounts)]
49005022
pub struct DeleteInitializedPerpMarket<'info> {
49015023
#[account(mut)]
@@ -4920,6 +5042,23 @@ pub struct AdminUpdatePerpMarket<'info> {
49205042
pub perp_market: AccountLoader<'info, PerpMarket>,
49215043
}
49225044

5045+
#[derive(Accounts)]
5046+
pub struct AdminUpdatePerpMarketContractTier<'info> {
5047+
pub admin: Signer<'info>,
5048+
#[account(
5049+
has_one = admin
5050+
)]
5051+
pub state: Box<Account<'info, State>>,
5052+
#[account(mut)]
5053+
pub perp_market: AccountLoader<'info, PerpMarket>,
5054+
#[account(
5055+
mut,
5056+
seeds = [AMM_POSITIONS_CACHE.as_ref()],
5057+
bump,
5058+
)]
5059+
pub amm_cache: Box<Account<'info, AmmCache>>,
5060+
}
5061+
49235062
#[derive(Accounts)]
49245063
pub struct AdminUpdatePerpMarketAmmSummaryStats<'info> {
49255064
#[account(
@@ -5087,6 +5226,12 @@ pub struct AdminUpdatePerpMarketOracle<'info> {
50875226
pub oracle: AccountInfo<'info>,
50885227
/// CHECK: checked in `admin_update_perp_market_oracle` ix constraint
50895228
pub old_oracle: AccountInfo<'info>,
5229+
#[account(
5230+
mut,
5231+
seeds = [AMM_POSITIONS_CACHE.as_ref()],
5232+
bump,
5233+
)]
5234+
pub amm_cache: Box<Account<'info, AmmCache>>,
50905235
}
50915236

50925237
#[derive(Accounts)]

programs/drift/src/instructions/keeper.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ use crate::state::fulfillment_params::serum::SerumFulfillmentParams;
4040
use crate::state::high_leverage_mode_config::HighLeverageModeConfig;
4141
use crate::state::insurance_fund_stake::InsuranceFundStake;
4242
use crate::state::oracle_map::OracleMap;
43-
use crate::state::order_params::{OrderParams, PlaceOrderOptions, SignedMsgOrderParamsMessage};
43+
use crate::state::order_params::{OrderParams, PlaceOrderOptions};
4444
use crate::state::paused_operations::{PerpOperation, SpotOperation};
45+
use crate::state::perp_market::CacheInfo;
46+
use crate::state::perp_market::AMM_POSITIONS_CACHE;
4547
use crate::state::perp_market::{ContractType, MarketStatus, PerpMarket};
4648
use crate::state::perp_market_map::{
4749
get_market_set_for_spot_positions, get_market_set_for_user_positions, get_market_set_from_list,
@@ -62,6 +64,8 @@ use crate::state::user::{
6264
MarginMode, MarketType, OrderStatus, OrderTriggerCondition, OrderType, User, UserStats,
6365
};
6466
use crate::state::user_map::{load_user_map, load_user_maps, UserMap, UserStatsMap};
67+
use crate::state::zero_copy::AccountZeroCopyMut;
68+
use crate::state::zero_copy::ZeroCopyLoader;
6569
use crate::validation::sig_verification::verify_and_decode_ed25519_msg;
6670
use crate::validation::user::{validate_user_deletion, validate_user_is_idle};
6771
use crate::{
@@ -2911,6 +2915,63 @@ pub fn handle_pause_spot_market_deposit_withdraw(
29112915
Ok(())
29122916
}
29132917

2918+
pub fn handle_update_amm_cache<'c: 'info, 'info>(
2919+
ctx: Context<'_, '_, 'c, 'info, UpdateAmmCache<'info>>,
2920+
) -> Result<()> {
2921+
let remaining_accounts_iter = &mut ctx.remaining_accounts.iter().peekable();
2922+
let mut amm_cache: AccountZeroCopyMut<'_, CacheInfo, _> =
2923+
ctx.accounts.amm_cache.load_zc_mut()?;
2924+
let AccountMaps {
2925+
perp_market_map,
2926+
spot_market_map: _,
2927+
mut oracle_map,
2928+
} = load_maps(
2929+
remaining_accounts_iter,
2930+
&MarketSet::new(),
2931+
&MarketSet::new(),
2932+
Clock::get()?.slot,
2933+
None,
2934+
)?;
2935+
let slot = Clock::get()?.slot;
2936+
2937+
for (_, perp_market_loader) in perp_market_map.0.iter() {
2938+
let perp_market = perp_market_loader.load()?;
2939+
let cached_info = amm_cache.get_mut(perp_market.market_index as u32);
2940+
cached_info.position = perp_market.amm.get_protocol_owned_position()?;
2941+
cached_info.slot = slot;
2942+
cached_info.last_oracle_price_twap = perp_market
2943+
.amm
2944+
.historical_oracle_data
2945+
.last_oracle_price_twap;
2946+
2947+
validate!(
2948+
perp_market.oracle_id() == cached_info.oracle_id()?,
2949+
ErrorCode::DefaultError,
2950+
"oracle id mismatch between amm cache and perp market"
2951+
)?;
2952+
2953+
let oracle_data = oracle_map.get_price_data(&perp_market.oracle_id())?;
2954+
cached_info.oracle_price = oracle_data.price;
2955+
cached_info.oracle_delay = oracle_data.delay;
2956+
cached_info.oracle_confidence = oracle_data.confidence;
2957+
}
2958+
2959+
Ok(())
2960+
}
2961+
2962+
#[derive(Accounts)]
2963+
pub struct UpdateAmmCache<'info> {
2964+
#[account(mut)]
2965+
pub keeper: Signer<'info>,
2966+
#[account(
2967+
mut,
2968+
seeds = [AMM_POSITIONS_CACHE.as_ref()],
2969+
bump,
2970+
)]
2971+
/// CHECK: checked in AmmCacheZeroCopy checks
2972+
pub amm_cache: AccountInfo<'info>,
2973+
}
2974+
29142975
#[derive(Accounts)]
29152976
pub struct FillOrder<'info> {
29162977
pub state: Box<Account<'info, State>>,

0 commit comments

Comments
 (0)