Start converting Loans to use fixed payments and track value

- Not expected to build
This commit is contained in:
Ed Hennis
2025-10-01 20:09:48 -04:00
parent d353f4a2e6
commit 63edf035a6
13 changed files with 353 additions and 305 deletions

View File

@@ -66,15 +66,15 @@ public:
static int const cMaxOffset = 80;
// Maximum native value supported by the code
static std::uint64_t const cMinValue = 1000000000000000ull;
static std::uint64_t const cMaxValue = 9999999999999999ull;
static std::uint64_t const cMaxNative = 9000000000000000000ull;
static std::uint64_t const cMinValue = 1'000'000'000'000'000ull;
static std::uint64_t const cMaxValue = 9'999'999'999'999'999ull;
static std::uint64_t const cMaxNative = 9'000'000'000'000'000'000ull;
// Max native value on network.
static std::uint64_t const cMaxNativeN = 100000000000000000ull;
static std::uint64_t const cIssuedCurrency = 0x8000000000000000ull;
static std::uint64_t const cPositive = 0x4000000000000000ull;
static std::uint64_t const cMPToken = 0x2000000000000000ull;
static std::uint64_t const cMaxNativeN = 100'000'000'000'000'000ull;
static std::uint64_t const cIssuedCurrency = 0x8'000'000'000'000'000ull;
static std::uint64_t const cPositive = 0x4'000'000'000'000'000ull;
static std::uint64_t const cMPToken = 0x2'000'000'000'000'000ull;
static std::uint64_t const cValueMask = ~(cPositive | cMPToken);
static std::uint64_t const uRateOne;
@@ -695,21 +695,22 @@ divRoundStrict(
std::uint64_t
getRate(STAmount const& offerOut, STAmount const& offerIn);
/** Round an arbitrary precision Amount to the precision of a reference Amount.
/** Round an arbitrary precision Amount to the precision of an STAmount that has
* a given exponent.
*
* This is used to ensure that calculations involving IOU amounts do not collect
* dust beyond the precision of the reference value.
*
* @param value The value to be rounded
* @param referenceValue A reference value to establish the precision limit of
* `value`. Should be larger than `value`.
* @param scale An exponent value to establish the precision limit of
* `value`. Should be larger than `value.exponent()`.
* @param rounding Optional Number rounding mode
*
*/
STAmount
roundToReference(
STAmount const value,
STAmount referenceValue,
roundToScale(
STAmount value,
std::int32_t scale,
Number::rounding_mode rounding = Number::getround());
/** Round an arbitrary precision Number to the precision of a given Asset.
@@ -720,9 +721,8 @@ roundToReference(
*
* @param asset The relevant asset
* @param value The value to be rounded
* @param referenceValue Only relevant to IOU assets. A reference value to
* establish the precision limit of `value`. Should be larger than
* `value`.
* @param scale Only relevant to IOU assets. An exponent value to establish the
* precision limit of `value`. Should be larger than `value.exponent()`.
* @param rounding Optional Number rounding mode
*/
template <AssetType A>
@@ -730,7 +730,7 @@ Number
roundToAsset(
A const& asset,
Number const& value,
Number const& referenceValue,
std::int32_t scale,
Number::rounding_mode rounding = Number::getround())
{
NumberRoundModeGuard mg(rounding);
@@ -739,7 +739,7 @@ roundToAsset(
return ret;
// Not that the ctor will round integral types (XRP, MPT) via canonicalize,
// so no extra work is needed for those.
return roundToReference(ret, STAmount{asset, referenceValue});
return roundToScale(ret, scale);
}
//------------------------------------------------------------------------------

View File

@@ -548,25 +548,29 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
{sfLoanBrokerID, soeREQUIRED},
{sfLoanSequence, soeREQUIRED},
{sfBorrower, soeREQUIRED},
{sfLoanOriginationFee, soeREQUIRED},
{sfLoanServiceFee, soeREQUIRED},
{sfLatePaymentFee, soeREQUIRED},
{sfClosePaymentFee, soeREQUIRED},
{sfOverpaymentFee, soeREQUIRED},
{sfInterestRate, soeREQUIRED},
{sfLateInterestRate, soeREQUIRED},
{sfCloseInterestRate, soeREQUIRED},
{sfOverpaymentInterestRate, soeREQUIRED},
{sfLoanOriginationFee, soeDEFAULT},
{sfLoanServiceFee, soeDEFAULT},
{sfLatePaymentFee, soeDEFAULT},
{sfClosePaymentFee, soeDEFAULT},
{sfOverpaymentFee, soeDEFAULT},
{sfInterestRate, soeDEFAULT},
{sfLateInterestRate, soeDEFAULT},
{sfCloseInterestRate, soeDEFAULT},
{sfOverpaymentInterestRate, soeDEFAULT},
{sfStartDate, soeREQUIRED},
{sfPaymentInterval, soeREQUIRED},
{sfGracePeriod, soeREQUIRED},
{sfPeriodicPayment, soeREQUIRED},
{sfPreviousPaymentDate, soeREQUIRED},
{sfNextPaymentDueDate, soeREQUIRED},
{sfPaymentRemaining, soeREQUIRED},
{sfPrincipalOutstanding, soeREQUIRED},
// Save the original request amount for rounding / scaling of
// other computations, particularly for IOUs
{sfPrincipalRequested, soeREQUIRED},
{sfTotalValueOutstanding, soeDEFAULT},
// Based on the original principal borrowed, used for
// rounding calculated values so they are all on a
// consistent scale - that is, they all have the same
// number of decimal places after the decimal point.
{sfLoanScale, soeDEFAULT},
}))
#undef EXPAND

View File

@@ -239,12 +239,11 @@ TYPED_SFIELD(sfLatePaymentFee, NUMBER, 11)
TYPED_SFIELD(sfClosePaymentFee, NUMBER, 12)
TYPED_SFIELD(sfPrincipalOutstanding, NUMBER, 13)
TYPED_SFIELD(sfPrincipalRequested, NUMBER, 14)
TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15)
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
// int32
// NOTE: Do not use `sfDummyInt32`. It's so far the only use of INT32
// in this file and has been defined here for test only.
// TODO: Replace `sfDummyInt32` with actually useful field.
TYPED_SFIELD(sfDummyInt32, INT32, 1) // for tests only
TYPED_SFIELD(sfLoanScale, INT32, 1)
// currency amount (common)
TYPED_SFIELD(sfAmount, AMOUNT, 1)