Skip to content

Commit

Permalink
dupe lite refresh (solana-labs#62) (solana-labs#63)
Browse files Browse the repository at this point in the history
* lite refresh that doesn't take the oracle price when depositing

* mark reserve as stale

* format

* added fask track for repay and made a test

* check that reserve is stale after depositing

* clean up

Co-authored-by: ra <RealAwesomeness@users.noreply.github.com>

Co-authored-by: ra <RealAwesomeness@users.noreply.github.com>
  • Loading branch information
nope-finance and ra authored Jan 23, 2022
1 parent 87f6ca2 commit 920a449
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 21 deletions.
39 changes: 26 additions & 13 deletions token-lending/program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,23 @@ fn _refresh_reserve<'a>(
}

reserve.liquidity.market_price = get_price(switchboard_feed_info, pyth_price_info, clock)?;
Reserve::pack(reserve, &mut reserve_info.data.borrow_mut())?;

_refresh_reserve_interest(program_id, reserve_info, clock)
}

/// Lite version of refresh_reserve that should be used when the oracle price doesn't need to be updated
/// BE CAREFUL WHEN USING THIS
fn _refresh_reserve_interest<'a>(
program_id: &Pubkey,
reserve_info: &AccountInfo<'a>,
clock: &Clock,
) -> ProgramResult {
let mut reserve = Reserve::unpack(&reserve_info.data.borrow())?;
if reserve_info.owner != program_id {
msg!("Reserve provided is not owned by the lending program");
return Err(LendingError::InvalidAccountOwner.into());
}

reserve.accrue_interest(clock.slot)?;
reserve.last_update.update_slot(clock.slot);
Expand Down Expand Up @@ -483,7 +500,6 @@ fn _deposit_reserve_liquidity<'a>(
msg!("Lending market token program does not match the token program provided");
return Err(LendingError::InvalidTokenProgram.into());
}

let mut reserve = Reserve::unpack(&reserve_info.data.borrow())?;
if reserve_info.owner != program_id {
msg!("Reserve provided is not owned by the lending program");
Expand Down Expand Up @@ -513,7 +529,6 @@ fn _deposit_reserve_liquidity<'a>(
msg!("Reserve is stale and must be refreshed in the current slot");
return Err(LendingError::ReserveStale.into());
}

let authority_signer_seeds = &[
lending_market_info.key.as_ref(),
&[lending_market.bump_seed],
Expand Down Expand Up @@ -971,7 +986,6 @@ fn _deposit_obligation_collateral<'a>(
.deposit(collateral_amount)?;
obligation.last_update.mark_stale();
Obligation::pack(obligation, &mut obligation_info.data.borrow_mut())?;

spl_token_transfer(TokenTransferParams {
source: source_collateral_info.clone(),
destination: destination_collateral_info.clone(),
Expand All @@ -980,7 +994,6 @@ fn _deposit_obligation_collateral<'a>(
authority_signer_seeds: &[],
token_program: token_program_id.clone(),
})?;

Ok(())
}

Expand All @@ -1006,12 +1019,13 @@ fn process_deposit_reserve_liquidity_and_obligation_collateral(
let destination_collateral_info = next_account_info(account_info_iter)?;
let obligation_info = next_account_info(account_info_iter)?;
let obligation_owner_info = next_account_info(account_info_iter)?;
let pyth_price_info = next_account_info(account_info_iter)?;
let switchboard_feed_info = next_account_info(account_info_iter)?;
let _pyth_price_info = next_account_info(account_info_iter)?;
let _switchboard_feed_info = next_account_info(account_info_iter)?;
let user_transfer_authority_info = next_account_info(account_info_iter)?;
let clock = &Clock::from_account_info(next_account_info(account_info_iter)?)?;
let token_program_id = next_account_info(account_info_iter)?;

_refresh_reserve_interest(program_id, reserve_info, clock)?;
let collateral_amount = _deposit_reserve_liquidity(
program_id,
liquidity_amount,
Expand All @@ -1026,13 +1040,7 @@ fn process_deposit_reserve_liquidity_and_obligation_collateral(
clock,
token_program_id,
)?;
_refresh_reserve(
program_id,
reserve_info,
pyth_price_info,
switchboard_feed_info,
clock,
)?;
_refresh_reserve_interest(program_id, reserve_info, clock)?;
_deposit_obligation_collateral(
program_id,
collateral_amount,
Expand All @@ -1046,6 +1054,11 @@ fn process_deposit_reserve_liquidity_and_obligation_collateral(
clock,
token_program_id,
)?;
// mark the reserve as stale to make sure no weird bugs happen
let mut reserve = Reserve::unpack(&reserve_info.data.borrow())?;
reserve.last_update.mark_stale();
Reserve::pack(reserve, &mut reserve_info.data.borrow_mut())?;

Ok(())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#![cfg(feature = "test-bpf")]

mod helpers;

use helpers::*;
use solana_program_test::*;
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
use spl_token_lending::processor::process_instruction;

#[tokio::test]
async fn test_success() {
let mut test = ProgramTest::new(
"spl_token_lending",
spl_token_lending::id(),
processor!(process_instruction),
);

// limit to track compute unit increase
test.set_bpf_compute_max_units(70_000);

let user_accounts_owner = Keypair::new();
let lending_market = add_lending_market(&mut test);

let usdc_mint = add_usdc_mint(&mut test);
let usdc_oracle = add_usdc_oracle(&mut test);
let usdc_test_reserve = add_reserve(
&mut test,
&lending_market,
&usdc_oracle,
&user_accounts_owner,
AddReserveArgs {
user_liquidity_amount: 100 * FRACTIONAL_TO_USDC,
liquidity_amount: 10_000 * FRACTIONAL_TO_USDC,
liquidity_mint_decimals: usdc_mint.decimals,
liquidity_mint_pubkey: usdc_mint.pubkey,
config: test_reserve_config(),
mark_fresh: true,
..AddReserveArgs::default()
},
);

let test_obligation = add_obligation(
&mut test,
&lending_market,
&user_accounts_owner,
AddObligationArgs::default(),
);

let (mut banks_client, payer, _recent_blockhash) = test.start().await;

test_obligation.validate_state(&mut banks_client).await;

// let initial_collateral_supply_balance =
// get_token_balance(&mut banks_client, usdc_test_reserve.collateral_supply_pubkey).await;
// let initial_user_collateral_balance =
// get_token_balance(&mut banks_client, usdc_test_reserve.user_collateral_pubkey).await;

lending_market
.deposit_obligation_and_collateral(
&mut banks_client,
&user_accounts_owner,
&payer,
&usdc_test_reserve,
&test_obligation,
100 * FRACTIONAL_TO_USDC,
)
.await;

let usdc_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
assert_eq!(usdc_reserve.last_update.stale, true);
}
19 changes: 11 additions & 8 deletions token-lending/program/tests/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,6 @@ impl TestLendingMarket {
payer: &Keypair,
reserve: &TestReserve,
obligation: &TestObligation,
obligation_keypair: &Keypair,
liquidity_amount: u64,
) {
let user_transfer_authority = Keypair::new();
Expand All @@ -617,6 +616,15 @@ impl TestLendingMarket {
liquidity_amount,
)
.unwrap(),
approve(
&spl_token::id(),
&reserve.user_collateral_pubkey,
&user_transfer_authority.pubkey(),
&user_accounts_owner.pubkey(),
&[],
liquidity_amount,
)
.unwrap(),
deposit_reserve_liquidity_and_obligation_collateral(
spl_token_lending::id(),
liquidity_amount,
Expand All @@ -625,7 +633,7 @@ impl TestLendingMarket {
reserve.pubkey,
reserve.liquidity_supply_pubkey,
reserve.collateral_mint_pubkey,
reserve.pubkey,
self.pubkey,
reserve.collateral_supply_pubkey,
obligation.pubkey,
obligation.owner,
Expand All @@ -639,12 +647,7 @@ impl TestLendingMarket {

let recent_blockhash = banks_client.get_recent_blockhash().await.unwrap();
transaction.sign(
&[
payer,
user_accounts_owner,
&user_transfer_authority,
&obligation_keypair,
],
&[payer, user_accounts_owner, &user_transfer_authority],
recent_blockhash,
);

Expand Down

0 comments on commit 920a449

Please sign in to comment.