From 5bd363b3d09ee3231a4cc8a8914daa261b3fd1c3 Mon Sep 17 00:00:00 2001 From: Vito <5780819+Tapanito@users.noreply.github.com> Date: Mon, 17 Aug 2026 12:23:10 +0200 Subject: [PATCH] refactor: Gate loan impairment fix behind fixCleanup3_4_0 Switches the impair/unimpair behaviour change (reject non-late impair with tecTOO_SOON; stop rewriting sfNextPaymentDueDate on impair/unimpair) from featureLendingProtocolV1_1 to fixCleanup3_4_0, along with the associated tests. --- .../tx/transactors/lending/LoanManage.cpp | 6 ++--- src/test/app/lending/LoanCashBasis_test.cpp | 6 ++--- src/test/app/lending/LoanSecurity_test.cpp | 24 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/libxrpl/tx/transactors/lending/LoanManage.cpp b/src/libxrpl/tx/transactors/lending/LoanManage.cpp index c924aadeec..4220049889 100644 --- a/src/libxrpl/tx/transactors/lending/LoanManage.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanManage.cpp @@ -287,7 +287,7 @@ LoanManage::impairLoan( Asset const& vaultAsset, beast::Journal j) { - if (view.rules().enabled(featureLendingProtocolV1_1) && !isPaymentLate(view, loanSle)) + if (view.rules().enabled(fixCleanup3_4_0) && !isPaymentLate(view, loanSle)) { JLOG(j.warn()) << "Cannot impair a loan that is not late"; return tecTOO_SOON; @@ -315,7 +315,7 @@ LoanManage::impairLoan( // Update the Loan object loanSle->setFlag(lsfLoanImpaired); - if (!view.rules().enabled(featureLendingProtocolV1_1)) + if (!view.rules().enabled(fixCleanup3_4_0)) { auto loanNextDueProxy = loanSle->at(sfNextPaymentDueDate); if (!isPaymentLate(view, loanSle)) @@ -359,7 +359,7 @@ LoanManage::unimpairLoan( // Update the Loan object loanSle->clearFlag(lsfLoanImpaired); - if (!view.rules().enabled(featureLendingProtocolV1_1)) + if (!view.rules().enabled(fixCleanup3_4_0)) { auto const paymentInterval = loanSle->at(sfPaymentInterval); auto const normalPaymentDueDate = diff --git a/src/test/app/lending/LoanCashBasis_test.cpp b/src/test/app/lending/LoanCashBasis_test.cpp index 0bd156adca..d00f7a3989 100644 --- a/src/test/app/lending/LoanCashBasis_test.cpp +++ b/src/test/app/lending/LoanCashBasis_test.cpp @@ -542,10 +542,10 @@ private: return std::make_tuple(broker, loanKeylet, lender, borrower); }; - // Under featureLendingProtocolV1_1 impairment is only allowed once the + // Under fixCleanup3_4_0 impairment is only allowed once the // payment is late. Advance past the first due date before impairing. auto advancePastDueDate = [&](Env& env, Keylet const& loanKeylet) { - if (!env.current()->rules().enabled(featureLendingProtocolV1_1)) + if (!env.current()->rules().enabled(fixCleanup3_4_0)) return; auto const loan = env.le(loanKeylet); BEAST_EXPECT(loan); @@ -835,7 +835,7 @@ private: Number const managementFeeBeforeImpair = loanBeforeImpair->at(sfManagementFeeOutstanding); Number const expectedExposure = totalValueBeforeImpair - managementFeeBeforeImpair; - // With featureLendingProtocolV1_1, impairment is only allowed once the + // With fixCleanup3_4_0, impairment is only allowed once the // payment is late. After the earlier LoanPay the due date advanced by // one interval, so use the current due date rather than startDate. std::uint32_t const dueDateBeforeImpair = loanBeforeImpair->at(sfNextPaymentDueDate); diff --git a/src/test/app/lending/LoanSecurity_test.cpp b/src/test/app/lending/LoanSecurity_test.cpp index 81cd307067..0708c8ad36 100644 --- a/src/test/app/lending/LoanSecurity_test.cpp +++ b/src/test/app/lending/LoanSecurity_test.cpp @@ -512,7 +512,7 @@ private: PaymentParameters{.showStepBalances = true}); } - // Verify that with featureLendingProtocolV1_1: + // Verify that with fixCleanup3_4_0: // 1. A loan cannot be impaired before its payment is late. // 2. Impairing a late loan does not change sfNextPaymentDueDate. // 3. The unimpair operation does not change sfNextPaymentDueDate. @@ -525,8 +525,8 @@ private: testcase("Impairment does not change payment due date"); - Env env(*this, all_ | featureLendingProtocolV1_1); - BEAST_EXPECT(env.enabled(featureLendingProtocolV1_1)); + Env env(*this, all_ | fixCleanup3_4_0); + BEAST_EXPECT(env.enabled(fixCleanup3_4_0)); Account const lender{"lender"}; Account const borrower{"borrower"}; @@ -590,7 +590,7 @@ private: } } - // Verify that without featureLendingProtocolV1_1, the pre-amendment + // Verify that without fixCleanup3_4_0, the pre-amendment // impair/unimpair behaviour is preserved: // 1. Impairing a loan before its payment is late moves // sfNextPaymentDueDate to "now". @@ -607,8 +607,8 @@ private: testcase("Pre-amendment impair/unimpair date restoration"); - Env env(*this, all_ - featureLendingProtocolV1_1); - BEAST_EXPECT(!env.enabled(featureLendingProtocolV1_1)); + Env env(*this, all_ - fixCleanup3_4_0); + BEAST_EXPECT(!env.enabled(fixCleanup3_4_0)); Account const lender{"lender"}; Account const borrower{"borrower"}; @@ -729,7 +729,7 @@ private: // FN-68: a borrower must not be able to bypass late-payment charges by // paying an impaired, overdue loan with a plain LoanPay. Under - // featureLendingProtocolV1_1 impairment no longer moves the due date, so + // fixCleanup3_4_0 impairment no longer moves the due date, so // the payment logic sees the real (overdue) date: a regular payment is // rejected with tecEXPIRED, and only a tfLoanLatePayment (which charges // the late fee + late interest) is accepted. @@ -742,8 +742,8 @@ private: testcase("Impaired overdue LoanPay requires late-payment flag"); - Env env(*this, all_ | featureLendingProtocolV1_1); - BEAST_EXPECT(env.enabled(featureLendingProtocolV1_1)); + Env env(*this, all_ | fixCleanup3_4_0); + BEAST_EXPECT(env.enabled(fixCleanup3_4_0)); Account const lender{"lender"}; Account const borrower{"borrower"}; @@ -830,7 +830,7 @@ private: } // FN-68 (pre-amendment): documents the original vulnerability. Without - // featureLendingProtocolV1_1, impairing moves the due date and LoanPay + // fixCleanup3_4_0, impairing moves the due date and LoanPay // auto-unimpair pushes it into the future before the late check, so a // plain (Flags = 0) LoanPay on an impaired, overdue loan is accepted as // on-time (tesSUCCESS) and the borrower dodges the late-payment charges. @@ -845,8 +845,8 @@ private: testcase("Impaired overdue LoanPay bypass (pre-amendment)"); - Env env(*this, all_ - featureLendingProtocolV1_1); - BEAST_EXPECT(!env.enabled(featureLendingProtocolV1_1)); + Env env(*this, all_ - fixCleanup3_4_0); + BEAST_EXPECT(!env.enabled(fixCleanup3_4_0)); Account const lender{"lender"}; Account const borrower{"borrower"};