-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
0xripleys outflow limits #125
Changes from 5 commits
7a93837
99cec4d
e7adf0d
3fe3564
03843b2
07551e0
2fc35b1
5432602
2255e67
6a7eac9
732b09b
4d3a37c
5e8bffc
0c7b65c
1af333a
275e509
ebec41a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,8 +9,8 @@ use crate::{ | |
state::{ | ||
CalculateBorrowResult, CalculateLiquidationResult, CalculateRepayResult, | ||
InitLendingMarketParams, InitObligationParams, InitReserveParams, LendingMarket, | ||
NewReserveCollateralParams, NewReserveLiquidityParams, Obligation, Reserve, | ||
ReserveCollateral, ReserveConfig, ReserveLiquidity, | ||
LendingMarketConfig, NewReserveCollateralParams, NewReserveLiquidityParams, Obligation, | ||
Reserve, ReserveCollateral, ReserveConfig, ReserveLiquidity, | ||
}, | ||
}; | ||
use pyth_sdk_solana::{self, state::ProductAccount}; | ||
|
@@ -30,6 +30,7 @@ use solana_program::{ | |
Sysvar, | ||
}, | ||
}; | ||
use solend_sdk::state::RateLimiter; | ||
use solend_sdk::{switchboard_v2_devnet, switchboard_v2_mainnet}; | ||
use spl_token::state::Mint; | ||
use std::{cmp::min, result::Result}; | ||
|
@@ -53,9 +54,9 @@ pub fn process_instruction( | |
msg!("Instruction: Init Lending Market"); | ||
process_init_lending_market(program_id, owner, quote_currency, accounts) | ||
} | ||
LendingInstruction::SetLendingMarketOwner { new_owner } => { | ||
LendingInstruction::SetLendingMarketOwnerAndConfig { new_owner, config } => { | ||
msg!("Instruction: Set Lending Market Owner"); | ||
process_set_lending_market_owner(program_id, new_owner, accounts) | ||
process_set_lending_market_owner_and_config(program_id, new_owner, config, accounts) | ||
} | ||
LendingInstruction::InitReserve { | ||
liquidity_amount, | ||
|
@@ -190,16 +191,18 @@ fn process_init_lending_market( | |
token_program_id: *token_program_id.key, | ||
oracle_program_id: *oracle_program_id.key, | ||
switchboard_oracle_program_id: *switchboard_oracle_program_id.key, | ||
current_slot: Clock::get()?.slot, | ||
}); | ||
LendingMarket::pack(lending_market, &mut lending_market_info.data.borrow_mut())?; | ||
|
||
Ok(()) | ||
} | ||
|
||
#[inline(never)] // avoid stack frame limit | ||
fn process_set_lending_market_owner( | ||
fn process_set_lending_market_owner_and_config( | ||
program_id: &Pubkey, | ||
new_owner: Pubkey, | ||
config: LendingMarketConfig, | ||
accounts: &[AccountInfo], | ||
) -> ProgramResult { | ||
let account_info_iter = &mut accounts.iter(); | ||
|
@@ -221,6 +224,19 @@ fn process_set_lending_market_owner( | |
} | ||
|
||
lending_market.owner = new_owner; | ||
if (Decimal::from(config.max_outflow), config.window_duration) | ||
!= ( | ||
lending_market.rate_limiter.max_outflow, | ||
lending_market.rate_limiter.window_duration, | ||
) | ||
{ | ||
lending_market.rate_limiter = RateLimiter::new( | ||
Decimal::from(config.max_outflow), | ||
config.window_duration, | ||
Clock::get()?.slot, | ||
); | ||
} | ||
|
||
LendingMarket::pack(lending_market, &mut lending_market_info.data.borrow_mut())?; | ||
|
||
Ok(()) | ||
|
@@ -659,7 +675,6 @@ fn process_redeem_reserve_collateral( | |
} | ||
let token_program_id = next_account_info(account_info_iter)?; | ||
|
||
_refresh_reserve_interest(program_id, reserve_info, clock)?; | ||
_redeem_reserve_collateral( | ||
program_id, | ||
collateral_amount, | ||
|
@@ -673,6 +688,7 @@ fn process_redeem_reserve_collateral( | |
user_transfer_authority_info, | ||
clock, | ||
token_program_id, | ||
true, | ||
)?; | ||
let mut reserve = Reserve::unpack(&reserve_info.data.borrow())?; | ||
reserve.last_update.mark_stale(); | ||
|
@@ -695,8 +711,9 @@ fn _redeem_reserve_collateral<'a>( | |
user_transfer_authority_info: &AccountInfo<'a>, | ||
clock: &Clock, | ||
token_program_id: &AccountInfo<'a>, | ||
check_rate_limits: bool, | ||
) -> Result<u64, ProgramError> { | ||
let lending_market = LendingMarket::unpack(&lending_market_info.data.borrow())?; | ||
let mut lending_market = LendingMarket::unpack(&lending_market_info.data.borrow())?; | ||
if lending_market_info.owner != program_id { | ||
msg!("Lending market provided is not owned by the lending program"); | ||
return Err(LendingError::InvalidAccountOwner.into()); | ||
|
@@ -750,8 +767,33 @@ fn _redeem_reserve_collateral<'a>( | |
} | ||
|
||
let liquidity_amount = reserve.redeem_collateral(collateral_amount)?; | ||
|
||
if check_rate_limits { | ||
let market_value = reserve | ||
.liquidity | ||
.market_price | ||
.try_mul(Decimal::from(liquidity_amount))?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. try_div(10**reserve.liquidity.mint_decimals) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe call it redemption_value |
||
|
||
lending_market | ||
.rate_limiter | ||
.update(clock.slot, market_value) | ||
.map_err(|err| { | ||
msg!("Market outflow limit exceeded! Please try again later."); | ||
err | ||
})?; | ||
|
||
reserve | ||
.rate_limiter | ||
.update(clock.slot, Decimal::from(liquidity_amount)) | ||
.map_err(|err| { | ||
msg!("Reserve outflow limit exceeded! Please try again later."); | ||
err | ||
})?; | ||
} | ||
|
||
reserve.last_update.mark_stale(); | ||
Reserve::pack(reserve, &mut reserve_info.data.borrow_mut())?; | ||
LendingMarket::pack(lending_market, &mut lending_market_info.data.borrow_mut())?; | ||
|
||
spl_token_burn(TokenBurnParams { | ||
mint: reserve_collateral_mint_info.clone(), | ||
|
@@ -1359,7 +1401,7 @@ fn process_borrow_obligation_liquidity( | |
} | ||
let token_program_id = next_account_info(account_info_iter)?; | ||
|
||
let lending_market = LendingMarket::unpack(&lending_market_info.data.borrow())?; | ||
let mut lending_market = LendingMarket::unpack(&lending_market_info.data.borrow())?; | ||
if lending_market_info.owner != program_id { | ||
msg!("Lending market provided is not owned by the lending program"); | ||
return Err(LendingError::InvalidAccountOwner.into()); | ||
|
@@ -1477,6 +1519,32 @@ fn process_borrow_obligation_liquidity( | |
|
||
let cumulative_borrow_rate_wads = borrow_reserve.liquidity.cumulative_borrow_rate_wads; | ||
|
||
// check outflow rate limits | ||
{ | ||
let market_value = borrow_reserve | ||
.liquidity | ||
.market_price | ||
.try_mul(borrow_amount)?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same divide needed |
||
|
||
lending_market | ||
.rate_limiter | ||
.update(clock.slot, market_value) | ||
.map_err(|err| { | ||
msg!("Market outflow limit exceeded! Please try again later."); | ||
err | ||
})?; | ||
|
||
borrow_reserve | ||
.rate_limiter | ||
.update(clock.slot, borrow_amount) | ||
.map_err(|err| { | ||
msg!("Reserve outflow limit exceeded! Please try again later"); | ||
err | ||
})?; | ||
} | ||
|
||
LendingMarket::pack(lending_market, &mut lending_market_info.data.borrow_mut())?; | ||
|
||
borrow_reserve.liquidity.borrow(borrow_amount)?; | ||
borrow_reserve.last_update.mark_stale(); | ||
Reserve::pack(borrow_reserve, &mut borrow_reserve_info.data.borrow_mut())?; | ||
|
@@ -1885,6 +1953,7 @@ fn process_liquidate_obligation_and_redeem_reserve_collateral( | |
user_transfer_authority_info, | ||
clock, | ||
token_program_id, | ||
false, | ||
)?; | ||
let withdraw_reserve = Reserve::unpack(&withdraw_reserve_info.data.borrow())?; | ||
if &withdraw_reserve.config.fee_receiver != withdraw_reserve_liquidity_fee_receiver_info.key | ||
|
@@ -1959,6 +2028,7 @@ fn process_withdraw_obligation_collateral_and_redeem_reserve_liquidity( | |
user_transfer_authority_info, | ||
clock, | ||
token_program_id, | ||
true, | ||
)?; | ||
Ok(()) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the lending market rate limiter is denominated in usd, we need an up-to-date price so i removed this function call