1use bytemuck::{Pod, Zeroable};
2use solana_pubkey::Pubkey;
3use spl_discriminator::SplDiscriminate;
4
5use super::{
6 common::{BigFractionBytes, LastUpdate},
7 pod::PodU128,
8};
9
10#[derive(Debug, Clone, Copy, Pod, Zeroable, SplDiscriminate)]
16#[discriminator_hash_input("account:Reserve")]
17#[repr(C)]
18pub struct Reserve {
19 pub version: u64,
20 pub last_update: LastUpdate,
21 pub lending_market: Pubkey,
22 pub farm_collateral: Pubkey,
23 pub farm_debt: Pubkey,
24 pub liquidity: ReserveLiquidity,
25 pub reserve_liquidity_padding: [u64; 150],
26 pub collateral: ReserveCollateral,
27 pub reserve_collateral_padding: [u64; 150],
28 pub config: ReserveConfig,
29 pub config_padding: [u64; 112],
30 pub borrowed_amount_outside_elevation_group: u64,
31 pub borrowed_amounts_against_this_reserve_in_elevation_groups: [u64; 32],
32 pub withdraw_queue: WithdrawQueue,
33 pub padding: [u64; 204],
34}
35
36const _: () = assert!(core::mem::size_of::<Reserve>() == 8616);
37
38impl Reserve {
39 pub fn available_liquidity(&self) -> u64 {
41 self.liquidity.total_available_amount
42 }
43
44 pub fn borrowed_amount(&self) -> u128 {
46 u128::from(self.liquidity.borrowed_amount_sf)
47 }
48
49 pub fn market_price(&self) -> u128 {
51 u128::from(self.liquidity.market_price_sf)
52 }
53
54 pub fn mint_decimals(&self) -> u64 {
56 self.liquidity.mint_decimals
57 }
58
59 pub fn collateral_total_supply(&self) -> u64 {
61 self.collateral.mint_total_supply
62 }
63
64 pub fn accumulated_protocol_fees(&self) -> u128 {
66 u128::from(self.liquidity.accumulated_protocol_fees_sf)
67 }
68
69 pub fn accumulated_referrer_fees(&self) -> u128 {
71 u128::from(self.liquidity.accumulated_referrer_fees_sf)
72 }
73
74 pub fn status(&self) -> u8 {
76 self.config.status
77 }
78
79 pub fn is_emergency_mode(&self) -> bool {
81 self.config.emergency_mode != 0
82 }
83
84 pub fn loan_to_value_pct(&self) -> u8 {
86 self.config.loan_to_value_pct
87 }
88
89 pub fn liquidation_threshold_pct(&self) -> u8 {
91 self.config.liquidation_threshold_pct
92 }
93
94 pub fn borrow_factor_pct(&self) -> u64 {
96 self.config.borrow_factor_pct
97 }
98
99 pub fn deposit_limit(&self) -> u64 {
101 self.config.deposit_limit
102 }
103
104 pub fn borrow_limit(&self) -> u64 {
106 self.config.borrow_limit
107 }
108
109 pub fn next_withdraw_ticket_sequence_number(&self) -> u64 {
111 self.withdraw_queue.next_issued_ticket_sequence_number
112 }
113}
114
115#[derive(Debug, Clone, Copy, Pod, Zeroable)]
121#[repr(C)]
122pub struct ReserveLiquidity {
123 pub mint_pubkey: Pubkey,
124 pub supply_vault: Pubkey,
125 pub fee_vault: Pubkey,
126 pub total_available_amount: u64,
127 pub borrowed_amount_sf: PodU128,
129 pub market_price_sf: PodU128,
131 pub market_price_last_updated_ts: u64,
132 pub mint_decimals: u64,
133 pub deposit_limit_crossed_timestamp: u64,
134 pub borrow_limit_crossed_timestamp: u64,
135 pub cumulative_borrow_rate_bsf: BigFractionBytes,
137 pub accumulated_protocol_fees_sf: PodU128,
139 pub accumulated_referrer_fees_sf: PodU128,
141 pub pending_referrer_fees_sf: PodU128,
143 pub absolute_referral_rate_sf: PodU128,
145 pub token_program: Pubkey,
146 pub rewards_amount_available: u64,
148 pub padding2: [u64; 50],
149 pub padding3: [PodU128; 32],
150}
151
152#[derive(Debug, Clone, Copy, Pod, Zeroable)]
158#[repr(C)]
159pub struct ReserveCollateral {
160 pub mint_pubkey: Pubkey,
161 pub mint_total_supply: u64,
162 pub supply_vault: Pubkey,
163 pub padding1: [PodU128; 32],
164 pub padding2: [PodU128; 32],
165}
166
167#[derive(Debug, Clone, Copy, Pod, Zeroable)]
173#[repr(C)]
174pub struct ReserveConfig {
175 pub status: u8,
177 pub padding_deprecated_asset_tier: u8,
178 pub host_fixed_interest_rate_bps: u16,
179 pub min_deleveraging_bonus_bps: u16,
180 pub block_ctoken_usage: u8,
181 pub early_repay_remaining_interest_pct: u8,
182 pub emergency_mode: u8,
184 pub reserved_1: [u8; 4],
185 pub protocol_order_execution_fee_pct: u8,
186 pub protocol_take_rate_pct: u8,
187 pub protocol_liquidation_fee_pct: u8,
188 pub loan_to_value_pct: u8,
189 pub liquidation_threshold_pct: u8,
190 pub min_liquidation_bonus_bps: u16,
191 pub max_liquidation_bonus_bps: u16,
192 pub bad_debt_liquidation_bonus_bps: u16,
193 pub deleveraging_margin_call_period_secs: u64,
194 pub deleveraging_threshold_decrease_bps_per_day: u64,
195 pub fees: ReserveFees,
196 pub borrow_rate_curve: BorrowRateCurve,
197 pub borrow_factor_pct: u64,
198 pub deposit_limit: u64,
199 pub borrow_limit: u64,
200 pub token_info: TokenInfo,
201 pub deposit_withdrawal_cap: WithdrawalCaps,
202 pub debt_withdrawal_cap: WithdrawalCaps,
203 pub elevation_groups: [u8; 20],
204 pub disable_usage_as_coll_outside_emode: u8,
205 pub utilization_limit_block_borrowing_above_pct: u8,
206 pub autodeleverage_enabled: u8,
207 pub proposer_authority_locked: u8,
208 pub borrow_limit_outside_elevation_group: u64,
209 pub borrow_limit_against_this_collateral_in_elevation_group: [u64; 32],
210 pub deleveraging_bonus_increase_bps_per_day: u64,
211 pub debt_maturity_timestamp: u64,
212 pub debt_term_seconds: u64,
213 pub rewards_amount_per_slot: u64,
215 pub permissioned_ops: u64,
216}
217
218const _: () = assert!(core::mem::size_of::<ReserveConfig>() == 952);
219
220#[derive(Debug, Clone, Copy, Zeroable, Pod)]
225#[repr(C)]
226pub struct ReserveFees {
227 pub origination_fee_sf: u64,
229 pub flash_loan_fee_sf: u64,
231 pub padding: [u8; 8],
232}
233
234#[derive(Debug, Clone, Copy, Zeroable, Pod)]
239#[repr(C)]
240pub struct BorrowRateCurve {
241 pub points: [CurvePoint; 11],
242}
243
244#[derive(Debug, Clone, Copy, Zeroable, Pod)]
245#[repr(C)]
246pub struct CurvePoint {
247 pub utilization_rate_bps: u32,
248 pub borrow_rate_bps: u32,
249}
250
251#[derive(Debug, Clone, Copy, Pod, Zeroable)]
256#[repr(C)]
257pub struct TokenInfo {
258 pub name: [u8; 32],
259 pub heuristic: PriceHeuristic,
260 pub max_twap_divergence_bps: u64,
261 pub max_age_price_seconds: u64,
262 pub max_age_twap_seconds: u64,
263 pub scope_configuration: ScopeConfiguration,
264 pub switchboard_configuration: SwitchboardConfiguration,
265 pub pyth_configuration: PythConfiguration,
266 pub block_price_usage: u8,
267 pub reserved: [u8; 7],
268 pub _padding: [u64; 19],
269}
270
271const _: () = assert!(core::mem::size_of::<TokenInfo>() == 384);
272
273impl TokenInfo {
274 pub fn name_str(&self) -> Option<&str> {
278 let end = self
279 .name
280 .iter()
281 .position(|&b| b == 0)
282 .unwrap_or(self.name.len());
283 core::str::from_utf8(&self.name[..end]).ok()
284 }
285}
286
287#[derive(Debug, Clone, Copy, Zeroable, Pod)]
288#[repr(C)]
289pub struct PriceHeuristic {
290 pub lower: u64,
291 pub upper: u64,
292 pub exp: u64,
293}
294
295#[derive(Debug, Clone, Copy, Zeroable, Pod)]
296#[repr(C)]
297pub struct ScopeConfiguration {
298 pub price_feed: Pubkey,
299 pub price_chain: [u16; 4],
300 pub twap_chain: [u16; 4],
301}
302
303#[derive(Debug, Clone, Copy, Zeroable, Pod)]
304#[repr(C)]
305pub struct SwitchboardConfiguration {
306 pub price_aggregator: Pubkey,
307 pub twap_aggregator: Pubkey,
308}
309
310#[derive(Debug, Clone, Copy, Zeroable, Pod)]
311#[repr(C)]
312pub struct PythConfiguration {
313 pub price: Pubkey,
314}
315
316#[derive(Debug, Clone, Copy, Zeroable, Pod)]
321#[repr(C)]
322pub struct WithdrawalCaps {
323 pub config_capacity: i64,
324 pub current_total: i64,
325 pub last_interval_start_timestamp: u64,
326 pub config_interval_length_seconds: u64,
327}
328
329#[derive(Debug, Clone, Copy, Zeroable, Pod)]
334#[repr(C)]
335pub struct WithdrawQueue {
336 pub queued_collateral_amount: u64,
337 pub next_issued_ticket_sequence_number: u64,
338 pub next_withdrawable_ticket_sequence_number: u64,
339}