mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-02 07:10:34 +00:00
Replace the per-transactor `if (!useDust)` gate around
`associateAsset(*vaultSle, asset)` and the pre-truncation
`- split.receiver->dustDelta` compensation in the dust-aware
Vault writes with a metadata-driven exemption on sfAssetsTotal
itself. Under featureLendingProtocolV1_1, sfAssetsTotal now
retains full Number (19-digit) precision instead of being
truncated to STAmount (16-digit) precision at end of transactor,
so it can absorb the same sub-quantum residual that sfDust
absorbs on the custody line. The receivable invariant becomes
`sfAssetsTotal − (sfAssetsAvailable + custodyLine.sfDust) =
Σ PrincipalOutstanding`, which reduces to the classic form
pre-amendment (dust always zero) and holds byte-for-byte across
arbitrarily long dust-bearing sequences post-amendment.
Design (no signature changes, no plumbing at any of the ~19
associateAsset call sites):
- Introduce `SField::kSmdAssetPreLend11 = 0x100`, semantically
"swept only when featureLendingProtocolV1_1 is not enabled."
- Retag sfAssetsTotal from `kSmdNeedsAsset | kSmdDefault` to
`kSmdAssetPreLend11 | kSmdDefault`. sfAssetsAvailable,
sfAssetsMaximum, sfLossUnrealized keep kSmdNeedsAsset.
- `associateAsset(SLE&, Asset const&)` gate becomes the union
`kSmdNeedsAsset || (kSmdAssetPreLend11 &&
!isFeatureEnabled(featureLendingProtocolV1_1))`, read from the
thread-local CurrentTransactionRulesGuard. No rules installed
→ returns false → sweep runs (safe legacy behavior).
- Widen the Debug-only sanity assertion in
`STNumber::associateAsset` to accept either bit. The
serialisation-path check at STNumber::add remains keyed on
kSmdNeedsAsset only — that is what keeps sfAssetsTotal at full
precision on the wire post-amendment.
Consequences:
- addVaultAssets: `sfAssetsTotal += Number{valueDelta}` (no
`- dustDelta` compensation).
- reconcileSenderDust: only sfAssetsAvailable moves on a
sender-leg dust reshuffle; sfAssetsTotal is unchanged because
the underlying quantity on the custody line is unchanged.
- LoanPay: unconditional `associateAsset(*vaultSle, asset)`; the
20-line docblock explaining the local skip is gone.
- VaultInvariant: sfAssetsTotal delta comparisons in the
deposit / withdraw / clawback branches now use the extended
delta `delta + dustDelta`. Pre-amendment dustDelta is always
zero, so the check reduces to the classic form there.
Tests:
- New src/tests/libxrpl/protocol/STTakesAsset.cpp — 6 targeted
gtest cases covering the sweep for (kSmdNeedsAsset-only,
kSmdAssetPreLend11-only, both, neither) × (rules on, rules
off, no rules installed).
- Existing Vault/Loan suites re-baselined to the dust-inclusive
invariant via `readVaultDust()`; the shared VaultRounding_test
fixtures now degrade cleanly to the classic RED contract on
the base branch where readVaultDust() returns zero.