From ab6c827aca7b26b305640cf05be4e94b84bb215d Mon Sep 17 00:00:00 2001
From: 0xxgen1 <0xxgen@solend.fi>
Date: Fri, 8 Nov 2024 17:26:25 +0000
Subject: [PATCH] (wip) - Deposit - Withdraw - Repay - Liquidate
---
contracts/suilend/sources/lending_market.move | 4 +-
contracts/suilend/sources/obligation.move | 127 +-
contracts/suilend/tests/obligation_tests.move | 1259 ++++++++++++++---
3 files changed, 1211 insertions(+), 179 deletions(-)
diff --git a/contracts/suilend/sources/lending_market.move b/contracts/suilend/sources/lending_market.move
index 10adaf8..bb74fe2 100644
--- a/contracts/suilend/sources/lending_market.move
+++ b/contracts/suilend/sources/lending_market.move
@@ -356,7 +356,9 @@ module suilend::lending_market {
let (receive_balance, borrow_amount_with_fees) = reserve::borrow_liquidity
(reserve, amount);
let origination_fee_amount = borrow_amount_with_fees - balance::value(&receive_balance);
- obligation::borrow
(obligation, reserve, clock, borrow_amount_with_fees);
+ obligation::borrow
(obligation, &mut lending_market.reserves, reserve_array_index, clock, borrow_amount_with_fees);
+
+ let reserve = vector::borrow_mut(&mut lending_market.reserves, reserve_array_index);
let borrow_value = reserve::market_value_upper_bound(reserve, decimal::from(borrow_amount_with_fees));
rate_limiter::process_qty(
diff --git a/contracts/suilend/sources/obligation.move b/contracts/suilend/sources/obligation.move
index 758fcd6..2dba176 100644
--- a/contracts/suilend/sources/obligation.move
+++ b/contracts/suilend/sources/obligation.move
@@ -399,6 +399,13 @@ module suilend::obligation {
let borrow_index = find_borrow_index(obligation, reserve);
assert!(borrow_index == vector::length(&obligation.borrows), ECannotDepositAndBorrowSameAsset);
+ let is_emode = is_emode(obligation);
+ let (open_ltv, close_ltv, _) = get_ltvs(
+ obligation,
+ reserve,
+ is_emode,
+ );
+
let deposit = vector::borrow_mut(&mut obligation.deposits, deposit_index);
deposit.deposited_ctoken_amount = deposit.deposited_ctoken_amount + ctoken_amount;
@@ -414,14 +421,14 @@ module suilend::obligation {
obligation.allowed_borrow_value_usd,
mul(
reserve::ctoken_market_value_lower_bound(reserve, ctoken_amount),
- open_ltv(config(reserve))
+ open_ltv,
)
);
obligation.unhealthy_borrow_value_usd = add(
obligation.unhealthy_borrow_value_usd,
mul(
deposit_value,
- close_ltv(config(reserve))
+ close_ltv,
)
);
@@ -432,28 +439,46 @@ module suilend::obligation {
deposit.deposited_ctoken_amount,
clock
);
+
+ if (is_emode) {
+ assert!(vector::length(&obligation.deposits) == 1, EIsolatedAssetViolation);
+ let target_reserve_index = emode_deposit_reserve_array_index(obligation);
+ let deposit = vector::borrow(&obligation.deposits, deposit_index);
+ assert!(deposit.reserve_array_index == target_reserve_index, EInvalidEModeDeposit);
+ };
+
log_obligation_data(obligation);
}
/// Process a borrow action. Makes sure that the obligation is healthy after the borrow.
public(package) fun borrow
(
obligation: &mut Obligation
,
- reserve: &mut Reserve
,
+ reserves: &mut vector>,
+ borrow_reserve_array_index: u64,
clock: &Clock,
amount: u64,
) {
- let borrow_index = find_or_add_borrow(obligation, reserve, clock);
+ let borrow_reserve = vector::borrow_mut(reserves, borrow_reserve_array_index);
+
+ let borrow_index = find_or_add_borrow(obligation, borrow_reserve, clock);
assert!(vector::length(&obligation.borrows) <= MAX_BORROWS, ETooManyBorrows);
- let deposit_index = find_deposit_index(obligation, reserve);
+ let is_emode = is_emode(obligation);
+ let borrow_weight = if (is_emode) {
+ decimal::from(1)
+ } else {
+ borrow_weight(config(borrow_reserve))
+ };
+
+ let deposit_index = find_deposit_index(obligation, borrow_reserve);
assert!(deposit_index == vector::length(&obligation.deposits), ECannotDepositAndBorrowSameAsset);
let borrow = vector::borrow_mut(&mut obligation.borrows, borrow_index);
borrow.borrowed_amount = add(borrow.borrowed_amount, decimal::from(amount));
// update health values
- let borrow_market_value = reserve::market_value(reserve, decimal::from(amount));
- let borrow_market_value_upper_bound = reserve::market_value_upper_bound(reserve, decimal::from(amount));
+ let borrow_market_value = reserve::market_value(borrow_reserve, decimal::from(amount));
+ let borrow_market_value_upper_bound = reserve::market_value_upper_bound(borrow_reserve, decimal::from(amount));
borrow.market_value = add(borrow.market_value, borrow_market_value);
obligation.unweighted_borrowed_value_usd = add(
@@ -462,16 +487,16 @@ module suilend::obligation {
);
obligation.weighted_borrowed_value_usd = add(
obligation.weighted_borrowed_value_usd,
- mul(borrow_market_value, borrow_weight(config(reserve)))
+ mul(borrow_market_value, borrow_weight)
);
obligation.weighted_borrowed_value_upper_bound_usd = add(
obligation.weighted_borrowed_value_upper_bound_usd,
- mul(borrow_market_value_upper_bound, borrow_weight(config(reserve)))
+ mul(borrow_market_value_upper_bound, borrow_weight)
);
let user_reward_manager = vector::borrow_mut(&mut obligation.user_reward_managers, borrow.user_reward_manager_index);
liquidity_mining::change_user_reward_manager_share(
- reserve::borrows_pool_reward_manager_mut(reserve),
+ reserve::borrows_pool_reward_manager_mut(borrow_reserve),
user_reward_manager,
liability_shares(borrow),
clock
@@ -479,9 +504,41 @@ module suilend::obligation {
assert!(is_healthy(obligation), EObligationIsNotHealthy);
- if (isolated(config(reserve)) || obligation.borrowing_isolated_asset) {
+ if (isolated(config(borrow_reserve)) || obligation.borrowing_isolated_asset) {
assert!(vector::length(&obligation.borrows) == 1, EIsolatedAssetViolation);
};
+
+ if (is_emode) {
+ // assert!(vector::length(&obligation.borrows) == 1, EIsolatedAssetViolation);
+ let target_reserve_index = emode_borrow_reserve_array_index(obligation);
+ let borrow = vector::borrow(&obligation.borrows, borrow_index);
+ assert!(borrow.reserve_array_index == target_reserve_index, EInvalidEModeBorrow);
+
+ let emode_deposit_reserve_array_index = emode_deposit_reserve_array_index(obligation);
+
+ let deposit_reserve = vector::borrow(reserves, emode_deposit_reserve_array_index);
+
+ let (open_ltv, close_ltv, _) = get_ltvs(
+ obligation,
+ deposit_reserve,
+ is_emode,
+ );
+
+ let deposit_index = option::destroy_some(get_single_deposit_array_reserve_if_any(obligation));
+
+ let deposit = vector::borrow_mut(&mut obligation.deposits, deposit_index);
+ let deposit_value = reserve::ctoken_market_value(deposit_reserve, deposit.deposited_ctoken_amount);
+
+ obligation.allowed_borrow_value_usd = mul(
+ reserve::ctoken_market_value_lower_bound(deposit_reserve, deposit.deposited_ctoken_amount),
+ open_ltv,
+ );
+ obligation.unhealthy_borrow_value_usd = mul(
+ deposit_value,
+ close_ltv,
+ );
+ };
+
log_obligation_data(obligation);
}
@@ -492,6 +549,13 @@ module suilend::obligation {
clock: &Clock,
max_repay_amount: Decimal,
): Decimal {
+ // TODO: FIX BORROW WEIGHT
+ let borrow_weight = if (is_emode(obligation)) {
+ decimal::from(1)
+ } else {
+ borrow_weight(config(reserve))
+ };
+
let borrow_index = find_borrow_index(obligation, reserve);
assert!(borrow_index < vector::length(&obligation.borrows), EBorrowNotFound);
let borrow = vector::borrow_mut(&mut obligation.borrows, borrow_index);
@@ -520,11 +584,11 @@ module suilend::obligation {
);
obligation.weighted_borrowed_value_usd = saturating_sub(
obligation.weighted_borrowed_value_usd,
- mul(repay_value, borrow_weight(config(reserve)))
+ mul(repay_value, borrow_weight)
);
obligation.weighted_borrowed_value_upper_bound_usd = saturating_sub(
obligation.weighted_borrowed_value_upper_bound_usd,
- mul(repay_value_upper_bound, borrow_weight(config(reserve)))
+ mul(repay_value_upper_bound, borrow_weight)
);
}
else {
@@ -539,11 +603,11 @@ module suilend::obligation {
);
obligation.weighted_borrowed_value_usd = add(
obligation.weighted_borrowed_value_usd,
- mul(additional_borrow_value, borrow_weight(config(reserve)))
+ mul(additional_borrow_value, borrow_weight)
);
obligation.weighted_borrowed_value_upper_bound_usd = add(
obligation.weighted_borrowed_value_upper_bound_usd,
- mul(additional_borrow_value_upper_bound, borrow_weight(config(reserve)))
+ mul(additional_borrow_value_upper_bound, borrow_weight)
);
};
@@ -1093,6 +1157,14 @@ module suilend::obligation {
) {
let deposit_index = find_deposit_index(obligation, reserve);
assert!(deposit_index < vector::length(&obligation.deposits), EDepositNotFound);
+
+ let is_emode = is_emode(obligation);
+ let (open_ltv, close_ltv, _) = get_ltvs(
+ obligation,
+ reserve,
+ is_emode,
+ );
+
let deposit = vector::borrow_mut(&mut obligation.deposits, deposit_index);
let withdraw_market_value = reserve::ctoken_market_value(reserve, ctoken_amount);
@@ -1107,14 +1179,14 @@ module suilend::obligation {
mul(
// need to use lower bound to keep calculation consistent
reserve::ctoken_market_value_lower_bound(reserve, ctoken_amount),
- open_ltv(config(reserve))
+ open_ltv
)
);
obligation.unhealthy_borrow_value_usd = sub(
obligation.unhealthy_borrow_value_usd,
mul(
withdraw_market_value,
- close_ltv(config(reserve))
+ close_ltv
)
);
@@ -1380,6 +1452,16 @@ module suilend::obligation {
df::exists_(&obligation.id, EModeFlag {})
}
+ fun emode_borrow_reserve_array_index(obligation: &Obligation
): u64 {
+ let borrow_reserve_index = get_single_borrow_array_reserve_if_any(obligation);
+ *option::borrow(&borrow_reserve_index)
+ }
+
+ fun emode_deposit_reserve_array_index
(obligation: &Obligation
): u64 {
+ let deposit_reserve_index = get_single_deposit_array_reserve_if_any(obligation);
+ *option::borrow(&deposit_reserve_index)
+ }
+
fun get_single_borrow_array_reserve_if_any
(
obligation: &Obligation
,
): Option {
@@ -1390,4 +1472,15 @@ module suilend::obligation {
option::some(vector::borrow(&obligation.borrows, 0).reserve_array_index)
}
}
+
+ fun get_single_deposit_array_reserve_if_any(
+ obligation: &Obligation
,
+ ): Option {
+ let len = vector::length(&obligation.deposits);
+ if (len != 1) {
+ option::none()
+ } else {
+ option::some(vector::borrow(&obligation.deposits, 0).reserve_array_index)
+ }
+ }
}
\ No newline at end of file
diff --git a/contracts/suilend/tests/obligation_tests.move b/contracts/suilend/tests/obligation_tests.move
index de0559c..c2724f7 100644
--- a/contracts/suilend/tests/obligation_tests.move
+++ b/contracts/suilend/tests/obligation_tests.move
@@ -327,17 +327,18 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 200 * 1_000_000 + 1);
+ let sui_reserve = get_reserve_mut(&mut reserves);
+
+ deposit(&mut obligation, sui_reserve, &clock, 100 * 1_000_000_000);
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 200 * 1_000_000 + 1);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
sui::test_utils::destroy(clock);
test_scenario::end(scenario);
@@ -352,18 +353,21 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
+ let sui_reserve = get_reserve_mut(&mut reserves);
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 1);
- deposit(&mut obligation, &mut usdc_reserve, &clock, 1);
+ deposit(&mut obligation, sui_reserve, &clock, 100 * 1_000_000_000);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 1);
+ let usdc_reserve = get_reserve_mut(&mut reserves);
+ deposit(&mut obligation, usdc_reserve, &clock, 1);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
sui::test_utils::destroy(clock);
test_scenario::end(scenario);
@@ -378,15 +382,18 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut sui_reserve = sui_reserve(&mut scenario);
-
+
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut sui_reserve, &clock, 1);
+ let sui_reserve = get_reserve_mut(&mut reserves);
+
+ deposit(&mut obligation, sui_reserve, &clock, 100 * 1_000_000_000);
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 1);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
sui::test_utils::destroy(clock);
test_scenario::end(scenario);
@@ -427,9 +434,11 @@ module suilend::obligation_tests {
config
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1
);
@@ -439,7 +448,8 @@ module suilend::obligation_tests {
// this fails
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1
);
@@ -487,9 +497,11 @@ module suilend::obligation_tests {
config
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1
);
@@ -497,9 +509,11 @@ module suilend::obligation_tests {
refresh(&mut obligation, &mut reserves, &clock);
// this fails
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1
);
@@ -547,20 +561,24 @@ module suilend::obligation_tests {
config
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
- &clock,
+ &mut reserves,
+ borrow_idx,
+ &clock,
1
);
refresh(&mut obligation, &mut reserves, &clock);
// this fails
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
- &clock,
+ &mut reserves,
+ borrow_idx,
+ &clock,
1
);
@@ -619,28 +637,30 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
+ let usdc_reserve = get_reserve_mut(&mut reserves);
reserve::update_price_for_testing(
- &mut usdc_reserve,
+ usdc_reserve,
&clock,
decimal::from(1),
decimal::from(2)
);
+ let sui_reserve = get_reserve_mut(&mut reserves);
reserve::update_price_for_testing(
- &mut sui_reserve,
+ sui_reserve,
&clock,
decimal::from(10),
decimal::from(5)
);
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 12_500_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 12_500_000);
+ deposit(&mut obligation, sui_reserve, &clock, 100 * 1_000_000_000);
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 12_500_000);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 12_500_000);
assert!(obligation.deposits().length() == 1, 0);
@@ -669,8 +689,7 @@ module suilend::obligation_tests {
assert!(obligation.weighted_borrowed_value_upper_bound_usd() == decimal::from(100), 4);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
clock::destroy_for_testing(clock);
test_scenario::end(scenario);
@@ -685,20 +704,21 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
-
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 50 * 1_000_000);
+ let sui_reserve = get_reserve_mut(&mut reserves);
+ deposit(&mut obligation, sui_reserve, &clock, 100 * 1_000_000_000);
- withdraw(&mut obligation, &mut sui_reserve, &clock, 50 * 1_000_000_000 + 1);
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 50 * 1_000_000);
+
+ let sui_reserve = get_reserve_mut(&mut reserves);
+ withdraw(&mut obligation, sui_reserve, &clock, 50 * 1_000_000_000 + 1);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
sui::test_utils::destroy(clock);
test_scenario::end(scenario);
@@ -713,20 +733,22 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 50 * 1_000_000);
+ let sui_reserve = get_reserve_mut(&mut reserves);
+ deposit(&mut obligation, sui_reserve, &clock, 100 * 1_000_000_000);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 50 * 1_000_000);
- withdraw(&mut obligation, &mut usdc_reserve, &clock, 1);
+ let usdc_reserve = get_reserve_mut(&mut reserves);
+ withdraw(&mut obligation, usdc_reserve, &clock, 1);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
sui::test_utils::destroy(clock);
test_scenario::end(scenario);
@@ -740,55 +762,52 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut usdt_reserve = usdt_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
reserve::update_price_for_testing(
- &mut usdc_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(1),
decimal::from(2)
);
reserve::update_price_for_testing(
- &mut usdt_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(1),
decimal::from(2)
);
reserve::update_price_for_testing(
- &mut sui_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(10),
decimal::from(5)
);
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
+ deposit(&mut obligation, get_reserve_mut(&mut reserves), &clock, 100 * 1_000_000_000);
- let amount = obligation.max_withdraw_amount(&sui_reserve);
+ let amount = obligation.max_withdraw_amount(get_reserve(&reserves));
assert!(amount == 100 * 1_000_000_000, 0);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 20 * 1_000_000);
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 20 * 1_000_000);
// sui open ltv is 0.2
// allowed borrow value = 100 * 0.2 * 5 = 100
// weighted upper bound borrow value = 20 * 2 * 2 = 80
// => max withdraw amount should be 20
- let amount = obligation.max_withdraw_amount(&sui_reserve);
+ let amount = obligation.max_withdraw_amount(get_reserve(&mut reserves));
assert!(amount == 20 * 1_000_000_000, 0);
- deposit(&mut obligation, &mut usdt_reserve, &clock, 100 * 1_000_000);
+ deposit(&mut obligation, get_reserve_mut(&mut reserves),&clock, 100 * 1_000_000);
- let amount = obligation.max_withdraw_amount(&usdt_reserve);
+ let amount = obligation.max_withdraw_amount(get_reserve(&mut reserves));
assert!(amount == 100 * 1_000_000, 0);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(usdt_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
sui::test_utils::destroy(obligation);
clock::destroy_for_testing(clock);
test_scenario::end(scenario);
@@ -803,28 +822,29 @@ module suilend::obligation_tests {
let mut scenario = test_scenario::begin(owner);
let lending_market_id = object::new(test_scenario::ctx(&mut scenario));
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
reserve::update_price_for_testing(
- &mut usdc_reserve,
- &clock,
+ get_reserve_mut(&mut reserves),
+ &clock,
decimal::from(1),
decimal::from(2)
);
reserve::update_price_for_testing(
- &mut sui_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(10),
decimal::from(5)
);
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 20 * 1_000_000);
- withdraw(&mut obligation, &mut sui_reserve, &clock, 20 * 1_000_000_000);
+ deposit(&mut obligation, get_reserve_mut(&mut reserves), &clock, 100 * 1_000_000_000);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 20 * 1_000_000);
+ withdraw(&mut obligation, get_reserve_mut(&mut reserves), &clock, 20 * 1_000_000_000);
assert!(obligation.deposits().length() == 1, 0);
@@ -853,8 +873,7 @@ module suilend::obligation_tests {
assert!(obligation.weighted_borrowed_value_upper_bound_usd() == decimal::from(80), 4);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
clock::destroy_for_testing(clock);
sui::test_utils::destroy(obligation);
test_scenario::end(scenario);
@@ -871,33 +890,34 @@ module suilend::obligation_tests {
let mut clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
clock::set_for_testing(&mut clock, 0);
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
reserve::update_price_for_testing(
- &mut usdc_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(1),
decimal::from(2)
);
reserve::update_price_for_testing(
- &mut sui_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(10),
decimal::from(5)
);
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 25 * 1_000_000);
+ deposit(&mut obligation, get_reserve_mut(&mut reserves), &clock, 100 * 1_000_000_000);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 25 * 1_000_000);
clock::set_for_testing(&mut clock, 1000);
- reserve::compound_interest(&mut usdc_reserve, &clock);
+ reserve::compound_interest(get_reserve_mut(&mut reserves), &clock);
let repay_amount = repay(
&mut obligation,
- &mut usdc_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(25 * 1_000_000)
);
@@ -932,8 +952,7 @@ module suilend::obligation_tests {
assert!(obligation.weighted_borrowed_value_upper_bound_usd() == decimal::from(1), 4);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
clock::destroy_for_testing(clock);
sui::test_utils::destroy(obligation);
test_scenario::end(scenario);
@@ -950,18 +969,18 @@ module suilend::obligation_tests {
let mut clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
clock::set_for_testing(&mut clock, 0);
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 100 * 1_000_000);
+ deposit(&mut obligation, get_reserve_mut(&mut reserves), &clock, 100 * 1_000_000_000);
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 100 * 1_000_000);
clock::set_for_testing(&mut clock, 1000);
- reserve::compound_interest(&mut usdc_reserve, &clock);
+ reserve::compound_interest(get_reserve_mut(&mut reserves), &clock);
- let repay_amount = repay(&mut obligation, &mut usdc_reserve, &clock, decimal::from(500_000));
+ let repay_amount = repay(&mut obligation, get_reserve_mut(&mut reserves), &clock, decimal::from(500_000));
assert!(repay_amount == decimal::from(500_000), 0);
assert!(obligation.deposits().length() == 1, 0);
@@ -992,8 +1011,7 @@ module suilend::obligation_tests {
assert!(obligation.weighted_borrowed_value_usd() == decimal::from_percent_u64(20_100), 4);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
clock::destroy_for_testing(clock);
sui::test_utils::destroy(obligation);
test_scenario::end(scenario);
@@ -1010,33 +1028,33 @@ module suilend::obligation_tests {
let mut clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
clock::set_for_testing(&mut clock, 0);
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 100 * 1_000_000);
+ deposit(&mut obligation, get_reserve_mut(&mut reserves), &clock, 100 * 1_000_000_000);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 100 * 1_000_000);
clock::set_for_testing(&mut clock, 1000);
reserve::update_price_for_testing(
- &mut usdc_reserve,
- &clock,
+ get_reserve_mut(&mut reserves),
+ &clock,
decimal::from(10),
decimal::from(10)
);
- reserve::compound_interest(&mut usdc_reserve, &clock);
+ reserve::compound_interest(get_reserve_mut(&mut reserves), &clock);
let repay_amount = repay(
&mut obligation,
- &mut usdc_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(100 * 1_000_000)
);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
clock::destroy_for_testing(clock);
sui::test_utils::destroy(obligation);
test_scenario::end(scenario);
@@ -1053,18 +1071,18 @@ module suilend::obligation_tests {
let mut clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
clock::set_for_testing(&mut clock, 0);
- let mut usdc_reserve = usdc_reserve(&mut scenario);
- let mut sui_reserve = sui_reserve(&mut scenario);
+ let mut reserves = reserves(&mut scenario);
let mut obligation = create_obligation(object::uid_to_inner(&lending_market_id), test_scenario::ctx(&mut scenario));
- deposit(&mut obligation, &mut sui_reserve, &clock, 100 * 1_000_000_000);
- borrow(&mut obligation, &mut usdc_reserve, &clock, 100 * 1_000_000);
-
+ deposit(&mut obligation, get_reserve_mut(&mut reserves), &clock, 100 * 1_000_000_000);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
+ borrow(&mut obligation, &mut reserves, borrow_idx, &clock, 100 * 1_000_000);
let repay_amount = repay(
&mut obligation,
- &mut usdc_reserve,
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(101 * 1_000_000)
);
@@ -1079,7 +1097,7 @@ module suilend::obligation_tests {
assert!(obligation.borrows().length() == 0, 0);
let user_reward_manager_index = obligation.find_user_reward_manager_index(
- reserve::borrows_pool_reward_manager_mut(&mut usdc_reserve)
+ reserve::borrows_pool_reward_manager_mut(get_reserve_mut(&mut reserves))
);
let user_reward_manager = &obligation.user_reward_managers()[user_reward_manager_index];
assert!(liquidity_mining::shares(user_reward_manager) == 0, 0);
@@ -1091,8 +1109,7 @@ module suilend::obligation_tests {
assert!(obligation.weighted_borrowed_value_usd() == decimal::from_percent_u64(0), 4);
sui::test_utils::destroy(lending_market_id);
- sui::test_utils::destroy(usdc_reserve);
- sui::test_utils::destroy(sui_reserve);
+ sui::test_utils::destroy(reserves);
clock::destroy_for_testing(clock);
sui::test_utils::destroy(obligation);
test_scenario::end(scenario);
@@ -1103,6 +1120,7 @@ module suilend::obligation_tests {
public fun test_refresh_fail_deposit_price_stale() {
use sui::test_scenario::{Self};
use sui::clock::{Self};
+ use sui::test_utils::{Self};
let owner = @0x26;
let mut scenario = test_scenario::begin(owner);
@@ -1128,7 +1146,7 @@ module suilend::obligation_tests {
&clock
);
- sui::test_utils::destroy(reserves);
+ test_utils::destroy(reserves);
sui::test_utils::destroy(lending_market_id);
clock::destroy_for_testing(clock);
sui::test_utils::destroy(obligation);
@@ -1157,9 +1175,11 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
100 * 1_000_000
);
@@ -1185,6 +1205,7 @@ module suilend::obligation_tests {
test_scenario::end(scenario);
}
+
#[test]
public fun test_refresh_happy() {
use sui::test_scenario::{Self};
@@ -1212,9 +1233,11 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
100 * 1_000_000
);
@@ -1298,9 +1321,11 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
100 * 1_000_000
);
@@ -1347,15 +1372,19 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
50 * 1_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
50 * 1_000_000
);
@@ -1458,9 +1487,11 @@ module suilend::obligation_tests {
&clock,
2 * 100_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
100 * 1_000_000
);
@@ -1513,7 +1544,7 @@ module suilend::obligation_tests {
assert!(obligation.deposits().length() == 1, 0);
- let user_reward_manager_index = obligation.find_user_reward_manager_index(
+ let user_reward_manager_index = obligation.find_user_reward_manager_index(
reserve::deposits_pool_reward_manager_mut(get_reserve_mut(&mut reserves))
);
let user_reward_manager = &obligation.user_reward_managers()[user_reward_manager_index];
@@ -1569,9 +1600,11 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1 * 1_000_000
);
@@ -1623,7 +1656,7 @@ module suilend::obligation_tests {
let user_reward_manager_index = obligation.find_user_reward_manager_index(
reserve::borrows_pool_reward_manager_mut(get_reserve_mut(&mut reserves))
);
- let user_reward_manager = &obligation.user_reward_managers()[user_reward_manager_index];
+ let user_reward_manager = vector::borrow(obligation.user_reward_managers(), user_reward_manager_index);
assert!(liquidity_mining::shares(user_reward_manager) == 0, 5);
assert!(obligation.deposited_value_usd() == add(decimal::from(998), decimal::from_percent(90)), 0);
@@ -1666,9 +1699,11 @@ module suilend::obligation_tests {
&clock,
550_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
10 * 1_000_000
);
@@ -1782,9 +1817,11 @@ module suilend::obligation_tests {
&clock,
10 * 1_000_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -1827,18 +1864,22 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -1899,27 +1940,33 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -1935,9 +1982,11 @@ module suilend::obligation_tests {
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -1979,27 +2028,34 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000
);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -2015,9 +2071,11 @@ module suilend::obligation_tests {
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -2059,27 +2117,34 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000
);
+
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -2095,9 +2160,11 @@ module suilend::obligation_tests {
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -2155,27 +2222,33 @@ module suilend::obligation_tests {
sui::test_utils::destroy(vector::pop_back(obligation.borrows_mut()));
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000
);
assert!(!obligation.is_looped(), 0);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000
);
@@ -2224,9 +2297,11 @@ module suilend::obligation_tests {
&clock,
100 * 1_000_000
);
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000_000
);
@@ -2242,9 +2317,11 @@ module suilend::obligation_tests {
};
// actually loop
+ let borrow_idx = get_reserve_array_index(&reserves);
borrow(
&mut obligation,
- get_reserve_mut(&mut reserves),
+ &mut reserves,
+ borrow_idx,
&clock,
1_000_000
);
@@ -2266,7 +2343,7 @@ module suilend::obligation_tests {
}
#[test]
- public fun test_set_emod_on_and_off() {
+ public fun test_emode_deposit_borrow() {
use sui::test_scenario::{Self};
let owner = @0x26;
@@ -2279,7 +2356,7 @@ module suilend::obligation_tests {
let clock = clock::create_for_testing(test_scenario::ctx(&mut scenario));
reserve::update_price_for_testing(
- get_reserve_mut(&mut reserves),
+ get_reserve_mut(&mut reserves),
&clock,
decimal::from(1),
decimal::from(2)
@@ -2291,14 +2368,14 @@ module suilend::obligation_tests {
decimal::from(5)
);
- let usdc_index = get_reserve_array_index(&reserves);
+ let borrow_idx = get_reserve_array_index