Skip to content

Commit bdcdbc1

Browse files
committed
Add instruction to update the LTV of a reserve
1 parent b7f7207 commit bdcdbc1

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

token-lending/program/src/instruction.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,22 @@ pub enum LendingInstruction {
362362
/// liquidity_amount is the amount of collateral tokens to withdraw
363363
collateral_amount: u64,
364364
},
365+
366+
// 16
367+
/// Updates a reserve config parameter
368+
///
369+
/// Accounts expected by this instruction:
370+
///
371+
/// 1. `[writable]` Reserve account - refreshed
372+
/// 2 `[]` Lending market account.
373+
/// 3 `[]` Derived lending market authority.
374+
/// 4 `[signer]` Lending market owner.
375+
UpdateReserveConfig {
376+
/// Specifies which config to change
377+
config_enum: u8,
378+
/// New value for the config
379+
new_value: u8,
380+
},
365381
}
366382

367383
impl LendingInstruction {
@@ -456,6 +472,14 @@ impl LendingInstruction {
456472
let (collateral_amount, _rest) = Self::unpack_u64(rest)?;
457473
Self::WithdrawObligationCollateralAndRedeemReserveCollateral { collateral_amount }
458474
}
475+
16 => {
476+
let (config_enum, _rest) = Self::unpack_u8(rest)?;
477+
let (new_value, _rest) = Self::unpack_u8(_rest)?;
478+
Self::UpdateReserveConfig {
479+
config_enum,
480+
new_value,
481+
}
482+
}
459483
_ => {
460484
msg!("Instruction cannot be unpacked");
461485
return Err(LendingError::InstructionUnpackError.into());
@@ -612,6 +636,14 @@ impl LendingInstruction {
612636
buf.push(15);
613637
buf.extend_from_slice(&collateral_amount.to_le_bytes());
614638
}
639+
Self::UpdateReserveConfig {
640+
config_enum,
641+
new_value,
642+
} => {
643+
buf.push(16);
644+
buf.extend_from_slice(&config_enum.to_le_bytes());
645+
buf.extend_from_slice(&new_value.to_le_bytes());
646+
}
615647
}
616648
buf
617649
}

token-lending/program/src/processor.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
CalculateBorrowResult, CalculateLiquidationResult, CalculateRepayResult,
1010
InitLendingMarketParams, InitObligationParams, InitReserveParams, LendingMarket,
1111
NewReserveCollateralParams, NewReserveLiquidityParams, Obligation, Reserve,
12-
ReserveCollateral, ReserveConfig, ReserveLiquidity,
12+
ReserveCollateral, ReserveConfig, ReserveConfigKey, ReserveLiquidity,
1313
},
1414
};
1515
use num_traits::FromPrimitive;
@@ -114,13 +114,25 @@ pub fn process_instruction(
114114
LendingInstruction::WithdrawObligationCollateralAndRedeemReserveCollateral {
115115
collateral_amount,
116116
} => {
117-
msg!("Instruction: Withdraw Obligation Collateral and Redeem Reserve Collateral ");
117+
msg!("Instruction: Withdraw Obligation Collateral and Redeem Reserve Collateral");
118118
process_withdraw_obligation_collateral_and_redeem_reserve_liquidity(
119119
program_id,
120120
collateral_amount,
121121
accounts,
122122
)
123123
}
124+
LendingInstruction::UpdateReserveConfig {
125+
config_enum,
126+
new_value,
127+
} => {
128+
msg!("Instruction: UpdateReserveConfig");
129+
process_update_reserve_config(
130+
program_id,
131+
ReserveConfigKey::from_u8(config_enum)?,
132+
new_value,
133+
accounts,
134+
)
135+
}
124136
}
125137
}
126138

@@ -1994,6 +2006,68 @@ fn process_withdraw_obligation_collateral_and_redeem_reserve_liquidity(
19942006
)
19952007
}
19962008

2009+
#[inline(never)] // avoid stack frame limit
2010+
fn process_update_reserve_config(
2011+
program_id: &Pubkey,
2012+
config_enum: ReserveConfigKey,
2013+
new_value: u8,
2014+
accounts: &[AccountInfo],
2015+
) -> ProgramResult {
2016+
let account_info_iter = &mut accounts.iter().peekable();
2017+
let reserve_info = next_account_info(account_info_iter)?;
2018+
let lending_market_info = next_account_info(account_info_iter)?;
2019+
let lending_market_authority_info = next_account_info(account_info_iter)?;
2020+
let lending_market_owner_info = next_account_info(account_info_iter)?;
2021+
2022+
let mut reserve = assert_uninitialized::<Reserve>(reserve_info)?;
2023+
if reserve_info.owner != program_id {
2024+
msg!(
2025+
"Reserve provided is not owned by the lending program {} != {}",
2026+
&reserve_info.owner.to_string(),
2027+
&program_id.to_string(),
2028+
);
2029+
return Err(LendingError::InvalidAccountOwner.into());
2030+
}
2031+
2032+
let lending_market = LendingMarket::unpack(&lending_market_info.data.borrow())?;
2033+
if lending_market_info.owner != program_id {
2034+
msg!(
2035+
"Lending market provided is not owned by the lending program {} != {}",
2036+
&lending_market_info.owner.to_string(),
2037+
&program_id.to_string(),
2038+
);
2039+
return Err(LendingError::InvalidAccountOwner.into());
2040+
}
2041+
if &lending_market.owner != lending_market_owner_info.key {
2042+
msg!("Lending market owner does not match the lending market owner provided");
2043+
return Err(LendingError::InvalidMarketOwner.into());
2044+
}
2045+
if !lending_market_owner_info.is_signer {
2046+
msg!("Lending market owner provided must be a signer");
2047+
return Err(LendingError::InvalidSigner.into());
2048+
}
2049+
2050+
let authority_signer_seeds = &[
2051+
lending_market_info.key.as_ref(),
2052+
&[lending_market.bump_seed],
2053+
];
2054+
let lending_market_authority_pubkey =
2055+
Pubkey::create_program_address(authority_signer_seeds, program_id)?;
2056+
if &lending_market_authority_pubkey != lending_market_authority_info.key {
2057+
msg!(
2058+
"Derived lending market authority does not match the lending market authority provided"
2059+
);
2060+
return Err(LendingError::InvalidMarketAuthority.into());
2061+
}
2062+
match config_enum {
2063+
ReserveConfigKey::LoanToValueRatio => {
2064+
reserve.config.loan_to_value_ratio = new_value;
2065+
}
2066+
};
2067+
Reserve::pack(reserve, &mut reserve_info.data.borrow_mut())?;
2068+
Ok(())
2069+
}
2070+
19972071
fn assert_rent_exempt(rent: &Rent, account_info: &AccountInfo) -> ProgramResult {
19982072
if !rent.is_exempt(account_info.lamports(), account_info.data_len()) {
19992073
msg!(

token-lending/program/src/state/reserve.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,23 @@ pub struct ReserveConfig {
613613
pub fees: ReserveFees,
614614
}
615615

616+
/// ReserveConfig configurable values
617+
#[repr(u8)]
618+
pub enum ReserveConfigKey {
619+
/// Enum to specify LoanToValueRatio
620+
LoanToValueRatio = 0,
621+
}
622+
623+
impl ReserveConfigKey {
624+
/// returns the ReserveConfigKey corresponding to the integer
625+
pub fn from_u8(value: u8) -> Result<ReserveConfigKey, ProgramError> {
626+
match value {
627+
0 => Ok(ReserveConfigKey::LoanToValueRatio),
628+
_ => Err(LendingError::InvalidConfig.into()),
629+
}
630+
}
631+
}
632+
616633
/// Additional fee information on a reserve
617634
///
618635
/// These exist separately from interest accrual fees, and are specifically for the program owner

0 commit comments

Comments
 (0)