@@ -620,10 +620,117 @@ class LendingHelpers_test : public beast::unit_test::suite
620620 }
621621 }
622622
623+ void
624+ testTryOverpaymentValueChange ()
625+ {
626+ // This test ensures that overpayment value change is computed
627+ // correctly. I am sorry, this unit test will be a pain in the ass.
628+ testcase (" tryOverpay - Value Change is the decrease in interest" );
629+
630+ using namespace jtx ;
631+ using namespace ripple ::detail;
632+
633+ Env env{*this };
634+ Account const issuer{" issuer" };
635+ PrettyAsset const asset = issuer[" USD" ];
636+
637+ // Interest delta is 40 (100 - 50 - 10)
638+ ExtendedPaymentComponents const overpaymentComponents = {
639+ PaymentComponents{
640+ .trackedValueDelta = Number{50 , 0 },
641+ .trackedPrincipalDelta = Number{50 , 0 },
642+ .trackedManagementFeeDelta = Number{0 , 0 },
643+ .specialCase = PaymentSpecialCase::extra,
644+ },
645+ numZero,
646+ numZero,
647+ };
648+
649+ TenthBips16 managementFeeRate{20'000 }; // 10%
650+ TenthBips32 loanInterestRate{10'000 }; // 20%
651+ Number loanPrincipal{1'000 };
652+ std::uint32_t paymentInterval = 30 * 24 * 60 * 60 ;
653+ std::uint32_t paymentsRemaining = 10 ;
654+ std::int32_t loanScale = -5 ;
655+ auto const periodicRate =
656+ loanPeriodicRate (loanInterestRate, paymentInterval);
657+
658+ auto loanProperites = computeLoanProperties (
659+ asset,
660+ loanPrincipal,
661+ loanInterestRate,
662+ paymentInterval,
663+ paymentsRemaining,
664+ managementFeeRate,
665+ loanScale);
666+ std::cout << loanProperites.periodicPayment << std::endl;
667+ std::cout << loanProperites.loanState .valueOutstanding << std::endl;
668+ std::cout << loanProperites.loanState .interestOutstanding ()
669+ << std::endl;
670+
671+ Number periodicPayment = loanProperites.periodicPayment ;
672+
673+ auto const ret = tryOverpayment (
674+ asset,
675+ loanScale,
676+ overpaymentComponents,
677+ loanProperites.loanState ,
678+ periodicPayment,
679+ periodicRate,
680+ paymentsRemaining,
681+ managementFeeRate,
682+ env.journal );
683+
684+ BEAST_EXPECT (ret);
685+
686+ auto const & [actualPaymentParts, newLoanProperties] = *ret;
687+ auto const newState = newLoanProperties.loanState ;
688+
689+ // value change should be equal to interest decrease
690+ BEAST_EXPECTS (
691+ actualPaymentParts.valueChange ==
692+ newState.interestDue - loanProperites.loanState .interestDue ,
693+ " valueChange mismatch: expected " +
694+ to_string (
695+ newState.interestDue -
696+ loanProperites.loanState .interestDue ) +
697+ " , got " + to_string (actualPaymentParts.valueChange ));
698+
699+ BEAST_EXPECTS (
700+ actualPaymentParts.feePaid ==
701+ loanProperites.loanState .managementFeeDue -
702+ newState.managementFeeDue ,
703+ " feePaid mismatch: expected " +
704+ to_string (
705+ loanProperites.loanState .managementFeeDue -
706+ newState.managementFeeDue ) +
707+ " , got " + to_string (actualPaymentParts.feePaid ));
708+
709+ BEAST_EXPECTS (
710+ actualPaymentParts.principalPaid ==
711+ loanProperites.loanState .principalOutstanding -
712+ newState.principalOutstanding ,
713+ " principalPaid mismatch: expected " +
714+ to_string (
715+ loanProperites.loanState .principalOutstanding -
716+ newState.principalOutstanding ) +
717+ " , got " + to_string (actualPaymentParts.principalPaid ));
718+
719+ BEAST_EXPECTS (
720+ actualPaymentParts.interestPaid ==
721+ loanProperites.loanState .interestDue - newState.interestDue ,
722+ " interestPaid mismatch: expected " +
723+ to_string (
724+ loanProperites.loanState .interestDue -
725+ newState.interestDue ) +
726+ " , got " + to_string (actualPaymentParts.interestPaid ));
727+ }
728+
623729public:
624730 void
625731 run () override
626732 {
733+ testTryOverpaymentValueChange ();
627734 testComputeFullPaymentInterest ();
628735 testLoanAccruedInterest ();
629736 testLoanLatePaymentInterest ();
0 commit comments