1
1
//! Program state processor
2
2
3
3
use crate :: {
4
- self as spl_token_lending,
4
+ self as spl_token_lending, emit_log_event ,
5
5
error:: LendingError ,
6
6
instruction:: LendingInstruction ,
7
- logs:: { emit_log_event, PythOraclePriceUpdate , SwitchboardV1OraclePriceUpdate } ,
7
+ logs:: {
8
+ LogEventType , ProgramVersion , PythError , PythOraclePriceUpdate , ReserveStateUpdate ,
9
+ SwitchboardError , SwitchboardV1OraclePriceUpdate ,
10
+ } ,
8
11
math:: { Decimal , Rate , TryAdd , TryDiv , TryMul , TrySub , WAD } ,
9
12
pyth,
10
13
state:: {
11
14
CalculateBorrowResult , CalculateLiquidationResult , CalculateRepayResult ,
12
15
InitLendingMarketParams , InitObligationParams , InitReserveParams , LendingMarket ,
13
16
NewReserveCollateralParams , NewReserveLiquidityParams , Obligation , Reserve ,
14
- ReserveCollateral , ReserveConfig , ReserveLiquidity ,
17
+ ReserveCollateral , ReserveConfig , ReserveLiquidity , PROGRAM_VERSION ,
15
18
} ,
16
19
} ;
17
20
use num_traits:: FromPrimitive ;
@@ -40,6 +43,11 @@ pub fn process_instruction(
40
43
accounts : & [ AccountInfo ] ,
41
44
input : & [ u8 ] ,
42
45
) -> ProgramResult {
46
+ emit_log_event ! ( & ProgramVersion {
47
+ event_type: LogEventType :: ProgramVersion ,
48
+ version: PROGRAM_VERSION ,
49
+ } ) ;
50
+
43
51
let instruction = LendingInstruction :: unpack ( input) ?;
44
52
match instruction {
45
53
LendingInstruction :: InitLendingMarket {
@@ -432,6 +440,15 @@ fn _refresh_reserve_interest<'a>(
432
440
433
441
reserve. accrue_interest ( clock. slot ) ?;
434
442
reserve. last_update . update_slot ( clock. slot ) ;
443
+ emit_log_event ! ( & ReserveStateUpdate {
444
+ event_type: LogEventType :: ReserveStateUpdate ,
445
+ reserve_id: * reserve_info. key,
446
+ available_amount: reserve. liquidity. available_amount,
447
+ borrowed_amount_wads: reserve. liquidity. borrowed_amount_wads,
448
+ cumulative_borrow_rate_wads: reserve. liquidity. cumulative_borrow_rate_wads,
449
+ collateral_mint_total_supply: reserve. collateral. mint_total_supply,
450
+ collateral_exchange_rate: reserve. collateral_exchange_rate( ) ?. to_string( ) ,
451
+ } ) ;
435
452
Reserve :: pack ( reserve, & mut reserve_info. data . borrow_mut ( ) ) ?;
436
453
437
454
Ok ( ( ) )
@@ -807,7 +824,6 @@ fn process_refresh_obligation(program_id: &Pubkey, accounts: &[AccountInfo]) ->
807
824
let decimals = 10u64
808
825
. checked_pow ( deposit_reserve. liquidity . mint_decimals as u32 )
809
826
. ok_or ( LendingError :: MathOverflow ) ?;
810
-
811
827
let market_value = deposit_reserve
812
828
. collateral_exchange_rate ( ) ?
813
829
. decimal_collateral_to_liquidity ( collateral. deposited_amount . into ( ) ) ?
@@ -2153,15 +2169,24 @@ fn get_pyth_price(pyth_price_info: &AccountInfo, clock: &Clock) -> Result<Decima
2153
2169
. map_err ( |_| ProgramError :: InvalidAccountData ) ?;
2154
2170
2155
2171
if pyth_price. ptype != pyth:: PriceType :: Price {
2156
- msg ! ( "Oracle price type is invalid {}" , pyth_price. ptype as u8 ) ;
2172
+ emit_log_event ! ( & PythError {
2173
+ event_type: LogEventType :: PythError ,
2174
+ oracle_pubkey: * pyth_price_info. key,
2175
+ error_message: format!( "Oracle price type is invalid: {}" , pyth_price. ptype as u8 ) ,
2176
+ } ) ;
2177
+
2157
2178
return Err ( LendingError :: InvalidOracleConfig . into ( ) ) ;
2158
2179
}
2159
2180
2160
2181
if pyth_price. agg . status != pyth:: PriceStatus :: Trading {
2161
- msg ! (
2162
- "Oracle price status is invalid: {}" ,
2163
- pyth_price. agg. status as u8
2164
- ) ;
2182
+ emit_log_event ! ( & PythError {
2183
+ event_type: LogEventType :: PythError ,
2184
+ oracle_pubkey: * pyth_price_info. key,
2185
+ error_message: format!(
2186
+ "Oracle price status is invalid: {}" ,
2187
+ pyth_price. agg. status as u8
2188
+ ) ,
2189
+ } ) ;
2165
2190
return Err ( LendingError :: InvalidOracleConfig . into ( ) ) ;
2166
2191
}
2167
2192
@@ -2170,12 +2195,20 @@ fn get_pyth_price(pyth_price_info: &AccountInfo, clock: &Clock) -> Result<Decima
2170
2195
. checked_sub ( pyth_price. valid_slot )
2171
2196
. ok_or ( LendingError :: MathOverflow ) ?;
2172
2197
if slots_elapsed >= STALE_AFTER_SLOTS_ELAPSED {
2173
- msg ! ( "Pyth oracle price is stale" ) ;
2198
+ emit_log_event ! ( & PythError {
2199
+ event_type: LogEventType :: PythError ,
2200
+ oracle_pubkey: * pyth_price_info. key,
2201
+ error_message: format!( "Pyth oracle price is stale: {} slots old." , slots_elapsed) ,
2202
+ } ) ;
2174
2203
return Err ( LendingError :: InvalidOracleConfig . into ( ) ) ;
2175
2204
}
2176
2205
2177
2206
let price: u64 = pyth_price. agg . price . try_into ( ) . map_err ( |_| {
2178
- msg ! ( "Oracle price cannot be negative" ) ;
2207
+ emit_log_event ! ( & PythError {
2208
+ event_type: LogEventType :: PythError ,
2209
+ oracle_pubkey: * pyth_price_info. key,
2210
+ error_message: "Oracle price cannot be negative" . to_string( ) ,
2211
+ } ) ;
2179
2212
LendingError :: InvalidOracleConfig
2180
2213
} ) ?;
2181
2214
@@ -2186,11 +2219,15 @@ fn get_pyth_price(pyth_price_info: &AccountInfo, clock: &Clock) -> Result<Decima
2186
2219
// 100/confidence_ratio = maximum size of confidence range as a percent of price
2187
2220
// confidence_ratio of 10 filters out pyth prices with conf > 10% of price
2188
2221
if conf. checked_mul ( confidence_ratio) . unwrap ( ) > price {
2189
- msg ! (
2190
- "Oracle price confidence is too wide. price: {}, conf: {}" ,
2191
- price,
2192
- conf,
2193
- ) ;
2222
+ emit_log_event ! ( & PythError {
2223
+ event_type: LogEventType :: PythError ,
2224
+ oracle_pubkey: * pyth_price_info. key,
2225
+ error_message: format!(
2226
+ "Oracle price confidence is too wide. price: {}, conf: {}" ,
2227
+ price, conf
2228
+ ) ,
2229
+ } ) ;
2230
+
2194
2231
return Err ( LendingError :: InvalidOracleConfig . into ( ) ) ;
2195
2232
}
2196
2233
@@ -2215,10 +2252,11 @@ fn get_pyth_price(pyth_price_info: &AccountInfo, clock: &Clock) -> Result<Decima
2215
2252
. ok_or ( LendingError :: MathOverflow ) ?;
2216
2253
Decimal :: from ( price) . try_div ( decimals) ?
2217
2254
} ;
2218
- emit_log_event ( & PythOraclePriceUpdate {
2255
+ emit_log_event ! ( & PythOraclePriceUpdate {
2256
+ event_type: LogEventType :: PythOraclePriceUpdate ,
2219
2257
oracle_pubkey: * pyth_price_info. key,
2220
2258
price: market_price,
2221
- conf : conf,
2259
+ confidence : conf,
2222
2260
published_slot: pyth_price. valid_slot,
2223
2261
} ) ;
2224
2262
@@ -2238,7 +2276,11 @@ fn get_switchboard_price(
2238
2276
let account_buf = switchboard_feed_info. try_borrow_data ( ) ?;
2239
2277
// first byte type discriminator
2240
2278
if account_buf[ 0 ] != SwitchboardAccountType :: TYPE_AGGREGATOR as u8 {
2241
- msg ! ( "switchboard address not of type aggregator" ) ;
2279
+ emit_log_event ! ( & SwitchboardError {
2280
+ event_type: LogEventType :: SwitchboardError ,
2281
+ oracle_pubkey: * switchboard_feed_info. key,
2282
+ error_message: "Switchboard feed is not of type aggregator" . to_string( ) ,
2283
+ } ) ;
2242
2284
return Err ( LendingError :: InvalidAccountInput . into ( ) ) ;
2243
2285
}
2244
2286
@@ -2254,7 +2296,11 @@ fn get_switchboard_price(
2254
2296
. checked_sub ( open_slot)
2255
2297
. ok_or ( LendingError :: MathOverflow ) ?;
2256
2298
if slots_elapsed >= STALE_AFTER_SLOTS_ELAPSED {
2257
- msg ! ( "Switchboard oracle price is stale" ) ;
2299
+ emit_log_event ! ( & SwitchboardError {
2300
+ event_type: LogEventType :: SwitchboardError ,
2301
+ oracle_pubkey: * switchboard_feed_info. key,
2302
+ error_message: format!( "Oracle price is stale by {} slots" , slots_elapsed) ,
2303
+ } ) ;
2258
2304
return Err ( LendingError :: InvalidOracleConfig . into ( ) ) ;
2259
2305
}
2260
2306
@@ -2266,7 +2312,8 @@ fn get_switchboard_price(
2266
2312
let price = ( ( price_quotient as f64 ) * price_float) as u128 ;
2267
2313
2268
2314
let market_price = Decimal :: from ( price) . try_div ( price_quotient) ?;
2269
- emit_log_event ( & SwitchboardV1OraclePriceUpdate {
2315
+ emit_log_event ! ( & SwitchboardV1OraclePriceUpdate {
2316
+ event_type: LogEventType :: SwitchboardV1OraclePriceUpdate ,
2270
2317
oracle_pubkey: * switchboard_feed_info. key,
2271
2318
price: market_price,
2272
2319
published_slot: open_slot,
0 commit comments