From 19ea6b500c872154e754693b6eb59ddf4a4b021d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Mon, 15 Jan 2024 16:44:40 +0100 Subject: [PATCH] Loans: add `increase_debt()` action (#1691) * base implementation * add event * add testing & benchmarks * fix docs --- pallets/loans/src/benchmarking.rs | 8 +++++ pallets/loans/src/lib.rs | 35 ++++++++++++++++++- pallets/loans/src/tests/borrow_loan.rs | 29 +++++++++++++++ pallets/loans/src/weights.rs | 5 +++ runtime/altair/src/weights/pallet_loans.rs | 5 +++ .../centrifuge/src/weights/pallet_loans.rs | 5 +++ .../development/src/weights/pallet_loans.rs | 5 +++ 7 files changed, 91 insertions(+), 1 deletion(-) diff --git a/pallets/loans/src/benchmarking.rs b/pallets/loans/src/benchmarking.rs index 6a30adad01..d1b2f6ace0 100644 --- a/pallets/loans/src/benchmarking.rs +++ b/pallets/loans/src/benchmarking.rs @@ -472,6 +472,14 @@ benchmarks! { }: _(RawOrigin::Signed(any), pool_id, change_id) + increase_debt { + let n in 1..Helper::::max_active_loans() - 1; + + let borrower = account("borrower", 0, 0); + let pool_id = Helper::::initialize_active_state(n); + let loan_id = Helper::::create_loan(pool_id, u16::MAX.into()); + + }: _(RawOrigin::Signed(borrower), pool_id, loan_id, PrincipalInput::Internal(10.into())) } impl_benchmark_test_suite!( diff --git a/pallets/loans/src/lib.rs b/pallets/loans/src/lib.rs index fb93249cb3..12e47079ac 100644 --- a/pallets/loans/src/lib.rs +++ b/pallets/loans/src/lib.rs @@ -346,6 +346,12 @@ pub mod pallet { repaid_amount: RepaidInput, borrow_amount: PrincipalInput, }, + /// Debt of a loan has been increased + DebtIncreased { + pool_id: T::PoolId, + loan_id: T::LoanId, + amount: PrincipalInput, + }, } #[pallet::error] @@ -469,7 +475,6 @@ pub mod pallet { /// at [`types::LoanRestrictions`]. The `amount` will be transferred /// from pool reserve to borrower. The portfolio valuation of the pool /// is updated to reflect the new present value of the loan. - /// Rate accumulation will start after the first borrow. #[pallet::weight(T::WeightInfo::borrow(T::MaxActiveLoansPerPool::get()))] #[pallet::call_index(1)] pub fn borrow( @@ -847,6 +852,34 @@ pub mod pallet { Ok(()) } + + /// Increase debt for a loan. Similar to [`Pallet::borrow()`] but + /// without transferring from the pool. + /// + /// The origin must be the borrower of the loan. + /// The increase debt action should fulfill the borrow restrictions + /// configured at [`types::LoanRestrictions`]. The portfolio valuation + /// of the pool is updated to reflect the new present value of the loan. + #[pallet::weight(T::WeightInfo::increase_debt(T::MaxActiveLoansPerPool::get()))] + #[pallet::call_index(13)] + pub fn increase_debt( + origin: OriginFor, + pool_id: T::PoolId, + loan_id: T::LoanId, + amount: PrincipalInput, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let _count = Self::borrow_action(&who, pool_id, loan_id, &amount, false)?; + + Self::deposit_event(Event::::DebtIncreased { + pool_id, + loan_id, + amount, + }); + + Ok(()) + } } // Loan actions diff --git a/pallets/loans/src/tests/borrow_loan.rs b/pallets/loans/src/tests/borrow_loan.rs index 038feb6586..20f51c8ae3 100644 --- a/pallets/loans/src/tests/borrow_loan.rs +++ b/pallets/loans/src/tests/borrow_loan.rs @@ -582,3 +582,32 @@ fn twice_with_elapsed_time() { ); }); } + +#[test] +fn increase_debt_does_not_withdraw() { + new_test_ext().execute_with(|| { + MockPools::mock_withdraw(|_, _, _| { + unreachable!("increase debt must not withdraw funds from the pool"); + }); + + let loan = LoanInfo { + pricing: Pricing::External(ExternalPricing { + max_borrow_amount: ExtMaxBorrowAmount::NoLimit, + ..util::base_external_pricing() + }), + ..util::base_external_loan() + }; + + let loan_id = util::create_loan(loan); + + let amount = ExternalAmount::new(QUANTITY, PRICE_VALUE); + config_mocks(amount.balance().unwrap()); + + assert_ok!(Loans::borrow( + RuntimeOrigin::signed(BORROWER), + POOL_A, + loan_id, + PrincipalInput::External(amount) + )); + }); +} diff --git a/pallets/loans/src/weights.rs b/pallets/loans/src/weights.rs index 75c2fae7ee..e76a7da46a 100644 --- a/pallets/loans/src/weights.rs +++ b/pallets/loans/src/weights.rs @@ -27,6 +27,7 @@ pub trait WeightInfo { fn update_portfolio_valuation(n: u32) -> Weight; fn propose_transfer_debt(n: u32) -> Weight; fn apply_transfer_debt(n: u32) -> Weight; + fn increase_debt(n: u32) -> Weight; } impl WeightInfo for () { @@ -81,4 +82,8 @@ impl WeightInfo for () { fn apply_transfer_debt(_: u32) -> Weight { Weight::zero() } + + fn increase_debt(_: u32) -> Weight { + Weight::zero() + } } diff --git a/runtime/altair/src/weights/pallet_loans.rs b/runtime/altair/src/weights/pallet_loans.rs index ee171ad4a5..613149733f 100644 --- a/runtime/altair/src/weights/pallet_loans.rs +++ b/runtime/altair/src/weights/pallet_loans.rs @@ -372,4 +372,9 @@ impl pallet_loans::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) } + + fn increase_debt(_: u32) -> Weight { + // Pending to generate + Weight::zero() + } } diff --git a/runtime/centrifuge/src/weights/pallet_loans.rs b/runtime/centrifuge/src/weights/pallet_loans.rs index 55726cfe35..7acbc5fc8c 100644 --- a/runtime/centrifuge/src/weights/pallet_loans.rs +++ b/runtime/centrifuge/src/weights/pallet_loans.rs @@ -372,4 +372,9 @@ impl pallet_loans::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) } + + fn increase_debt(_: u32) -> Weight { + // Pending to generate + Weight::zero() + } } diff --git a/runtime/development/src/weights/pallet_loans.rs b/runtime/development/src/weights/pallet_loans.rs index 4926ed7cc7..67d1e5a19c 100644 --- a/runtime/development/src/weights/pallet_loans.rs +++ b/runtime/development/src/weights/pallet_loans.rs @@ -372,4 +372,9 @@ impl pallet_loans::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) } + + fn increase_debt(_: u32) -> Weight { + // Pending to generate + Weight::zero() + } }