mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
fixes overpayment interest calculation
This commit is contained in:
74
src/test/app/LendingHelpers_test.cpp
Normal file
74
src/test/app/LendingHelpers_test.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include <xrpl/beast/unit_test/suite.h>
|
||||||
|
//
|
||||||
|
#include <test/jtx.h>
|
||||||
|
#include <test/jtx/mpt.h>
|
||||||
|
|
||||||
|
#include <xrpld/app/misc/LendingHelpers.h>
|
||||||
|
#include <xrpld/app/misc/LoadFeeTrack.h>
|
||||||
|
#include <xrpld/app/tx/detail/Batch.h>
|
||||||
|
#include <xrpld/app/tx/detail/LoanSet.h>
|
||||||
|
|
||||||
|
#include <xrpl/beast/xor_shift_engine.h>
|
||||||
|
#include <xrpl/protocol/SField.h>
|
||||||
|
|
||||||
|
#include "test/jtx/amount.h"
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
class LendingHelpers_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
void
|
||||||
|
testComputeOverpaymentComponents()
|
||||||
|
{
|
||||||
|
testcase("computeOverpaymentComponents");
|
||||||
|
using namespace jtx;
|
||||||
|
using namespace ripple::detail;
|
||||||
|
|
||||||
|
Account const issuer{"issuer"};
|
||||||
|
PrettyAsset const IOU = issuer["IOU"];
|
||||||
|
int32_t const loanScale = 1;
|
||||||
|
auto const overpayment = Number{1'000};
|
||||||
|
auto const overpaymentInterestRate = TenthBips32{10'000}; // 10%
|
||||||
|
auto const overpaymentFeeRate = TenthBips32{10'000}; // 10%
|
||||||
|
auto const managementFeeRate = TenthBips16{10'000}; // 10%
|
||||||
|
|
||||||
|
auto const expectedOverpaymentFee = Number{100}; // 10% of 1,000
|
||||||
|
auto const expectedOverpaymentInterestGross =
|
||||||
|
Number{100}; // 10% of 1,000
|
||||||
|
auto const expectedOverpaymentInterestNet =
|
||||||
|
Number{90}; // 100 - 10% of 100
|
||||||
|
auto const expectedOverpaymentManagementFee = Number{10}; // 10% of
|
||||||
|
auto const expectedPrincipalPortion = Number{800}; // 1,000 - 100 - 100
|
||||||
|
|
||||||
|
auto const components = detail::computeOverpaymentComponents(
|
||||||
|
IOU,
|
||||||
|
loanScale,
|
||||||
|
overpayment,
|
||||||
|
overpaymentInterestRate,
|
||||||
|
overpaymentFeeRate,
|
||||||
|
managementFeeRate);
|
||||||
|
|
||||||
|
BEAST_EXPECT(
|
||||||
|
components.untrackedManagementFee == expectedOverpaymentFee);
|
||||||
|
BEAST_EXPECT(
|
||||||
|
components.untrackedInterest == expectedOverpaymentInterestNet);
|
||||||
|
BEAST_EXPECT(
|
||||||
|
components.trackedManagementFeeDelta ==
|
||||||
|
expectedOverpaymentManagementFee);
|
||||||
|
BEAST_EXPECT(
|
||||||
|
components.trackedPrincipalDelta == expectedPrincipalPortion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
testComputeOverpaymentComponents();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(LendingHelpers, app, ripple);
|
||||||
|
|
||||||
|
} // namespace test
|
||||||
|
} // namespace ripple
|
||||||
@@ -387,6 +387,20 @@ struct LoanStateDeltas
|
|||||||
nonNegative();
|
nonNegative();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::pair<Number, Number>
|
||||||
|
computeInterestAndFeeParts(
|
||||||
|
Number const& interest,
|
||||||
|
TenthBips16 managementFeeRate);
|
||||||
|
|
||||||
|
ExtendedPaymentComponents
|
||||||
|
computeOverpaymentComponents(
|
||||||
|
Asset const& asset,
|
||||||
|
int32_t const loanScale,
|
||||||
|
Number const& overpayment,
|
||||||
|
TenthBips32 const overpaymentInterestRate,
|
||||||
|
TenthBips32 const overpaymentFeeRate,
|
||||||
|
TenthBips16 const managementFeeRate);
|
||||||
|
|
||||||
PaymentComponents
|
PaymentComponents
|
||||||
computePaymentComponents(
|
computePaymentComponents(
|
||||||
Asset const& asset,
|
Asset const& asset,
|
||||||
|
|||||||
@@ -1225,19 +1225,14 @@ computeOverpaymentComponents(
|
|||||||
// This interest doesn't follow the normal amortization schedule - it's
|
// This interest doesn't follow the normal amortization schedule - it's
|
||||||
// a one-time charge for paying early.
|
// a one-time charge for paying early.
|
||||||
// Equation (20) and (21) from XLS-66 spec, Section A-2 Equation Glossary
|
// Equation (20) and (21) from XLS-66 spec, Section A-2 Equation Glossary
|
||||||
auto const [rawOverpaymentInterest, _] = [&]() {
|
|
||||||
Number const interest =
|
|
||||||
tenthBipsOfValue(overpayment, overpaymentInterestRate);
|
|
||||||
return detail::computeInterestAndFeeParts(interest, managementFeeRate);
|
|
||||||
}();
|
|
||||||
|
|
||||||
// Round the penalty interest components to the loan scale
|
|
||||||
auto const [roundedOverpaymentInterest, roundedOverpaymentManagementFee] =
|
auto const [roundedOverpaymentInterest, roundedOverpaymentManagementFee] =
|
||||||
[&]() {
|
[&]() {
|
||||||
Number const interest =
|
auto const interest = roundToAsset(
|
||||||
roundToAsset(asset, rawOverpaymentInterest, loanScale);
|
asset,
|
||||||
|
tenthBipsOfValue(overpayment, overpaymentInterestRate),
|
||||||
|
loanScale);
|
||||||
return detail::computeInterestAndFeeParts(
|
return detail::computeInterestAndFeeParts(
|
||||||
asset, interest, managementFeeRate, loanScale);
|
interest, managementFeeRate);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto const result = detail::ExtendedPaymentComponents{
|
auto const result = detail::ExtendedPaymentComponents{
|
||||||
|
|||||||
Reference in New Issue
Block a user