1- use crate :: error:: { DriftResult , ErrorCode } ;
1+ use crate :: error:: DriftResult ;
22use crate :: math:: casting:: Cast ;
33use crate :: math:: constants:: { PERCENTAGE_PRECISION_I128 , PERCENTAGE_PRECISION_I64 } ;
44use crate :: math:: safe_math:: SafeMath ;
5- use crate :: state:: oracle:: OracleSource ;
6- use crate :: state:: spot_market:: { SpotBalance , SpotBalanceType , SpotMarket } ;
5+ use crate :: state:: spot_market:: { SpotBalance , SpotBalanceType } ;
76use crate :: state:: traits:: Size ;
87use anchor_lang:: prelude:: * ;
8+ use anchor_lang:: Discriminator ;
99use borsh:: { BorshDeserialize , BorshSerialize } ;
1010
11+ use super :: zero_copy:: { AccountZeroCopy , AccountZeroCopyMut , HasLen } ;
12+ use crate :: impl_zero_copy_loader;
13+
1114#[ cfg( test) ]
1215mod tests;
1316
14- #[ account( zero_copy) ]
17+ #[ account( zero_copy( unsafe ) ) ]
1518#[ derive( Default , Debug ) ]
1619#[ repr( C ) ]
1720pub struct LPPool {
@@ -40,7 +43,7 @@ pub struct LPPool {
4043 /// timestamp of last AUM slot
4144 pub last_aum_slot : u64 , // 8, 152
4245 /// timestamp of last AUM update
43- pub last_aum_ts : u64 , // 8, 160
46+ pub last_aum_ts : u64 , // 8, 160``
4447
4548 /// timestamp of last vAMM revenue rebalance
4649 pub last_revenue_rebalance_ts : u64 , // 8, 168
@@ -51,7 +54,7 @@ pub struct LPPool {
5154 pub total_fees_paid : u128 , // 16, 192
5255
5356 pub constituents : u16 , // 2, 194
54- pub padding : [ u8 ; 6 ] ,
57+ pub _padding : [ u8 ; 6 ] ,
5558}
5659
5760impl Size for LPPool {
@@ -131,9 +134,6 @@ pub struct Constituent {
131134 pub padding : [ u8 ; 16 ] ,
132135}
133136
134- // pub struct PerpConstituent {
135- // }
136-
137137#[ zero_copy]
138138#[ derive( Debug , BorshDeserialize , BorshSerialize ) ]
139139#[ repr( C ) ]
@@ -146,6 +146,34 @@ pub struct AmmConstituentDatum {
146146 pub last_slot : u64 ,
147147}
148148
149+ #[ zero_copy]
150+ pub struct AmmConstituentMappingFixed {
151+ pub len : u32 ,
152+ }
153+
154+ impl HasLen for AmmConstituentMappingFixed {
155+ fn len ( & self ) -> u32 {
156+ self . len
157+ }
158+ }
159+
160+ #[ account]
161+ #[ derive( Debug ) ]
162+ #[ repr( C ) ]
163+ pub struct AmmConstituentMapping {
164+ // PERCENTAGE_PRECISION. Each datum represents the target weight for a single (AMM, Constituent) pair.
165+ // An AMM may be partially backed by multiple Constituents
166+ pub data : Vec < AmmConstituentDatum > ,
167+ }
168+
169+ impl_zero_copy_loader ! (
170+ AmmConstituentMapping ,
171+ crate :: id,
172+ AmmConstituentMappingFixed ,
173+ AmmConstituentDatum ,
174+ AmmConstituentMapping :: discriminator( )
175+ ) ;
176+
149177#[ zero_copy]
150178#[ derive( Debug , BorshDeserialize , BorshSerialize ) ]
151179#[ repr( C ) ]
@@ -157,13 +185,18 @@ pub struct WeightDatum {
157185 pub last_slot : u64 ,
158186}
159187
160- #[ account ]
188+ #[ zero_copy ]
161189#[ derive( Debug ) ]
162190#[ repr( C ) ]
163- pub struct AmmConstituentMapping {
164- // PERCENTAGE_PRECISION. Each datum represents the target weight for a single (AMM, Constituent) pair.
165- // An AMM may be partially backed by multiple Constituents
166- pub data : Vec < AmmConstituentDatum > ,
191+ pub struct ConstituentTargetWeightsFixed {
192+ /// total elements in the flattened `data` vec
193+ pub len : u32 ,
194+ }
195+
196+ impl HasLen for ConstituentTargetWeightsFixed {
197+ fn len ( & self ) -> u32 {
198+ self . len
199+ }
167200}
168201
169202#[ account]
@@ -174,6 +207,14 @@ pub struct ConstituentTargetWeights {
174207 pub data : Vec < WeightDatum > ,
175208}
176209
210+ impl_zero_copy_loader ! (
211+ ConstituentTargetWeights ,
212+ crate :: id,
213+ ConstituentTargetWeightsFixed ,
214+ WeightDatum ,
215+ ConstituentTargetWeights :: discriminator( )
216+ ) ;
217+
177218impl Default for ConstituentTargetWeights {
178219 fn default ( ) -> Self {
179220 ConstituentTargetWeights {
@@ -182,61 +223,46 @@ impl Default for ConstituentTargetWeights {
182223 }
183224}
184225
185- impl ConstituentTargetWeights {
226+ impl < ' a > AccountZeroCopyMut < ' a , WeightDatum , ConstituentTargetWeightsFixed > {
186227 /// Update target weights based on amm_inventory and mapping
187228 pub fn update_target_weights (
188229 & mut self ,
189- mapping : & AmmConstituentMapping ,
190- amm_inventory : & [ ( u16 , i64 ) ] ,
191- constituents : & [ Constituent ] ,
192- prices : & [ u64 ] , // same order as constituents
230+ mapping : & AccountZeroCopy < ' a , AmmConstituentDatum , AmmConstituentMappingFixed > ,
231+ // (perp market index, inventory, price)
232+ amm_inventory : & [ ( u16 , i64 ) ] , // length = mapping.num_rows
233+ constituents_indexes : & [ u16 ] ,
234+ prices : & [ i64 ] , // length = mapping.num_rows
193235 aum : u64 ,
194236 slot : u64 ,
195237 ) -> DriftResult < ( ) > {
196- // assert_ne!(aum, 0);
197- assert_eq ! ( prices. len( ) , constituents. len( ) ) ;
198-
199- self . data . clear ( ) ;
200-
201- for ( constituent_index, constituent) in constituents. iter ( ) . enumerate ( ) {
238+ for ( i, constituent_index) in constituents_indexes. iter ( ) . enumerate ( ) {
202239 let mut target_amount = 0i128 ;
203240
204241 for ( perp_market_index, inventory) in amm_inventory. iter ( ) {
205242 let idx = mapping
206- . data
207243 . iter ( )
208244 . position ( |d| & d. perp_market_index == perp_market_index)
209245 . expect ( "missing mapping for this market index" ) ;
210- let weight = mapping. data [ idx] . data ; // PERCENTAGE_PRECISION
246+ let weight = mapping. get ( idx) . data ; // PERCENTAGE_PRECISION
211247 target_amount +=
212248 ( * inventory as i128 ) * weight as i128 / PERCENTAGE_PRECISION_I64 as i128 ;
213249 }
214250
215- let price = prices[ constituent_index ] as i128 ;
251+ let price = prices[ i ] as i128 ;
216252 let target_weight = target_amount
217253 . saturating_mul ( price)
218254 . saturating_div ( aum. max ( 1 ) as i128 ) ;
219255
220256 // PERCENTAGE_PRECISION capped
221257 let weight_datum = ( target_weight) . min ( PERCENTAGE_PRECISION_I128 ) ;
222258
223- self . data . push ( WeightDatum {
224- constituent_index : constituent_index as u16 ,
225- padding : [ 0 ; 6 ] ,
226- data : weight_datum as i64 ,
227- last_slot : slot,
228- } ) ;
259+ let cell = self . get_mut ( * constituent_index as u32 ) ;
260+ cell. constituent_index = * constituent_index;
261+ cell. padding = [ 0 ; 6 ] ;
262+ cell. data = weight_datum as i64 ;
263+ cell. last_slot = slot;
229264 }
230265
231266 Ok ( ( ) )
232267 }
233-
234- pub fn get_target_weight ( & self , constituent_index : u16 ) -> DriftResult < i64 > {
235- let weight_datum = self
236- . data
237- . iter ( )
238- . find ( |d| d. constituent_index == constituent_index)
239- . expect ( "missing target weight for this constituent" ) ;
240- Ok ( weight_datum. data )
241- }
242268}
0 commit comments