mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-26 00:20:41 +00:00
fix: Use cash-basis-aware debt delta for LoanSet DebtMaximum guard
Remove unused vaultMaximum local left over from the AssetsMaximum guard refactor, and stop the DebtMaximum guard from unconditionally adding interestDue to the projected DebtTotal. Reuse the existing loanOriginationDeltas dispatcher, which already excludes interestDue under cash-basis accounting.
This commit is contained in:
@@ -439,9 +439,8 @@ LoanSet::doApply()
|
||||
principalRequested,
|
||||
properties.loanState.managementFeeDue);
|
||||
|
||||
auto const vaultMaximum = *vaultSle->at(sfAssetsMaximum);
|
||||
XRPL_ASSERT_PARTS(
|
||||
vaultMaximum == 0 || vaultMaximum > *vaultTotalProxy,
|
||||
*vaultSle->at(sfAssetsMaximum) == 0 || *vaultSle->at(sfAssetsMaximum) > *vaultTotalProxy,
|
||||
"xrpl::LoanSet::doApply",
|
||||
"Vault is below maximum limit");
|
||||
|
||||
@@ -492,8 +491,9 @@ LoanSet::doApply()
|
||||
|
||||
auto const loanAssetsToBorrower = principalRequested - originationFee;
|
||||
|
||||
auto const newDebtDelta = principalRequested + state.interestDue;
|
||||
auto const newDebtTotal = brokerSle->at(sfDebtTotal) + newDebtDelta;
|
||||
auto const [assetsTotalDelta, debtTotalDelta] =
|
||||
loanOriginationDeltas(ctx_.view().rules(), vaultSle, principalRequested, state.interestDue);
|
||||
auto const newDebtTotal = brokerSle->at(sfDebtTotal) + debtTotalDelta;
|
||||
if (auto const debtMaximum = brokerSle->at(sfDebtMaximum);
|
||||
debtMaximum != 0 && debtMaximum < newDebtTotal)
|
||||
{
|
||||
@@ -635,8 +635,6 @@ LoanSet::doApply()
|
||||
view.insert(loan);
|
||||
|
||||
// Update the balances in the vault
|
||||
auto const [assetsTotalDelta, debtTotalDelta] =
|
||||
loanOriginationDeltas(ctx_.view().rules(), vaultSle, principalRequested, state.interestDue);
|
||||
vaultAvailableProxy -= principalRequested;
|
||||
vaultTotalProxy += assetsTotalDelta;
|
||||
XRPL_ASSERT_PARTS(
|
||||
|
||||
@@ -8684,8 +8684,7 @@ protected:
|
||||
}
|
||||
|
||||
// AssetsMaximum guard checks interestDue headroom only under
|
||||
// whole-life accounting (cash-basis never adds interest to
|
||||
// AssetsTotal). DebtMaximum guard is unconditional either way.
|
||||
// whole-life accounting; DebtMaximum guard also varies by model.
|
||||
auto runVaultGuard = [&](FeatureBitset features, Number const& slack, TER expected) {
|
||||
Env env(*this, features);
|
||||
|
||||
@@ -8761,12 +8760,16 @@ protected:
|
||||
runVaultGuard(all_ | featureLendingProtocolV1_1, oneDrop, tesSUCCESS);
|
||||
}
|
||||
|
||||
for (auto const features : {all_ | featureLendingProtocolV1_1, all_})
|
||||
// DebtMaximum guard: cash-basis projects principal-only DebtTotal;
|
||||
// whole-life projects principal + interestDue.
|
||||
for (auto const cashBasis : {true, false})
|
||||
{
|
||||
testcase(
|
||||
std::string("cash-basis: LoanSet DebtMaximum guard unaffected by amendment (") +
|
||||
(features[featureLendingProtocolV1_1] ? "enabled)" : "disabled)"));
|
||||
Number const newDebtTotal = principalOutstandingCash + interestDueCash;
|
||||
std::string("LoanSet DebtMaximum guard (") +
|
||||
(cashBasis ? "cash-basis)" : "whole-life)"));
|
||||
auto const features = cashBasis ? all_ | featureLendingProtocolV1_1 : all_;
|
||||
Number const newDebtTotal =
|
||||
principalOutstandingCash + (cashBasis ? Number{} : interestDueCash);
|
||||
runBrokerGuard(features, newDebtTotal - oneDrop, tecLIMIT_EXCEEDED);
|
||||
runBrokerGuard(features, newDebtTotal, tesSUCCESS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user