Skip to content

Commit a08d499

Browse files
committed
added a test
1 parent e6dff79 commit a08d499

File tree

1 file changed

+165
-1
lines changed

1 file changed

+165
-1
lines changed

token-lending/program/tests/refresh_reserve.rs

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
mod helpers;
44

55
use helpers::*;
6+
use solana_program::{
7+
instruction::{AccountMeta, Instruction},
8+
pubkey::Pubkey,
9+
sysvar,
10+
};
611
use solana_program_test::*;
712
use solana_sdk::{
813
signature::{Keypair, Signer},
914
transaction::Transaction,
1015
};
1116
use solend_program::{
12-
instruction::refresh_reserve,
17+
instruction::{refresh_reserve, LendingInstruction},
1318
math::{Decimal, Rate, TryAdd, TryDiv, TryMul, TrySub},
1419
processor::process_instruction,
1520
state::SLOTS_PER_YEAR,
@@ -152,3 +157,162 @@ async fn test_success() {
152157
sol_reserve.liquidity.accumulated_protocol_fees_wads
153158
);
154159
}
160+
161+
#[tokio::test]
162+
async fn test_success_no_switchboard() {
163+
let mut test = ProgramTest::new(
164+
"solend_program",
165+
solend_program::id(),
166+
processor!(process_instruction),
167+
);
168+
169+
// limit to track compute unit increase
170+
test.set_compute_max_units(31_000);
171+
172+
const SOL_RESERVE_LIQUIDITY_LAMPORTS: u64 = 100 * LAMPORTS_TO_SOL;
173+
const USDC_RESERVE_LIQUIDITY_FRACTIONAL: u64 = 100 * FRACTIONAL_TO_USDC;
174+
const BORROW_AMOUNT: u64 = 100;
175+
176+
let user_accounts_owner = Keypair::new();
177+
let lending_market = add_lending_market(&mut test);
178+
179+
let mut reserve_config = test_reserve_config();
180+
reserve_config.loan_to_value_ratio = 80;
181+
182+
// Configure reserve to a fixed borrow rate of 1%
183+
const BORROW_RATE: u8 = 1;
184+
reserve_config.min_borrow_rate = BORROW_RATE;
185+
reserve_config.optimal_borrow_rate = BORROW_RATE;
186+
reserve_config.optimal_utilization_rate = 100;
187+
188+
let usdc_mint = add_usdc_mint(&mut test);
189+
let usdc_oracle = add_usdc_oracle(&mut test);
190+
let usdc_test_reserve = add_reserve(
191+
&mut test,
192+
&lending_market,
193+
&usdc_oracle,
194+
&user_accounts_owner,
195+
AddReserveArgs {
196+
borrow_amount: BORROW_AMOUNT,
197+
liquidity_amount: USDC_RESERVE_LIQUIDITY_FRACTIONAL,
198+
liquidity_mint_decimals: usdc_mint.decimals,
199+
liquidity_mint_pubkey: usdc_mint.pubkey,
200+
config: reserve_config,
201+
slots_elapsed: 1, // elapsed from 1; clock.slot = 2
202+
..AddReserveArgs::default()
203+
},
204+
);
205+
206+
let sol_oracle = add_sol_oracle(&mut test);
207+
let sol_test_reserve = add_reserve(
208+
&mut test,
209+
&lending_market,
210+
&sol_oracle,
211+
&user_accounts_owner,
212+
AddReserveArgs {
213+
borrow_amount: BORROW_AMOUNT,
214+
liquidity_amount: SOL_RESERVE_LIQUIDITY_LAMPORTS,
215+
liquidity_mint_decimals: 9,
216+
liquidity_mint_pubkey: spl_token::native_mint::id(),
217+
config: reserve_config,
218+
slots_elapsed: 1, // elapsed from 1; clock.slot = 2
219+
..AddReserveArgs::default()
220+
},
221+
);
222+
223+
let mut test_context = test.start_with_context().await;
224+
test_context.warp_to_slot(3).unwrap(); // clock.slot = 3
225+
226+
let ProgramTestContext {
227+
mut banks_client,
228+
payer,
229+
last_blockhash: recent_blockhash,
230+
..
231+
} = test_context;
232+
233+
let mut transaction = Transaction::new_with_payer(
234+
&[
235+
refresh_reserve_no_switchboard(
236+
solend_program::id(),
237+
usdc_test_reserve.pubkey,
238+
usdc_oracle.pyth_price_pubkey,
239+
false,
240+
),
241+
refresh_reserve_no_switchboard(
242+
solend_program::id(),
243+
sol_test_reserve.pubkey,
244+
sol_oracle.pyth_price_pubkey,
245+
true,
246+
),
247+
],
248+
Some(&payer.pubkey()),
249+
);
250+
251+
transaction.sign(&[&payer], recent_blockhash);
252+
assert!(banks_client.process_transaction(transaction).await.is_ok());
253+
254+
let sol_reserve = sol_test_reserve.get_state(&mut banks_client).await;
255+
let usdc_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
256+
257+
let slot_rate = Rate::from_percent(BORROW_RATE)
258+
.try_div(SLOTS_PER_YEAR)
259+
.unwrap();
260+
let compound_rate = Rate::one().try_add(slot_rate).unwrap();
261+
let compound_borrow = Decimal::from(BORROW_AMOUNT).try_mul(compound_rate).unwrap();
262+
let net_new_debt = compound_borrow
263+
.try_sub(Decimal::from(BORROW_AMOUNT))
264+
.unwrap();
265+
let protocol_take_rate = Rate::from_percent(usdc_reserve.config.protocol_take_rate);
266+
let delta_accumulated_protocol_fees = net_new_debt.try_mul(protocol_take_rate).unwrap();
267+
268+
assert_eq!(
269+
sol_reserve.liquidity.cumulative_borrow_rate_wads,
270+
compound_rate.into()
271+
);
272+
assert_eq!(
273+
sol_reserve.liquidity.cumulative_borrow_rate_wads,
274+
usdc_reserve.liquidity.cumulative_borrow_rate_wads
275+
);
276+
assert_eq!(sol_reserve.liquidity.borrowed_amount_wads, compound_borrow);
277+
assert_eq!(
278+
sol_reserve.liquidity.borrowed_amount_wads,
279+
usdc_reserve.liquidity.borrowed_amount_wads
280+
);
281+
assert_eq!(
282+
sol_reserve.liquidity.market_price,
283+
sol_test_reserve.market_price
284+
);
285+
assert_eq!(
286+
usdc_reserve.liquidity.market_price,
287+
usdc_test_reserve.market_price
288+
);
289+
assert_eq!(
290+
delta_accumulated_protocol_fees,
291+
usdc_reserve.liquidity.accumulated_protocol_fees_wads
292+
);
293+
assert_eq!(
294+
delta_accumulated_protocol_fees,
295+
sol_reserve.liquidity.accumulated_protocol_fees_wads
296+
);
297+
}
298+
299+
/// Creates a `RefreshReserve` instruction
300+
pub fn refresh_reserve_no_switchboard(
301+
program_id: Pubkey,
302+
reserve_pubkey: Pubkey,
303+
reserve_liquidity_pyth_oracle_pubkey: Pubkey,
304+
with_clock: bool,
305+
) -> Instruction {
306+
let mut accounts = vec![
307+
AccountMeta::new(reserve_pubkey, false),
308+
AccountMeta::new_readonly(reserve_liquidity_pyth_oracle_pubkey, false),
309+
];
310+
if with_clock {
311+
accounts.push(AccountMeta::new_readonly(sysvar::clock::id(), false))
312+
}
313+
Instruction {
314+
program_id,
315+
accounts,
316+
data: LendingInstruction::RefreshReserve.pack(),
317+
}
318+
}

0 commit comments

Comments
 (0)