Skip to content
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

Added deposit cap and borrow cap. #118

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
29 changes: 29 additions & 0 deletions token-lending/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ fn main() {
"borrow_fee_wad",
"flash_loan_fee_wad",
"host_fee_percentage",
"deposit_limit",
"borrow_limit",
]
.into_iter()
.map(build_u64_arg)
Expand Down Expand Up @@ -514,6 +516,26 @@ fn main() {
.default_value("20")
.help("Amount of fee going to host account: [0, 100]"),
)
.arg(
Arg::with_name("deposit_limit")
.long("deposit-limit")
.validator(is_parsable::<u64>)
.value_name("AMOUNT")
.takes_value(true)
.required(true)
.default_value("18446744073709551615")
.help("Maximum deposit limit in terms of lamports"),
)
.arg(
Arg::with_name("borrow_limit")
.long("borrow-limit")
.validator(is_parsable::<u64>)
.value_name("AMOUNT")
.takes_value(true)
.required(true)
.default_value("18446744073709551615")
.help("Maximum borrow limit in terms of lamports"),
)
)
.get_matches();

Expand Down Expand Up @@ -580,7 +602,10 @@ fn main() {
let borrow_fee_wad = value_of(arg_matches, "borrow_fee_wad");
let flash_loan_fee_wad = value_of(arg_matches, "flash_loan_fee_wad");
let host_fee_percentage = value_of(arg_matches, "host_fee_percentage");
let deposit_limit = value_of(arg_matches, "deposit_limit");
let borrow_limit = value_of(arg_matches, "borrow_limit");
let deposit_staking_pool = pubkey_or_none_of(arg_matches, "deposit_staking_pool");

let mut old_config =
Reserve::unpack(&config.rpc_client.get_account(&reserve).unwrap().data)
.unwrap()
Expand All @@ -604,6 +629,8 @@ fn main() {
host_fee_percentage.unwrap_or(old_config.fees.host_fee_percentage);
old_config.fees.flash_loan_fee_wad =
flash_loan_fee_wad.unwrap_or(old_config.fees.flash_loan_fee_wad);
old_config.deposit_limit = deposit_limit.unwrap_or(old_config.deposit_limit);
old_config.borrow_limit = borrow_limit.unwrap_or(old_config.borrow_limit);
old_config.deposit_staking_pool =
deposit_staking_pool.unwrap_or(old_config.deposit_staking_pool);
command_update_reserve(
Expand Down Expand Up @@ -681,6 +708,8 @@ fn main() {
host_fee_percentage,
},
deposit_staking_pool: COption::None,
deposit_limit: u64::MAX,
borrow_limit: u64::MAX,
},
source_liquidity_pubkey,
source_liquidity_owner_keypair,
Expand Down
8 changes: 8 additions & 0 deletions token-lending/program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,8 @@ impl LendingInstruction {
let (flash_loan_fee_wad, rest) = Self::unpack_u64(rest)?;
let (host_fee_percentage, rest) = Self::unpack_u8(rest)?;
let (deposit_staking_pool, rest) = Self::unpack_coption_key_compact(rest)?;
let (deposit_limit, rest) = Self::unpack_u64(rest)?;
let (borrow_limit, rest) = Self::unpack_u64(rest)?;
Ok((
ReserveConfig {
optimal_utilization_rate,
Expand All @@ -573,6 +575,8 @@ impl LendingInstruction {
host_fee_percentage,
},
deposit_staking_pool,
deposit_limit,
borrow_limit,
},
rest,
))
Expand Down Expand Up @@ -699,6 +703,8 @@ impl LendingInstruction {
host_fee_percentage,
},
deposit_staking_pool,
deposit_limit,
borrow_limit,
} = reserve_config;
buf.extend_from_slice(&optimal_utilization_rate.to_le_bytes());
buf.extend_from_slice(&loan_to_value_ratio.to_le_bytes());
Expand All @@ -713,6 +719,8 @@ impl LendingInstruction {
let mut coption_key_buf = [0u8; 33];
pack_coption_key_compact(&deposit_staking_pool, &mut coption_key_buf);
buf.extend_from_slice(&coption_key_buf);
buf.extend_from_slice(&deposit_limit.to_le_bytes());
buf.extend_from_slice(&borrow_limit.to_le_bytes());
}
}

Expand Down
18 changes: 18 additions & 0 deletions token-lending/program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,15 @@ fn _deposit_reserve_liquidity<'a>(
return Err(LendingError::InvalidMarketAuthority.into());
}

if Decimal::from(liquidity_amount)
.try_add(reserve.liquidity.total_supply()?)?
.try_floor_u64()?
> reserve.config.deposit_limit
{
msg!("Cannot deposit liquidity above the reserve deposit limit");
return Err(LendingError::InvalidAmount.into());
}

let collateral_amount = reserve.deposit_liquidity(liquidity_amount)?;
reserve.last_update.mark_stale();
Reserve::pack(reserve, &mut reserve_info.data.borrow_mut())?;
Expand Down Expand Up @@ -1496,6 +1505,15 @@ fn process_borrow_obligation_liquidity(
msg!("Borrow reserve is stale and must be refreshed in the current slot");
return Err(LendingError::ReserveStale.into());
}
if liquidity_amount != u64::MAX
&& Decimal::from(liquidity_amount)
.try_add(borrow_reserve.liquidity.borrowed_amount_wads)?
.try_floor_u64()?
> borrow_reserve.config.borrow_limit
{
msg!("Cannot borrow above the borrow limit");
return Err(LendingError::InvalidAmount.into());
}

let mut obligation = Obligation::unpack(&obligation_info.data.borrow())?;
if obligation_info.owner != program_id {
Expand Down
20 changes: 18 additions & 2 deletions token-lending/program/src/state/reserve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,10 @@ pub struct ReserveConfig {
pub fees: ReserveFees,
/// corresponded staking pool pubkey of deposit
pub deposit_staking_pool: COption<Pubkey>,
/// Maximum deposit limit of liquidity in native units, u64::MAX for inf
pub deposit_limit: u64,
/// Maximum borrow limit of liquidity in native units, u64::MAX for inf
pub borrow_limit: u64,
}

/// Additional fee information on a reserve
Expand Down Expand Up @@ -765,6 +769,8 @@ impl Pack for Reserve {
config_fees_flash_loan_fee_wad,
config_fees_host_fee_percentage,
config_deposit_staking_pool,
config_deposit_limit,
config_borrow_limit,
_padding,
) = mut_array_refs![
output,
Expand Down Expand Up @@ -795,7 +801,9 @@ impl Pack for Reserve {
8,
1,
33,
215
8,
8,
199
];

// reserve
Expand Down Expand Up @@ -841,6 +849,8 @@ impl Pack for Reserve {
&self.config.deposit_staking_pool,
config_deposit_staking_pool,
);
*config_deposit_limit = self.config.deposit_limit.to_le_bytes();
*config_borrow_limit = self.config.borrow_limit.to_le_bytes();
}

/// Unpacks a byte buffer into a [ReserveInfo](struct.ReserveInfo.html).
Expand Down Expand Up @@ -875,6 +885,8 @@ impl Pack for Reserve {
config_fees_flash_loan_fee_wad,
config_fees_host_fee_percentage,
config_deposit_staking_pool,
config_deposit_limit,
config_borrow_limit,
_padding,
) = array_refs![
input,
Expand Down Expand Up @@ -905,7 +917,9 @@ impl Pack for Reserve {
8,
1,
33,
215
8,
8,
199
];

let version = u8::from_le_bytes(*version);
Expand Down Expand Up @@ -951,6 +965,8 @@ impl Pack for Reserve {
host_fee_percentage: u8::from_le_bytes(*config_fees_host_fee_percentage),
},
deposit_staking_pool: unpack_coption_key_compact(config_deposit_staking_pool)?,
deposit_limit: u64::from_le_bytes(*config_deposit_limit),
borrow_limit: u64::from_le_bytes(*config_borrow_limit),
},
})
}
Expand Down
2 changes: 2 additions & 0 deletions token-lending/program/tests/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ pub const TEST_RESERVE_CONFIG: ReserveConfig = ReserveConfig {
host_fee_percentage: 20,
},
deposit_staking_pool: COption::None,
deposit_limit: u64::MAX,
borrow_limit: u64::MAX,
};

pub const SOL_PYTH_PRODUCT: &str = "3Mnn2fX6rQyUsyELYms1sBJyChWofzSNRoqYzvgMVz5E";
Expand Down
4 changes: 4 additions & 0 deletions token-lending/program/tests/max_withdraw_bug_poc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ async fn test_success() {
host_fee_percentage: 20,
},
deposit_staking_pool: COption::None,
deposit_limit: u64::MAX,
borrow_limit: u64::MAX,
};

// oracle price doesn't matter so using usdc oracle for ease of computation
Expand Down Expand Up @@ -106,6 +108,8 @@ async fn test_success() {
host_fee_percentage: 20,
},
deposit_staking_pool: COption::None,
deposit_limit: u64::MAX,
borrow_limit: u64::MAX,
};
let usdc_mint = add_usdc_mint(&mut test);
let usdc_oracle = add_usdc_pyth_oracle(&mut test);
Expand Down
2 changes: 2 additions & 0 deletions token-lending/program/tests/update_reserve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ async fn test_update_reserve() {
host_fee_percentage: 15,
},
deposit_staking_pool: COption::None,
deposit_limit: u64::MAX,
borrow_limit: u64::MAX,
};
let before_test_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
assert_ne!(before_test_reserve.config, new_config);
Expand Down