Review feedback from @shawnxie999: even more rounding

- Round the initial total value computation upward, unless there is
  0-interest.
- Rename getVaultScale to getAssetsTotalScale, and convert one incorrect
  computation to use it.
- Use adjustImpreciseNumber for LossUnrealized.
- Add some logging to computeLoanProperties.
This commit is contained in:
Ed Hennis
2025-12-05 21:04:53 -05:00
parent b02b700532
commit af43572ee5
9 changed files with 94 additions and 42 deletions

View File

@@ -141,7 +141,7 @@ protected:
using namespace jtx;
auto const vaultSle = env.le(keylet::vault(vaultID));
return getVaultScale(vaultSle);
return getAssetsTotalScale(vaultSle);
}
};
@@ -551,12 +551,15 @@ protected:
broker.vaultScale(env),
state.principalOutstanding.exponent())));
BEAST_EXPECT(state.paymentInterval == 600);
BEAST_EXPECT(
state.totalValue ==
roundToAsset(
broker.asset,
state.periodicPayment * state.paymentRemaining,
state.loanScale));
{
NumberRoundModeGuard mg(Number::upward);
BEAST_EXPECT(
state.totalValue ==
roundToAsset(
broker.asset,
state.periodicPayment * state.paymentRemaining,
state.loanScale));
}
BEAST_EXPECT(
state.managementFeeOutstanding ==
computeManagementFee(
@@ -697,7 +700,8 @@ protected:
interval,
total,
feeRate,
asset(brokerParams.vaultDeposit).number().exponent());
asset(brokerParams.vaultDeposit).number().exponent(),
env.journal);
log << "Loan properties:\n"
<< "\tPrincipal: " << principal << std::endl
<< "\tInterest rate: " << interest << std::endl
@@ -1477,7 +1481,8 @@ protected:
state.paymentInterval,
state.paymentRemaining,
broker.params.managementFeeRate,
state.loanScale);
state.loanScale,
env.journal);
verifyLoanStatus(
0,
@@ -2448,13 +2453,18 @@ protected:
// Make all the payments in one transaction
// service fee is 2
auto const startingPayments = state.paymentRemaining;
auto const rawPayoff = startingPayments *
(state.periodicPayment + broker.asset(2).value());
STAmount const payoffAmount{broker.asset, rawPayoff};
BEAST_EXPECT(
payoffAmount ==
broker.asset(Number(1024014840139457, -12)));
BEAST_EXPECT(payoffAmount > state.principalOutstanding);
STAmount const payoffAmount = [&]() {
NumberRoundModeGuard mg(Number::upward);
auto const rawPayoff = startingPayments *
(state.periodicPayment + broker.asset(2).value());
STAmount const payoffAmount{broker.asset, rawPayoff};
BEAST_EXPECTS(
payoffAmount ==
broker.asset(Number(1024014840139457, -12)),
to_string(payoffAmount));
BEAST_EXPECT(payoffAmount > state.principalOutstanding);
return payoffAmount;
}();
singlePayment(
loanKeylet,
@@ -4009,7 +4019,7 @@ protected:
createJson = env.json(createJson, sig(sfCounterpartySignature, lender));
// Fails in preclaim because principal requested can't be
// represented as XRP
env(createJson, ter(tecPRECISION_LOSS));
env(createJson, ter(tecPRECISION_LOSS), THISLINE);
env.close();
BEAST_EXPECT(!env.le(keylet));
@@ -4021,7 +4031,7 @@ protected:
createJson = env.json(createJson, sig(sfCounterpartySignature, lender));
// Fails in doApply because the payment is too small to be
// represented as XRP.
env(createJson, ter(tecPRECISION_LOSS));
env(createJson, ter(tecPRECISION_LOSS), THISLINE);
env.close();
}
@@ -4996,7 +5006,7 @@ protected:
auto const keylet = keylet::loan(broker.brokerID, loanSequence);
createJson = env.json(createJson, sig(sfCounterpartySignature, lender));
env(createJson, ter(tecPRECISION_LOSS));
env(createJson, ter(tecPRECISION_LOSS), THISLINE);
env.close(startDate);
auto loanPayTx = env.json(