Skip to content

Commit

Permalink
Release 1.8.1 (#26)
Browse files Browse the repository at this point in the history
- Add flag to skip ltv priority
- Make referrer an account argument rather than parameter when initialising referrer token states
- Add constraint on disable usage as coll in request elevation group
- Add missing refresh obligation checks
- Remove global unhealthy borrow value
oeble authored Jan 14, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent c183a70 commit c76cc96
Showing 12 changed files with 87 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ pub fn process<'info>(
let referrer_token_state = referrer_token_state_loader.load_mut()?;

validate_referrer_token_state(
&crate::ID,
&referrer_token_state,
referrer_token_state_loader.key(),
borrow_reserve.liquidity.mint_pubkey,
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ pub fn process(
let referrer_token_state = &mut referrer_token_state_loader.load_mut()?;

validate_referrer_token_state(
&crate::ID,
referrer_token_state,
referrer_token_state_loader.key(),
reserve.liquidity.mint_pubkey,
Original file line number Diff line number Diff line change
@@ -5,9 +5,10 @@ use crate::{
LendingMarket, ReferrerTokenState, Reserve,
};

pub fn process(ctx: Context<InitReferrerTokenState>, referrer: Pubkey) -> Result<()> {
pub fn process(ctx: Context<InitReferrerTokenState>) -> Result<()> {
let mut referrer_token_state = ctx.accounts.referrer_token_state.load_init()?;
let reserve = ctx.accounts.reserve.load()?;
let referrer = ctx.accounts.referrer.key();
let bump = ctx.bumps.referrer_token_state;

*referrer_token_state = ReferrerTokenState {
@@ -23,7 +24,6 @@ pub fn process(ctx: Context<InitReferrerTokenState>, referrer: Pubkey) -> Result
}

#[derive(Accounts)]
#[instruction(referrer: Pubkey)]
pub struct InitReferrerTokenState<'info> {
#[account(mut)]
pub payer: Signer<'info>,
@@ -35,8 +35,10 @@ pub struct InitReferrerTokenState<'info> {
)]
pub reserve: AccountLoader<'info, Reserve>,

pub referrer: AccountInfo<'info>,

#[account(init,
seeds = [BASE_SEED_REFERRER_TOKEN_STATE, referrer.as_ref(), reserve.key().as_ref()],
seeds = [BASE_SEED_REFERRER_TOKEN_STATE, referrer.key().as_ref(), reserve.key().as_ref()],
bump,
payer = payer,
space = REFERRER_TOKEN_STATE_SIZE + 8,
1 change: 1 addition & 0 deletions programs/klend/src/handlers/handler_refresh_obligation.rs
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ pub fn process(ctx: Context<RefreshObligation>) -> Result<()> {
});

lending_operations::refresh_obligation(
&crate::ID,
obligation,
lending_market,
clock.slot,
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ pub fn process(ctx: Context<RequestElevationGroup>, new_elevation_group: u8) ->
});

lending_operations::request_elevation_group(
&crate::ID,
obligation,
&lending_market,
slot,
29 changes: 18 additions & 11 deletions programs/klend/src/handlers/handler_update_lending_market.rs
Original file line number Diff line number Diff line change
@@ -76,11 +76,8 @@ pub fn process(
msg!("New value is {:?}", value);
market.global_allowed_borrow_value = value;
}
UpdateLendingMarketMode::UpdateGlobalUnhealthyBorrow => {
let value = u64::from_le_bytes(value[..8].try_into().unwrap());
msg!("Prv value is {:?}", market.global_unhealthy_borrow_value);
msg!("New value is {:?}", value);
market.global_unhealthy_borrow_value = value;
UpdateLendingMarketMode::DeprecatedUpdateGlobalUnhealthyBorrow => {
panic!("Deprecated field")
}
UpdateLendingMarketMode::UpdateMinFullLiquidationThreshold => {
let value = u64::from_le_bytes(value[..8].try_into().unwrap());
@@ -221,17 +218,27 @@ pub fn process(
);
market.min_net_value_in_obligation_sf = min_net_value_in_obligation_sf;
}
UpdateLendingMarketMode::UpdateMinValueSkipPriorityLiqCheck => {
let min_value_skip_liquidation_ltv_bf_checks =
UpdateLendingMarketMode::UpdateMinValueLtvSkipPriorityLiqCheck => {
let min_value_skip_liquidation_ltv_checks =
u64::from_le_bytes(value[..8].try_into().unwrap());
msg!(
"Prev Value is {}",
market.min_value_skip_liquidation_ltv_checks
);
msg!("New Value is {}", min_value_skip_liquidation_ltv_checks);

market.min_value_skip_liquidation_ltv_checks = min_value_skip_liquidation_ltv_checks;
}
UpdateLendingMarketMode::UpdateMinValueBfSkipPriorityLiqCheck => {
let min_value_skip_liquidation_bf_checks =
u64::from_le_bytes(value[..8].try_into().unwrap());
msg!(
"Prev Value is {}",
market.min_value_skip_liquidation_ltv_bf_checks
market.min_value_skip_liquidation_bf_checks
);
msg!("New Value is {}", min_value_skip_liquidation_ltv_bf_checks);
msg!("New Value is {}", min_value_skip_liquidation_bf_checks);

market.min_value_skip_liquidation_ltv_bf_checks =
min_value_skip_liquidation_ltv_bf_checks;
market.min_value_skip_liquidation_bf_checks = min_value_skip_liquidation_bf_checks;
}
UpdateLendingMarketMode::UpdatePaddingFields => {
msg!("Prev Value is {:?}", market.reserved1);
3 changes: 2 additions & 1 deletion programs/klend/src/lending_market/lending_checks.rs
Original file line number Diff line number Diff line change
@@ -430,6 +430,7 @@ pub fn post_transfer_vault_balance_liquidity_reserve_checks(
}

pub fn validate_referrer_token_state(
program_id: &Pubkey,
referrer_token_state: &ReferrerTokenState,
referrer_token_state_key: Pubkey,
mint: Pubkey,
@@ -453,7 +454,7 @@ pub fn validate_referrer_token_state(
reserve_key.as_ref(),
&[referrer_token_state.bump.try_into().unwrap()],
],
&crate::ID,
program_id,
)
.unwrap();

40 changes: 33 additions & 7 deletions programs/klend/src/lending_market/lending_operations.rs
Original file line number Diff line number Diff line change
@@ -344,6 +344,14 @@ pub fn deposit_obligation_collateral(
return err!(LendingError::ReserveStale);
}

if obligation
.last_update
.is_stale(slot, PriceStatusFlags::NONE)?
{
msg!("Obligation is stale and must be refreshed in the current slot");
return err!(LendingError::ObligationStale);
}

if deposit_reserve.config.disable_usage_as_coll_outside_emode > 0
&& obligation.elevation_group == ELEVATION_GROUP_NONE
&& obligation.borrow_factor_adjusted_debt_value_sf > 0
@@ -616,6 +624,13 @@ where
msg!("Repay reserve is stale and must be refreshed in the current slot");
return err!(LendingError::ReserveStale);
}
if obligation
.last_update
.is_stale(clock.slot, PriceStatusFlags::NONE)?
{
msg!("Obligation is stale and must be refreshed in the current slot");
return err!(LendingError::ObligationStale);
}

let (liquidity, liquidity_index) =
obligation.find_liquidity_in_borrows_mut(repay_reserve_pk)?;
@@ -673,7 +688,9 @@ where
Ok(repay_amount)
}

#[allow(clippy::too_many_arguments)]
pub fn request_elevation_group<'info, T, U>(
program_id: &Pubkey,
obligation: &mut Obligation,
lending_market: &LendingMarket,
slot: Slot,
@@ -725,6 +742,7 @@ where
borrowed_amount_in_elevation_group,
..
} = refresh_obligation_borrows(
program_id,
obligation,
lending_market,
slot,
@@ -735,6 +753,7 @@ where

let RefreshObligationDepositsResult {
allowed_borrow_value_f: allowed_borrow_value,
borrowing_disabled,
..
} = refresh_obligation_deposits(
obligation,
@@ -762,6 +781,7 @@ where
);

obligation.elevation_group = new_elevation_group;
obligation.borrowing_disabled = borrowing_disabled.into();
obligation.last_update.mark_stale();

utils::check_elevation_group_borrow_limit_constraints(
@@ -950,7 +970,7 @@ where
let (coll_ltv_pct, coll_liquidation_threshold_pct) =
get_max_ltv_and_liquidation_threshold(&deposit_reserve, elevation_group)?;

if market_value_f >= lending_market.min_value_skip_liquidation_ltv_bf_checks
if market_value_f >= lending_market.min_value_skip_liquidation_ltv_checks
&& coll_liquidation_threshold_pct > 0
{
lowest_deposit_liquidation_ltv_threshold =
@@ -997,6 +1017,7 @@ where
}

pub fn refresh_obligation_borrows<'info, T, U>(
program_id: &Pubkey,
obligation: &mut Obligation,
lending_market: &LendingMarket,
slot: u64,
@@ -1076,6 +1097,7 @@ where
}

accumulate_referrer_fees(
program_id,
borrow_reserve_info_key,
borrow_reserve,
&obligation.referrer,
@@ -1095,7 +1117,7 @@ where

let borrow_factor_f = borrow_reserve.borrow_factor_f(elevation_group.is_some());

if market_value_f >= lending_market.min_value_skip_liquidation_ltv_bf_checks {
if market_value_f >= lending_market.min_value_skip_liquidation_bf_checks {
highest_borrow_factor_f = highest_borrow_factor_f.max(borrow_factor_f);
}

@@ -1140,6 +1162,7 @@ where
}

pub fn refresh_obligation<'info, T, U>(
program_id: &Pubkey,
obligation: &mut Obligation,
lending_market: &LendingMarket,
slot: Slot,
@@ -1160,6 +1183,7 @@ where
borrowed_amount_in_elevation_group,
highest_borrow_factor_pct,
} = refresh_obligation_borrows(
program_id,
obligation,
lending_market,
slot,
@@ -1197,11 +1221,7 @@ where
)
.to_bits();

obligation.unhealthy_borrow_value_sf = min(
unhealthy_borrow_value,
Fraction::from(lending_market.global_unhealthy_borrow_value),
)
.to_bits();
obligation.unhealthy_borrow_value_sf = unhealthy_borrow_value.to_bits();

obligation.lowest_reserve_deposit_liquidation_ltv =
lowest_deposit_liquidation_ltv_threshold.into();
@@ -1611,6 +1631,7 @@ pub fn add_referrer_fee(

#[allow(clippy::too_many_arguments)]
pub fn accumulate_referrer_fees<'info, T>(
program_id: &Pubkey,
borrow_reserve_info_key: Pubkey,
borrow_reserve: &mut Reserve,
obligation_referrer: &Pubkey,
@@ -1660,6 +1681,7 @@ where
.map_err(|_| error!(LendingError::InvalidAccountInput))?;

validate_referrer_token_state(
program_id,
referrer_token_state,
referrer_token_state_loader.get_pubkey(),
borrow_reserve.liquidity.mint_pubkey,
@@ -2398,6 +2420,10 @@ pub mod utils {
}
}

if !obligation.borrows_empty() {
check_non_elevation_group_borrowing_enabled(obligation)?;
}

require!(
deposits_iter.next().is_none(),
LendingError::InvalidAccountInput
7 changes: 2 additions & 5 deletions programs/klend/src/lib.rs
Original file line number Diff line number Diff line change
@@ -230,11 +230,8 @@ pub mod kamino_lending {
handler_request_elevation_group::process(ctx, elevation_group)
}

pub fn init_referrer_token_state(
ctx: Context<InitReferrerTokenState>,
referrer: Pubkey,
) -> Result<()> {
handler_init_referrer_token_state::process(ctx, referrer)
pub fn init_referrer_token_state(ctx: Context<InitReferrerTokenState>) -> Result<()> {
handler_init_referrer_token_state::process(ctx)
}

pub fn init_user_metadata(
29 changes: 18 additions & 11 deletions programs/klend/src/state/lending_market.rs
Original file line number Diff line number Diff line change
@@ -10,9 +10,8 @@ use super::{serde_bool_u8, serde_string, serde_utf_string};
use crate::{
utils::{
CLOSE_TO_INSOLVENCY_RISKY_LTV, ELEVATION_GROUP_NONE, GLOBAL_ALLOWED_BORROW_VALUE,
GLOBAL_UNHEALTHY_BORROW_VALUE, LENDING_MARKET_SIZE, LIQUIDATION_CLOSE_FACTOR,
LIQUIDATION_CLOSE_VALUE, MAX_LIQUIDATABLE_VALUE_AT_ONCE, MIN_NET_VALUE_IN_OBLIGATION,
PROGRAM_VERSION,
LENDING_MARKET_SIZE, LIQUIDATION_CLOSE_FACTOR, LIQUIDATION_CLOSE_VALUE,
MAX_LIQUIDATABLE_VALUE_AT_ONCE, MIN_NET_VALUE_IN_OBLIGATION, PROGRAM_VERSION,
},
LendingError,
};
@@ -53,7 +52,12 @@ pub struct LendingMarket {
pub min_full_liquidation_value_threshold: u64,

pub max_liquidatable_debt_market_value_at_once: u64,
pub global_unhealthy_borrow_value: u64,
#[cfg_attr(
feature = "serde",
serde(skip_deserializing, skip_serializing, default)
)]
#[derivative(Debug = "ignore")]
pub reserved0: [u8; 8],
pub global_allowed_borrow_value: u64,
#[cfg_attr(feature = "serde", serde(with = "serde_string", default))]
pub risk_council: Pubkey,
@@ -81,22 +85,24 @@ pub struct LendingMarket {
)]
pub min_net_value_in_obligation_sf: u128,

pub min_value_skip_liquidation_ltv_bf_checks: u64,
pub min_value_skip_liquidation_ltv_checks: u64,

#[cfg_attr(feature = "serde", serde(with = "serde_utf_string", default))]
pub name: [u8; 32],

pub min_value_skip_liquidation_bf_checks: u64,

#[cfg_attr(
feature = "serde",
serde(skip_deserializing, skip_serializing, default = "default_padding_173")
)]
#[derivative(Debug = "ignore")]
pub padding1: [u64; 173],
pub padding1: [u64; 172],
}

#[cfg(feature = "serde")]
fn default_padding_173() -> [u64; 173] {
[0; 173]
fn default_padding_173() -> [u64; 172] {
[0; 172]
}

#[cfg(feature = "serde")]
@@ -120,17 +126,18 @@ impl Default for LendingMarket {
insolvency_risk_unhealthy_ltv_pct: CLOSE_TO_INSOLVENCY_RISKY_LTV,
max_liquidatable_debt_market_value_at_once: MAX_LIQUIDATABLE_VALUE_AT_ONCE,
global_allowed_borrow_value: GLOBAL_ALLOWED_BORROW_VALUE,
global_unhealthy_borrow_value: GLOBAL_UNHEALTHY_BORROW_VALUE,
min_full_liquidation_value_threshold: LIQUIDATION_CLOSE_VALUE,
reserved0: [0; 8],
reserved1: [0; 8],
referral_fee_bps: 0,
price_refresh_trigger_to_max_age_pct: 0,
elevation_groups: [ElevationGroup::default(); 32],
min_value_skip_liquidation_ltv_bf_checks: 0,
min_value_skip_liquidation_ltv_checks: 0,
min_value_skip_liquidation_bf_checks: 0,
elevation_group_padding: [0; 90],
min_net_value_in_obligation_sf: MIN_NET_VALUE_IN_OBLIGATION.to_bits(),
name: [0; 32],
padding1: [0; 173],
padding1: [0; 172],
}
}
}
9 changes: 5 additions & 4 deletions programs/klend/src/state/mod.rs
Original file line number Diff line number Diff line change
@@ -200,7 +200,7 @@ pub enum UpdateLendingMarketMode {
UpdateEmergencyMode = 1,
UpdateLiquidationCloseFactor = 2,
UpdateLiquidationMaxValue = 3,
UpdateGlobalUnhealthyBorrow = 4,
DeprecatedUpdateGlobalUnhealthyBorrow = 4,
UpdateGlobalAllowedBorrow = 5,
UpdateRiskCouncil = 6,
UpdateMinFullLiquidationThreshold = 7,
@@ -212,9 +212,10 @@ pub enum UpdateLendingMarketMode {
UpdateAutodeleverageEnabled = 13,
UpdateBorrowingDisabled = 14,
UpdateMinNetValueObligationPostAction = 15,
UpdateMinValueSkipPriorityLiqCheck = 16,
UpdatePaddingFields = 17,
UpdateName = 18,
UpdateMinValueLtvSkipPriorityLiqCheck = 16,
UpdateMinValueBfSkipPriorityLiqCheck = 17,
UpdatePaddingFields = 18,
UpdateName = 19,
}

#[cfg(feature = "serde")]
2 changes: 0 additions & 2 deletions programs/klend/src/utils/consts.rs
Original file line number Diff line number Diff line change
@@ -46,8 +46,6 @@ pub const REFERRER_STATE_SIZE: usize = 64;
pub const SHORT_URL_SIZE: usize = 68;
pub const TOKEN_INFO_SIZE: usize = 384;

pub const GLOBAL_UNHEALTHY_BORROW_VALUE: u64 = 50_000_000;

pub const GLOBAL_ALLOWED_BORROW_VALUE: u64 = 45_000_000;

pub const DEFAULT_BORROW_FACTOR_PCT: u64 = 100;

0 comments on commit c76cc96

Please sign in to comment.