1use bytemuck::{Pod, Zeroable};
2use solana_pubkey::Pubkey;
3use spl_discriminator::SplDiscriminate;
4use spl_pod::primitives::PodU128;
5
6use super::common::{BigFractionBytes, LastUpdate};
7
8#[derive(Debug, Clone, Copy, Pod, Zeroable, SplDiscriminate)]
14#[discriminator_hash_input("account:Reserve")]
15#[repr(C)]
16pub struct Reserve {
17 pub version: u64,
18 pub last_update: LastUpdate,
19 pub lending_market: Pubkey,
20 pub farm_collateral: Pubkey,
21 pub farm_debt: Pubkey,
22 pub liquidity: ReserveLiquidity,
23 pub reserve_liquidity_padding: [u64; 150],
24 pub collateral: ReserveCollateral,
25 pub reserve_collateral_padding: [u64; 150],
26 pub config: ReserveConfig,
27 pub config_padding: [u64; 114],
28 pub borrowed_amount_outside_elevation_group: u64,
29 pub borrowed_amounts_against_this_reserve_in_elevation_groups: [u64; 32],
30 pub withdraw_queue: WithdrawQueue,
31 pub padding: [u64; 204],
32}
33
34const _: () = assert!(core::mem::size_of::<Reserve>() == 8616);
35
36impl Reserve {
37 pub fn available_liquidity(&self) -> u64 {
39 self.liquidity.total_available_amount
40 }
41
42 pub fn borrowed_amount(&self) -> u128 {
44 u128::from(self.liquidity.borrowed_amount_sf)
45 }
46
47 pub fn market_price(&self) -> u128 {
49 u128::from(self.liquidity.market_price_sf)
50 }
51
52 pub fn mint_decimals(&self) -> u64 {
54 self.liquidity.mint_decimals
55 }
56
57 pub fn collateral_total_supply(&self) -> u64 {
59 self.collateral.mint_total_supply
60 }
61
62 pub fn accumulated_protocol_fees(&self) -> u128 {
64 u128::from(self.liquidity.accumulated_protocol_fees_sf)
65 }
66
67 pub fn accumulated_referrer_fees(&self) -> u128 {
69 u128::from(self.liquidity.accumulated_referrer_fees_sf)
70 }
71
72 pub fn status(&self) -> u8 {
74 self.config.status
75 }
76
77 pub fn is_emergency_mode(&self) -> bool {
79 self.config.emergency_mode != 0
80 }
81
82 pub fn loan_to_value_pct(&self) -> u8 {
84 self.config.loan_to_value_pct
85 }
86
87 pub fn liquidation_threshold_pct(&self) -> u8 {
89 self.config.liquidation_threshold_pct
90 }
91
92 pub fn borrow_factor_pct(&self) -> u64 {
94 self.config.borrow_factor_pct
95 }
96
97 pub fn deposit_limit(&self) -> u64 {
99 self.config.deposit_limit
100 }
101
102 pub fn borrow_limit(&self) -> u64 {
104 self.config.borrow_limit
105 }
106
107 pub fn next_withdraw_ticket_sequence_number(&self) -> u64 {
109 self.withdraw_queue.next_issued_ticket_sequence_number
110 }
111}
112
113#[derive(Debug, Clone, Copy, Pod, Zeroable)]
119#[repr(C)]
120pub struct ReserveLiquidity {
121 pub mint_pubkey: Pubkey,
122 pub supply_vault: Pubkey,
123 pub fee_vault: Pubkey,
124 pub total_available_amount: u64,
125 pub borrowed_amount_sf: PodU128,
127 pub market_price_sf: PodU128,
129 pub market_price_last_updated_ts: u64,
130 pub mint_decimals: u64,
131 pub deposit_limit_crossed_timestamp: u64,
132 pub borrow_limit_crossed_timestamp: u64,
133 pub cumulative_borrow_rate_bsf: BigFractionBytes,
135 pub accumulated_protocol_fees_sf: PodU128,
137 pub accumulated_referrer_fees_sf: PodU128,
139 pub pending_referrer_fees_sf: PodU128,
141 pub absolute_referral_rate_sf: PodU128,
143 pub token_program: Pubkey,
144 pub padding2: [u64; 51],
145 pub padding3: [PodU128; 32],
146}
147
148#[derive(Debug, Clone, Copy, Pod, Zeroable)]
154#[repr(C)]
155pub struct ReserveCollateral {
156 pub mint_pubkey: Pubkey,
157 pub mint_total_supply: u64,
158 pub supply_vault: Pubkey,
159 pub padding1: [PodU128; 32],
160 pub padding2: [PodU128; 32],
161}
162
163#[derive(Debug, Clone, Copy, Pod, Zeroable)]
169#[repr(C)]
170pub struct ReserveConfig {
171 pub status: u8,
173 pub padding_deprecated_asset_tier: u8,
174 pub host_fixed_interest_rate_bps: u16,
175 pub min_deleveraging_bonus_bps: u16,
176 pub block_ctoken_usage: u8,
177 pub early_repay_remaining_interest_pct: u8,
178 pub emergency_mode: u8,
180 pub reserved_1: [u8; 4],
181 pub protocol_order_execution_fee_pct: u8,
182 pub protocol_take_rate_pct: u8,
183 pub protocol_liquidation_fee_pct: u8,
184 pub loan_to_value_pct: u8,
185 pub liquidation_threshold_pct: u8,
186 pub min_liquidation_bonus_bps: u16,
187 pub max_liquidation_bonus_bps: u16,
188 pub bad_debt_liquidation_bonus_bps: u16,
189 pub deleveraging_margin_call_period_secs: u64,
190 pub deleveraging_threshold_decrease_bps_per_day: u64,
191 pub fees: ReserveFees,
192 pub borrow_rate_curve: BorrowRateCurve,
193 pub borrow_factor_pct: u64,
194 pub deposit_limit: u64,
195 pub borrow_limit: u64,
196 pub token_info: TokenInfo,
197 pub deposit_withdrawal_cap: WithdrawalCaps,
198 pub debt_withdrawal_cap: WithdrawalCaps,
199 pub elevation_groups: [u8; 20],
200 pub disable_usage_as_coll_outside_emode: u8,
201 pub utilization_limit_block_borrowing_above_pct: u8,
202 pub autodeleverage_enabled: u8,
203 pub proposer_authority_locked: u8,
204 pub borrow_limit_outside_elevation_group: u64,
205 pub borrow_limit_against_this_collateral_in_elevation_group: [u64; 32],
206 pub deleveraging_bonus_increase_bps_per_day: u64,
207 pub debt_maturity_timestamp: u64,
208 pub debt_term_seconds: u64,
209}
210
211const _: () = assert!(core::mem::size_of::<ReserveConfig>() == 936);
212
213#[derive(Debug, Clone, Copy, Zeroable, Pod)]
218#[repr(C)]
219pub struct ReserveFees {
220 pub origination_fee_sf: u64,
222 pub flash_loan_fee_sf: u64,
224 pub padding: [u8; 8],
225}
226
227#[derive(Debug, Clone, Copy, Zeroable, Pod)]
232#[repr(C)]
233pub struct BorrowRateCurve {
234 pub points: [CurvePoint; 11],
235}
236
237#[derive(Debug, Clone, Copy, Zeroable, Pod)]
238#[repr(C)]
239pub struct CurvePoint {
240 pub utilization_rate_bps: u32,
241 pub borrow_rate_bps: u32,
242}
243
244#[derive(Debug, Clone, Copy, Pod, Zeroable)]
249#[repr(C)]
250pub struct TokenInfo {
251 pub name: [u8; 32],
252 pub heuristic: PriceHeuristic,
253 pub max_twap_divergence_bps: u64,
254 pub max_age_price_seconds: u64,
255 pub max_age_twap_seconds: u64,
256 pub scope_configuration: ScopeConfiguration,
257 pub switchboard_configuration: SwitchboardConfiguration,
258 pub pyth_configuration: PythConfiguration,
259 pub block_price_usage: u8,
260 pub reserved: [u8; 7],
261 pub _padding: [u64; 19],
262}
263
264const _: () = assert!(core::mem::size_of::<TokenInfo>() == 384);
265
266impl TokenInfo {
267 pub fn name_str(&self) -> Option<&str> {
271 let end = self
272 .name
273 .iter()
274 .position(|&b| b == 0)
275 .unwrap_or(self.name.len());
276 core::str::from_utf8(&self.name[..end]).ok()
277 }
278}
279
280#[derive(Debug, Clone, Copy, Zeroable, Pod)]
281#[repr(C)]
282pub struct PriceHeuristic {
283 pub lower: u64,
284 pub upper: u64,
285 pub exp: u64,
286}
287
288#[derive(Debug, Clone, Copy, Zeroable, Pod)]
289#[repr(C)]
290pub struct ScopeConfiguration {
291 pub price_feed: Pubkey,
292 pub price_chain: [u16; 4],
293 pub twap_chain: [u16; 4],
294}
295
296#[derive(Debug, Clone, Copy, Zeroable, Pod)]
297#[repr(C)]
298pub struct SwitchboardConfiguration {
299 pub price_aggregator: Pubkey,
300 pub twap_aggregator: Pubkey,
301}
302
303#[derive(Debug, Clone, Copy, Zeroable, Pod)]
304#[repr(C)]
305pub struct PythConfiguration {
306 pub price: Pubkey,
307}
308
309#[derive(Debug, Clone, Copy, Zeroable, Pod)]
314#[repr(C)]
315pub struct WithdrawalCaps {
316 pub config_capacity: i64,
317 pub current_total: i64,
318 pub last_interval_start_timestamp: u64,
319 pub config_interval_length_seconds: u64,
320}
321
322#[derive(Debug, Clone, Copy, Zeroable, Pod)]
327#[repr(C)]
328pub struct WithdrawQueue {
329 pub queued_collateral_amount: u64,
330 pub next_issued_ticket_sequence_number: u64,
331 pub next_withdrawable_ticket_sequence_number: u64,
332}