1
- use std:: collections:: BTreeMap ;
2
-
3
1
use anchor_lang:: { prelude:: * , Accounts , Key , Result } ;
4
2
use anchor_spl:: token_interface:: { Mint , TokenAccount , TokenInterface } ;
5
3
@@ -15,10 +13,7 @@ use crate::{
15
13
math:: {
16
14
self ,
17
15
casting:: Cast ,
18
- constants:: {
19
- PERCENTAGE_PRECISION , PERCENTAGE_PRECISION_I128 , PERCENTAGE_PRECISION_I64 ,
20
- PERCENTAGE_PRECISION_U64 , PRICE_PRECISION , PRICE_PRECISION_I128 , QUOTE_PRECISION_I128 ,
21
- } ,
16
+ constants:: { PERCENTAGE_PRECISION_I64 , PRICE_PRECISION } ,
22
17
oracle:: { is_oracle_valid_for_action, oracle_validity, DriftAction } ,
23
18
safe_math:: SafeMath ,
24
19
} ,
@@ -27,9 +22,9 @@ use crate::{
27
22
constituent_map:: { ConstituentMap , ConstituentSet } ,
28
23
events:: { emit_stack, LPMintRedeemRecord , LPSwapRecord } ,
29
24
lp_pool:: {
30
- calculate_target_weight , AmmConstituentDatum , AmmConstituentMappingFixed , Constituent ,
31
- ConstituentCorrelationsFixed , ConstituentTargetBaseFixed , LPPool , TargetsDatum ,
32
- WeightValidationFlags , LP_POOL_SWAP_AUM_UPDATE_DELAY ,
25
+ update_constituent_target_base_for_derivatives , AmmConstituentDatum ,
26
+ AmmConstituentMappingFixed , Constituent , ConstituentCorrelationsFixed ,
27
+ ConstituentTargetBaseFixed , LPPool , TargetsDatum , LP_POOL_SWAP_AUM_UPDATE_DELAY ,
33
28
MAX_AMM_CACHE_STALENESS_FOR_TARGET_CALC ,
34
29
} ,
35
30
oracle:: OraclePriceData ,
@@ -199,6 +194,7 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
199
194
let state = & ctx. accounts . state ;
200
195
201
196
let slot = Clock :: get ( ) ?. slot ;
197
+ let now = Clock :: get ( ) ?. unix_timestamp ;
202
198
203
199
let remaining_accounts = & mut ctx. remaining_accounts . iter ( ) . peekable ( ) ;
204
200
@@ -251,88 +247,14 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
251
247
"Amm cache PDA does not match expected PDA"
252
248
) ?;
253
249
254
- let mut aum: u128 = 0 ;
255
- let mut crypto_delta = 0_i128 ;
256
- let mut oldest_slot = u64:: MAX ;
257
- let mut derivative_groups: BTreeMap < u16 , Vec < u16 > > = BTreeMap :: new ( ) ;
258
- for i in 0 ..lp_pool. constituents as usize {
259
- let constituent = constituent_map. get_ref ( & ( i as u16 ) ) ?;
260
- if slot. saturating_sub ( constituent. last_oracle_slot )
261
- > constituent. oracle_staleness_threshold
262
- {
263
- msg ! (
264
- "Constituent {} oracle slot is too stale: {}, current slot: {}" ,
265
- constituent. constituent_index,
266
- constituent. last_oracle_slot,
267
- slot
268
- ) ;
269
- return Err ( ErrorCode :: ConstituentOracleStale . into ( ) ) ;
270
- }
271
-
272
- if constituent. constituent_derivative_index >= 0 && constituent. derivative_weight != 0 {
273
- if !derivative_groups. contains_key ( & ( constituent. constituent_derivative_index as u16 ) ) {
274
- derivative_groups. insert (
275
- constituent. constituent_derivative_index as u16 ,
276
- vec ! [ constituent. constituent_index] ,
277
- ) ;
278
- } else {
279
- derivative_groups
280
- . get_mut ( & ( constituent. constituent_derivative_index as u16 ) )
281
- . unwrap ( )
282
- . push ( constituent. constituent_index ) ;
283
- }
284
- }
285
-
286
- let spot_market = spot_market_map. get_ref ( & constituent. spot_market_index ) ?;
287
-
288
- let oracle_slot = constituent. last_oracle_slot ;
289
-
290
- if oracle_slot < oldest_slot {
291
- oldest_slot = oracle_slot;
292
- }
293
-
294
- let ( numerator_scale, denominator_scale) = if spot_market. decimals > 6 {
295
- ( 10_i128 . pow ( spot_market. decimals - 6 ) , 1 )
296
- } else {
297
- ( 1 , 10_i128 . pow ( 6 - spot_market. decimals ) )
298
- } ;
299
-
300
- let constituent_aum = constituent
301
- . get_full_balance ( & spot_market) ?
302
- . safe_mul ( numerator_scale) ?
303
- . safe_div ( denominator_scale) ?
304
- . safe_mul ( constituent. last_oracle_price as i128 ) ?
305
- . safe_div ( PRICE_PRECISION_I128 ) ?
306
- . max ( 0 ) ;
307
- msg ! (
308
- "constituent: {}, aum: {}, deriv index: {}" ,
309
- constituent. constituent_index,
310
- constituent_aum,
311
- constituent. constituent_derivative_index
312
- ) ;
313
- if constituent. constituent_index != lp_pool. usdc_consituent_index
314
- && constituent. constituent_derivative_index != lp_pool. usdc_consituent_index as i16
315
- {
316
- let constituent_target_notional = constituent_target_base
317
- . get ( constituent. constituent_index as u32 )
318
- . target_base
319
- . safe_mul ( constituent. last_oracle_price ) ?
320
- . safe_div ( 10_i64 . pow ( constituent. decimals as u32 ) ) ?;
321
- crypto_delta = crypto_delta. safe_add ( constituent_target_notional. cast ( ) ?) ?;
322
- }
323
- aum = aum. safe_add ( constituent_aum. cast ( ) ?) ?;
324
- }
325
-
326
- let mut aum_i128 = aum. cast :: < i128 > ( ) ?;
327
- for cache_datum in amm_cache. iter ( ) {
328
- aum_i128 -= cache_datum. quote_owed_from_lp_pool as i128 ;
329
- }
330
- aum = aum_i128. max ( 0i128 ) . cast :: < u128 > ( ) ?;
331
-
332
- lp_pool. oldest_oracle_slot = oldest_slot;
333
- lp_pool. last_aum = aum;
334
- lp_pool. last_aum_slot = slot;
335
- lp_pool. last_aum_ts = Clock :: get ( ) ?. unix_timestamp ;
250
+ let ( aum, crypto_delta, derivative_groups) = lp_pool. update_aum (
251
+ now,
252
+ slot,
253
+ & constituent_map,
254
+ & spot_market_map,
255
+ & constituent_target_base,
256
+ & amm_cache,
257
+ ) ?;
336
258
337
259
// Set USDC stable weight
338
260
let total_stable_target_base = aum
@@ -341,16 +263,7 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
341
263
. max ( 0_i128 ) ;
342
264
constituent_target_base
343
265
. get_mut ( lp_pool. usdc_consituent_index as u32 )
344
- . target_base = total_stable_target_base
345
- . safe_mul (
346
- 10_i128 . pow (
347
- constituent_map
348
- . get_ref ( & lp_pool. usdc_consituent_index ) ?
349
- . decimals as u32 ,
350
- ) ,
351
- ) ?
352
- . safe_div ( QUOTE_PRECISION_I128 ) ?
353
- . cast :: < i64 > ( ) ?;
266
+ . target_base = total_stable_target_base. cast :: < i64 > ( ) ?;
354
267
355
268
msg ! (
356
269
"stable target base: {}" ,
@@ -361,75 +274,13 @@ pub fn handle_update_lp_pool_aum<'c: 'info, 'info>(
361
274
msg ! ( "aum: {}, crypto_delta: {}" , aum, crypto_delta) ;
362
275
msg ! ( "derivative groups: {:?}" , derivative_groups) ;
363
276
364
- // Handle all other derivatives
365
- for ( parent_index, constituent_indexes) in derivative_groups. iter ( ) {
366
- let parent_constituent = constituent_map. get_ref ( & ( parent_index) ) ?;
367
- let parent_target_base = constituent_target_base
368
- . get ( * parent_index as u32 )
369
- . target_base ;
370
- let target_parent_weight = calculate_target_weight (
371
- parent_target_base,
372
- & * spot_market_map. get_ref ( & parent_constituent. spot_market_index ) ?,
373
- parent_constituent. last_oracle_price ,
374
- aum,
375
- WeightValidationFlags :: NONE ,
376
- ) ?;
377
- let mut derivative_weights_sum = 0 ;
378
- for constituent_index in constituent_indexes {
379
- let constituent = constituent_map. get_ref ( constituent_index) ?;
380
- if constituent. last_oracle_price
381
- < parent_constituent
382
- . last_oracle_price
383
- . safe_mul ( constituent. constituent_derivative_depeg_threshold as i64 ) ?
384
- . safe_div ( PERCENTAGE_PRECISION_I64 ) ?
385
- {
386
- msg ! (
387
- "Constituent {} last oracle price {} is too low compared to parent constituent {} last oracle price {}. Assuming depegging and setting target base to 0." ,
388
- constituent. constituent_index,
389
- constituent. last_oracle_price,
390
- parent_constituent. constituent_index,
391
- parent_constituent. last_oracle_price
392
- ) ;
393
- constituent_target_base
394
- . get_mut ( * constituent_index as u32 )
395
- . target_base = 0_i64 ;
396
- continue ;
397
- }
398
-
399
- derivative_weights_sum += constituent. derivative_weight ;
400
-
401
- let target_weight = target_parent_weight
402
- . safe_mul ( constituent. derivative_weight as i64 ) ?
403
- . safe_div ( PERCENTAGE_PRECISION_I64 ) ?;
404
-
405
- msg ! (
406
- "constituent: {}, target weight: {}" ,
407
- constituent_index,
408
- target_weight,
409
- ) ;
410
- let target_base = lp_pool
411
- . last_aum
412
- . cast :: < i128 > ( ) ?
413
- . safe_mul ( target_weight as i128 ) ?
414
- . safe_div ( PERCENTAGE_PRECISION_I128 ) ?
415
- . safe_mul ( 10_i128 . pow ( constituent. decimals as u32 ) ) ?
416
- . safe_div ( constituent. last_oracle_price as i128 ) ?;
417
-
418
- msg ! (
419
- "constituent: {}, target base: {}" ,
420
- constituent_index,
421
- target_base
422
- ) ;
423
- constituent_target_base
424
- . get_mut ( * constituent_index as u32 )
425
- . target_base = target_base. cast :: < i64 > ( ) ?;
426
- }
427
- constituent_target_base
428
- . get_mut ( * parent_index as u32 )
429
- . target_base = parent_target_base
430
- . safe_mul ( PERCENTAGE_PRECISION_U64 . safe_sub ( derivative_weights_sum) ? as i64 ) ?
431
- . safe_div ( PERCENTAGE_PRECISION_I64 ) ?;
432
- }
277
+ update_constituent_target_base_for_derivatives (
278
+ aum,
279
+ & derivative_groups,
280
+ & constituent_map,
281
+ & spot_market_map,
282
+ & mut constituent_target_base,
283
+ ) ?;
433
284
434
285
Ok ( ( ) )
435
286
}
0 commit comments