mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-18 01:55:50 +00:00
Ensure interest portion doesn't go negative
- Ensure principal part is not bigger than whole payment. - Add some documentation.
This commit is contained in:
@@ -564,6 +564,20 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
|
|||||||
{sfPreviousPaymentDate, soeDEFAULT},
|
{sfPreviousPaymentDate, soeDEFAULT},
|
||||||
{sfNextPaymentDueDate, soeOPTIONAL},
|
{sfNextPaymentDueDate, soeOPTIONAL},
|
||||||
{sfPaymentRemaining, soeDEFAULT},
|
{sfPaymentRemaining, soeDEFAULT},
|
||||||
|
// The loan object tracks three values:
|
||||||
|
// - TotalValueOutstanding: The total amount owed by the borrower to
|
||||||
|
// the lender / vault.
|
||||||
|
// - PrincipalOutstanding: The portion of the TotalValueOutstanding
|
||||||
|
// that is from the prinicpal borrowed.
|
||||||
|
// - InterestOwed: The portion of the TotalValueOutstanding that
|
||||||
|
// represents interest owed to the vault.
|
||||||
|
// There are two additional values that can be computed from these:
|
||||||
|
// - InterestOutstanding: TotalValueOutstanding - PrincipalOutstanding
|
||||||
|
// This is the total amount of interest still pending on the loan,
|
||||||
|
// independent of management fees.
|
||||||
|
// - ManagementFeeOwed: InterestOutstanding - InterestOwed
|
||||||
|
// This is the amount of the total interest that will be sent to the
|
||||||
|
// broker as management fees.
|
||||||
{sfPrincipalOutstanding, soeDEFAULT},
|
{sfPrincipalOutstanding, soeDEFAULT},
|
||||||
{sfTotalValueOutstanding, soeDEFAULT},
|
{sfTotalValueOutstanding, soeDEFAULT},
|
||||||
{sfInterestOwed, soeDEFAULT},
|
{sfInterestOwed, soeDEFAULT},
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ computePaymentComponents(
|
|||||||
roundPeriodicPayment(asset, periodicPayment, scale);
|
roundPeriodicPayment(asset, periodicPayment, scale);
|
||||||
if (paymentRemaining == 1 || totalValueOutstanding <= periodicPayment)
|
if (paymentRemaining == 1 || totalValueOutstanding <= periodicPayment)
|
||||||
{
|
{
|
||||||
// If there's only one payment left, we need to pay off the principal.
|
// If there's only one payment left, we need to pay off each of the loan
|
||||||
|
// parts.
|
||||||
//
|
//
|
||||||
// The totalValueOutstanding should never be less than the
|
// The totalValueOutstanding should never be less than the
|
||||||
// periodicPayment until the last scheduled payment, but if it ever is,
|
// periodicPayment until the last scheduled payment, but if it ever is,
|
||||||
@@ -217,8 +218,9 @@ computePaymentComponents(
|
|||||||
totalValueOutstanding - roundedPeriodicPayment)
|
totalValueOutstanding - roundedPeriodicPayment)
|
||||||
return roundedPeriodicPayment;
|
return roundedPeriodicPayment;
|
||||||
// Use the amount that will get principal outstanding as close to
|
// Use the amount that will get principal outstanding as close to
|
||||||
// reference principal as possible.
|
// reference principal as possible, but don't pay more than the rounded
|
||||||
return p;
|
// periodic payment, or we'll end up with negative interest.
|
||||||
|
return std::min(p, roundedPeriodicPayment);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
// if(count($A20), if(AB19 < $B$5, AB19 - Z19, CEILING($B$10-W20, 1)), "")
|
// if(count($A20), if(AB19 < $B$5, AB19 - Z19, CEILING($B$10-W20, 1)), "")
|
||||||
@@ -234,13 +236,10 @@ computePaymentComponents(
|
|||||||
"ripple::detail::computePaymentComponents",
|
"ripple::detail::computePaymentComponents",
|
||||||
"valid rounded interest");
|
"valid rounded interest");
|
||||||
XRPL_ASSERT_PARTS(
|
XRPL_ASSERT_PARTS(
|
||||||
roundedPrincipal >= 0 && roundedPrincipal <= principalOutstanding,
|
roundedPrincipal >= 0 && roundedPrincipal <= principalOutstanding &&
|
||||||
|
isRounded(asset, roundedPrincipal, scale),
|
||||||
"ripple::detail::computePaymentComponents",
|
"ripple::detail::computePaymentComponents",
|
||||||
"valid rounded principal");
|
"valid rounded principal");
|
||||||
XRPL_ASSERT_PARTS(
|
|
||||||
isRounded(asset, roundedPrincipal, scale),
|
|
||||||
"ripple::detail::computePaymentComponents",
|
|
||||||
"principal is rounded");
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
.rawInterest = rawInterest,
|
.rawInterest = rawInterest,
|
||||||
|
|||||||
Reference in New Issue
Block a user