Use a loan scale of 0 for integral asset types

- Loan scale is completely irrelevant to integral types (XRP, MPT), and
  the field is "soeDEFAULT", so when set to 0, it won't be stored on
  ledger, saving a little bit of space.
This commit is contained in:
Ed Hennis
2025-10-22 17:15:34 -04:00
parent 4aa6baef26
commit 30e2650ff9
2 changed files with 22 additions and 7 deletions

View File

@@ -404,7 +404,10 @@ class Loan_test : public beast::unit_test::suite
BEAST_EXPECT(
state.principalOutstanding == broker.asset(1000).value());
BEAST_EXPECT(
state.principalOutstanding.exponent() == state.loanScale);
state.loanScale ==
(broker.asset.integral()
? 0
: state.principalOutstanding.exponent()));
BEAST_EXPECT(state.paymentInterval == 600);
BEAST_EXPECT(
state.totalValue ==
@@ -636,7 +639,9 @@ class Loan_test : public beast::unit_test::suite
BEAST_EXPECT(
loan->at(sfNextPaymentDueDate) == startDate + interval);
BEAST_EXPECT(loan->at(sfPaymentRemaining) == total);
BEAST_EXPECT(loan->at(sfLoanScale) == principalRequest.exponent());
BEAST_EXPECT(
loan->at(sfLoanScale) ==
(broker.asset.integral() ? 0 : principalRequest.exponent()));
BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == principalRequest);
}
@@ -654,7 +659,7 @@ class Loan_test : public beast::unit_test::suite
0,
startDate + interval,
total,
principalRequest.exponent(),
broker.asset.integral() ? 0 : principalRequest.exponent(),
loanProperties.totalValueOutstanding,
principalRequest,
loanProperties.managementFeeOwedToBroker,
@@ -711,7 +716,7 @@ class Loan_test : public beast::unit_test::suite
0,
nextDueDate,
total,
principalRequest.exponent(),
broker.asset.integral() ? 0 : principalRequest.exponent(),
loanProperties.totalValueOutstanding,
principalRequest,
loanProperties.managementFeeOwedToBroker,
@@ -1196,7 +1201,10 @@ class Loan_test : public beast::unit_test::suite
BEAST_EXPECT(brokerSle))
{
BEAST_EXPECT(
state.loanScale == state.principalOutstanding.exponent());
state.loanScale ==
(broker.asset.integral()
? 0
: state.principalOutstanding.exponent()));
auto const defaultAmount = roundToAsset(
broker.asset,
std::min(
@@ -2166,7 +2174,7 @@ class Loan_test : public beast::unit_test::suite
BEAST_EXPECT(!loan.isMember(sfPreviousPaymentDate));
BEAST_EXPECT(loan[sfPrincipalOutstanding] == "1000000000");
BEAST_EXPECT(loan[sfTotalValueOutstanding] == "1000000000");
BEAST_EXPECT(loan[sfLoanScale] == -6);
BEAST_EXPECT(!loan.isMember(sfLoanScale));
BEAST_EXPECT(
loan[sfStartDate].asUInt() ==
startDate.time_since_epoch().count());

View File

@@ -1158,7 +1158,7 @@ computeLoanProperties(
auto const periodicPayment = detail::loanPeriodicPayment(
principalOutstanding, periodicRate, paymentsRemaining);
Number const totalValueOutstanding = [&]() {
STAmount const totalValueOutstanding = [&]() {
NumberRoundModeGuard mg(Number::to_nearest);
// Use STAmount's internal rounding instead of roundToAsset, because
// we're going to use this result to determine the scale for all the
@@ -1176,6 +1176,13 @@ computeLoanProperties(
// biggest number involved (barring unusual parameters for late, full, or
// over payments)
auto const loanScale = totalValueOutstanding.exponent();
XRPL_ASSERT_PARTS(
totalValueOutstanding.integral() && loanScale == 0 ||
!totalValueOutstanding.integral() &&
loanScale ==
static_cast<Number>(totalValueOutstanding).exponent(),
"ripple::computeLoanProperties",
"loanScale value fits expectations");
// Since we just figured out the loan scale, we haven't been able to
// validate that the principal fits in it, so to allow this function to