mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
fix: Round deposit cover to LoanBroker scale
This commit is contained in:
@@ -39,10 +39,15 @@ canApplyToBrokerCover(
|
||||
beast::Journal j,
|
||||
std::string_view logPrefix)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
sleBroker && sleBroker->getType() == ltLOAN_BROKER,
|
||||
"xrpl::canApplyToBrokerCover : valid LoanBroker sle");
|
||||
XRPL_ASSERT(
|
||||
vaultAsset.getIssuer() == amount.getIssuer() && amount > beast::kZERO,
|
||||
"xrpl::canApplyToBrokerCover : valid LoanBroker sle");
|
||||
|
||||
if (!view.rules().enabled(fixCleanup3_2_0))
|
||||
return tesSUCCESS;
|
||||
if (amount == beast::kZERO)
|
||||
return tesSUCCESS;
|
||||
|
||||
int const coverScale = scale(sleBroker->at(sfCoverAvailable), vaultAsset);
|
||||
if (amount.isZeroAtScale(coverScale))
|
||||
|
||||
@@ -73,11 +73,6 @@ LoanBrokerCoverDeposit::preclaim(PreclaimContext const& ctx)
|
||||
if (amount.asset() != vaultAsset)
|
||||
return tecWRONG_ASSET;
|
||||
|
||||
// Helper handles both IOU and MPT correctly without explicit branching.
|
||||
if (auto const ret = canApplyToBrokerCover(
|
||||
ctx.view, sleBroker, vaultAsset, amount, ctx.j, "LoanBrokerCoverDeposit"))
|
||||
return ret;
|
||||
|
||||
auto const pseudoAccountID = sleBroker->at(sfAccount);
|
||||
// Cannot transfer a non-transferable Asset
|
||||
if (auto const ret = canTransfer(ctx.view, vaultAsset, account, pseudoAccountID))
|
||||
@@ -111,8 +106,6 @@ LoanBrokerCoverDeposit::doApply()
|
||||
auto const& tx = ctx_.tx;
|
||||
|
||||
auto const brokerID = tx[sfLoanBrokerID];
|
||||
auto const amount = tx[sfAmount];
|
||||
|
||||
auto broker = view().peek(keylet::loanbroker(brokerID));
|
||||
if (!broker)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
@@ -122,9 +115,25 @@ LoanBrokerCoverDeposit::doApply()
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const vaultAsset = vault->at(sfAsset);
|
||||
|
||||
auto const brokerPseudoID = broker->at(sfAccount);
|
||||
|
||||
bool const fix320Enabled = view().rules().enabled(fixCleanup3_2_0);
|
||||
auto const amount = [&]() -> STAmount {
|
||||
if (!fix320Enabled)
|
||||
return tx[sfAmount];
|
||||
|
||||
return roundToScale(
|
||||
tx[sfAmount],
|
||||
scale(broker->at(sfCoverAvailable), vaultAsset),
|
||||
Number::RoundingMode::Downward);
|
||||
}();
|
||||
|
||||
if (fix320Enabled && amount == beast::kZERO)
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "LoanBrokerCoverDeposit: deposit amount: " << tx[sfAmount]
|
||||
<< "is zero at loan broker scale";
|
||||
return tecPRECISION_LOSS;
|
||||
}
|
||||
// Transfer assets from depositor to pseudo-account.
|
||||
if (auto ter = accountSend(view(), account_, brokerPseudoID, amount, j_, WaiveTransferFee::Yes))
|
||||
return ter;
|
||||
|
||||
@@ -1896,6 +1896,29 @@ class LoanBroker_test : public beast::unit_test::Suite
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
testcase("Cover precision guard: Deposit");
|
||||
// Both cases succeed; post-fix the amount is rounded DOWN to
|
||||
// cover scale first, so the delta differs from pre-fix
|
||||
// Input: 1.8e-14 IOU (sub-scale at cover scale -14)
|
||||
// Pre-fix: 10 + 1.8e-14 → round-to-nearest →
|
||||
// 10.00000000000002 → delta 2e-14
|
||||
// Post-fix: roundToScale(1.8e-14, -14, Downward) = 1e-14;
|
||||
// 10 + 1e-14 = 10.00000000000001 → delta 1e-14
|
||||
Env env{*this, features};
|
||||
auto const [brokerKeylet, iou] = setup(env);
|
||||
PrettyAmount const subUlpAmt = iou(Number{18, -15});
|
||||
auto const coverBefore = env.le(brokerKeylet)->at(sfCoverAvailable);
|
||||
env(coverDeposit(alice, brokerKeylet.key, subUlpAmt), Ter(tesSUCCESS));
|
||||
env.close();
|
||||
auto const brokerAfter = env.le(brokerKeylet);
|
||||
if (!BEAST_EXPECT(brokerAfter))
|
||||
return;
|
||||
|
||||
Number const delta = features[fixCleanup3_2_0] ? Number{1, -14} : Number{2, -14};
|
||||
BEAST_EXPECT(brokerAfter->at(sfCoverAvailable) - coverBefore == delta);
|
||||
}
|
||||
|
||||
{
|
||||
testcase("Cover precision guard: Withdraw");
|
||||
Env env{*this, features};
|
||||
|
||||
Reference in New Issue
Block a user