Skip to content

Commit c3b159d

Browse files
authored
Skip rate limitter if no borrows (#211)
* We want to support withdraws for users that only have borrows, no deposits, but are deposited in a reserve with bad oracles. In such case, we skip liveness checks. However, while calculating max outflow the math depended on a value that was set upon refresh. That caused the max outflow to be zero and blocked withdrawals. * Fixing outdated CI * Fixing the calculation so that it still works as intended for other tests * Remove forgotten msg * Reverting to previous logic but with a better static value * Reverting to previous logic but with a better static value
1 parent c6195f1 commit c3b159d

13 files changed

+104
-21
lines changed

.github/workflows/pull-request-token-lending.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ name: Token Lending Pull Request
33
on:
44
pull_request:
55
paths:
6-
- 'token-lending/**'
7-
- 'token/**'
6+
- "token-lending/**"
7+
- "token/**"
88
push:
99
branches: [master]
1010
paths:
11-
- 'token-lending/**'
12-
- 'token/**'
11+
- "token-lending/**"
12+
- "token/**"
1313

1414
jobs:
1515
cargo-test-bpf:

.github/workflows/pull-request.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ name: Pull Request
33
on:
44
pull_request:
55
paths-ignore:
6-
- 'docs/**'
6+
- "docs/**"
77
push:
88
branches: [master, upcoming]
99
paths-ignore:
10-
- 'docs/**'
10+
- "docs/**"
1111

1212
jobs:
1313
all_github_action_checks:

token-lending/program/src/processor.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,13 +1540,15 @@ fn _withdraw_obligation_collateral<'a>(
15401540
.clone() // remaining_outflow is a mutable call, but we don't have mutable access here
15411541
.remaining_outflow(clock.slot)?;
15421542

1543-
let max_lending_market_outflow_liquidity_amount = withdraw_reserve
1544-
.usd_to_liquidity_amount_lower_bound(min(
1545-
max_outflow_usd,
1546-
// min here bc this function can overflow if max_outflow_usd is u64::MAX
1547-
// the actual value doesn't matter too much as long as its sensible
1548-
obligation.deposited_value.try_mul(2)?,
1549-
))?;
1543+
// min here bc this function can overflow if max_outflow_usd is u64::MAX
1544+
// the actual value doesn't matter too much as long as its sensible
1545+
let max_outflow_usd_capped = min(
1546+
max_outflow_usd,
1547+
Decimal::from(100_000_000_000u64), // enough USD to cover all requests
1548+
);
1549+
1550+
let max_lending_market_outflow_liquidity_amount =
1551+
withdraw_reserve.usd_to_liquidity_amount_lower_bound(max_outflow_usd_capped)?;
15501552

15511553
let max_reserve_outflow_liquidity_amount = withdraw_reserve
15521554
.rate_limiter

token-lending/program/tests/attributed_borrows.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ async fn test_refresh_obligation() {
9292
(usdc_mint::id(), 10 * FRACTIONAL_TO_USDC),
9393
(wsol_mint::id(), LAMPORTS_PER_SOL),
9494
],
95+
..Default::default()
9596
},
9697
ObligationArgs {
9798
deposits: vec![
@@ -102,6 +103,7 @@ async fn test_refresh_obligation() {
102103
(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC),
103104
(wsol_mint::id(), 2 * LAMPORTS_PER_SOL),
104105
],
106+
..Default::default()
105107
},
106108
],
107109
)
@@ -230,6 +232,7 @@ async fn test_calculations() {
230232
(usdc_mint::id(), 10 * FRACTIONAL_TO_USDC),
231233
(wsol_mint::id(), LAMPORTS_PER_SOL),
232234
],
235+
..Default::default()
233236
},
234237
ObligationArgs {
235238
deposits: vec![
@@ -240,6 +243,7 @@ async fn test_calculations() {
240243
(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC),
241244
(wsol_mint::id(), 2 * LAMPORTS_PER_SOL),
242245
],
246+
..Default::default()
243247
},
244248
],
245249
)
@@ -599,6 +603,7 @@ async fn test_withdraw() {
599603
(wsol_mint::id(), 2 * LAMPORTS_PER_SOL),
600604
],
601605
borrows: vec![(usdc_mint::id(), 10 * FRACTIONAL_TO_USDC)],
606+
..Default::default()
602607
}],
603608
)
604609
.await;
@@ -796,6 +801,7 @@ async fn test_liquidate() {
796801
&[ObligationArgs {
797802
deposits: vec![(usdc_mint::id(), FRACTIONAL_TO_USDC / 2)],
798803
borrows: vec![(wsol_mint::id(), LAMPORTS_PER_SOL / 40)],
804+
..Default::default()
799805
}],
800806
)
801807
.await;

token-lending/program/tests/borrow_obligation_liquidity.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ async fn test_borrow_max_rate_limiter() {
534534
&[ObligationArgs {
535535
deposits: vec![(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC)],
536536
borrows: vec![],
537+
..Default::default()
537538
}],
538539
)
539540
.await;

token-lending/program/tests/forgive_debt.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,12 @@ async fn test_forgive_debt_success_easy() {
7878
ObligationArgs {
7979
deposits: vec![(usdc_mint::id(), 20 * FRACTIONAL_TO_USDC)],
8080
borrows: vec![(wsol_mint::id(), LAMPORTS_PER_SOL)],
81+
..Default::default()
8182
},
8283
ObligationArgs {
8384
deposits: vec![(wsol_mint::id(), LAMPORTS_PER_SOL)],
8485
borrows: vec![],
86+
..Default::default()
8587
},
8688
],
8789
)
@@ -272,6 +274,7 @@ async fn test_forgive_debt_fail_invalid_signer() {
272274
&[ObligationArgs {
273275
deposits: vec![(usdc_mint::id(), 200 * FRACTIONAL_TO_USDC)],
274276
borrows: vec![(wsol_mint::id(), 10 * LAMPORTS_PER_SOL)],
277+
..Default::default()
275278
}],
276279
)
277280
.await;
@@ -373,6 +376,7 @@ async fn test_forgive_debt_fail_no_signer() {
373376
&[ObligationArgs {
374377
deposits: vec![(usdc_mint::id(), 200 * FRACTIONAL_TO_USDC)],
375378
borrows: vec![(wsol_mint::id(), 10 * LAMPORTS_PER_SOL)],
379+
..Default::default()
376380
}],
377381
)
378382
.await;

token-lending/program/tests/helpers/solend_program_test.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,17 @@ pub struct ReserveArgs {
18751875
pub struct ObligationArgs {
18761876
pub deposits: Vec<(Pubkey, u64)>,
18771877
pub borrows: Vec<(Pubkey, u64)>,
1878+
pub should_refresh: bool,
1879+
}
1880+
1881+
impl Default for ObligationArgs {
1882+
fn default() -> Self {
1883+
ObligationArgs {
1884+
deposits: vec![],
1885+
borrows: vec![],
1886+
should_refresh: true,
1887+
}
1888+
}
18781889
}
18791890

18801891
pub async fn custom_scenario(
@@ -1987,17 +1998,19 @@ pub async fn custom_scenario(
19871998
}
19881999
}
19892000

1990-
for (i, obligation_arg) in obligation_args.iter().enumerate() {
2001+
for ((obligation, obligation_owner), obligation_arg) in obligations
2002+
.iter_mut()
2003+
.zip(obligation_owners.iter_mut())
2004+
.zip(obligation_args.iter())
2005+
{
19912006
for (mint, amount) in obligation_arg.borrows.iter() {
19922007
let reserve = reserves
19932008
.iter()
19942009
.find(|reserve| reserve.account.liquidity.mint_pubkey == *mint)
19952010
.unwrap();
19962011

1997-
obligation_owners[i]
1998-
.create_token_account(mint, &mut test)
1999-
.await;
2000-
obligation_owners[i]
2012+
obligation_owner.create_token_account(mint, &mut test).await;
2013+
obligation_owner
20012014
.create_token_account(&reserve.account.collateral.mint_pubkey, &mut test)
20022015
.await;
20032016

@@ -2007,8 +2020,8 @@ pub async fn custom_scenario(
20072020
.borrow_obligation_liquidity(
20082021
&mut test,
20092022
reserve,
2010-
&obligations[i],
2011-
&obligation_owners[i],
2023+
obligation,
2024+
obligation_owner,
20122025
fee_receiver.get_account(mint),
20132026
*amount,
20142027
)
@@ -2017,7 +2030,11 @@ pub async fn custom_scenario(
20172030
}
20182031
}
20192032

2020-
for obligation in obligations.iter_mut() {
2033+
for obligation in obligations
2034+
.iter_mut()
2035+
.zip(obligation_args.iter())
2036+
.filter_map(|(obligation, arg)| arg.should_refresh.then_some(obligation))
2037+
{
20212038
lending_market
20222039
.refresh_obligation(&mut test, obligation)
20232040
.await

token-lending/program/tests/isolated_tier_assets.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ async fn test_refresh_obligation() {
6767
&[ObligationArgs {
6868
deposits: vec![(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC)],
6969
borrows: vec![],
70+
..Default::default()
7071
}],
7172
)
7273
.await;
@@ -173,6 +174,7 @@ async fn borrow_isolated_asset() {
173174
&[ObligationArgs {
174175
deposits: vec![(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC)],
175176
borrows: vec![],
177+
..Default::default()
176178
}],
177179
)
178180
.await;
@@ -269,6 +271,7 @@ async fn borrow_isolated_asset_invalid() {
269271
&[ObligationArgs {
270272
deposits: vec![(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC)],
271273
borrows: vec![(wsol_mint::id(), 1)],
274+
..Default::default()
272275
}],
273276
)
274277
.await;
@@ -354,6 +357,7 @@ async fn borrow_regular_asset_invalid() {
354357
&[ObligationArgs {
355358
deposits: vec![(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC)],
356359
borrows: vec![(bonk_mint::id(), 1)],
360+
..Default::default()
357361
}],
358362
)
359363
.await;
@@ -449,6 +453,7 @@ async fn invalid_borrow_due_to_reserve_config_change() {
449453
&[ObligationArgs {
450454
deposits: vec![(usdc_mint::id(), 100 * FRACTIONAL_TO_USDC)],
451455
borrows: vec![(bonk_mint::id(), 1), (wsol_mint::id(), LAMPORTS_PER_SOL)],
456+
..Default::default()
452457
}],
453458
)
454459
.await;

token-lending/program/tests/liquidate_obligation_and_redeem_collateral.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ async fn test_liquidity_ordering() {
576576
(wsol_mint::id(), LAMPORTS_PER_SOL),
577577
(usdc_mint::id(), FRACTIONAL_TO_USDC),
578578
],
579+
..Default::default()
579580
}],
580581
)
581582
.await;
@@ -705,6 +706,7 @@ async fn test_liquidate_closeable_obligation() {
705706
&[ObligationArgs {
706707
deposits: vec![(usdc_mint::id(), 20 * FRACTIONAL_TO_USDC)],
707708
borrows: vec![(wsol_mint::id(), LAMPORTS_PER_SOL)],
709+
..Default::default()
708710
}],
709711
)
710712
.await;

token-lending/program/tests/mark_obligation_as_closeable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ async fn test_mark_obligation_as_closeable_success() {
6161
&[ObligationArgs {
6262
deposits: vec![(usdc_mint::id(), 20 * FRACTIONAL_TO_USDC)],
6363
borrows: vec![(wsol_mint::id(), LAMPORTS_PER_SOL)],
64+
..Default::default()
6465
}],
6566
)
6667
.await;
@@ -176,6 +177,7 @@ async fn invalid_signer() {
176177
&[ObligationArgs {
177178
deposits: vec![(usdc_mint::id(), 20 * FRACTIONAL_TO_USDC)],
178179
borrows: vec![(wsol_mint::id(), LAMPORTS_PER_SOL)],
180+
..Default::default()
179181
}],
180182
)
181183
.await;

0 commit comments

Comments
 (0)