mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-28 15:58:07 +00:00
fix: Clamp Vault Deposit, Withdraw, and Clawback to assetsTotal grid
sfAssetsTotal is stored on a coarser STAmount grid than sfAssetsAvailable and the vault's trust line, so adding the same amount to all three quantizes differently on each and leaves the vault's books disagreeing with its actual holdings by a sub-ULP amount. Fix by clamping the credited/withdrawn amount to what sfAssetsTotal can represent before applying it to the other rails, via a shared clampToAssetsTotalScale helper used by all three transactors. - Deposit: clamp assetsDeposited downward to the assetsTotal grid, then re-derive shares from the clamped amount so the depositor cannot receive shares worth more than they paid. Return tecPRECISION_LOSS if the clamp rounds the deposit to zero. - Withdraw: clamp assetsWithdrawn upward (i.e. the vault pays out slightly less) so it never pays out more than it can account for. Shares are not re-derived, so the withdrawer receives slightly less per share, favouring remaining holders. - Clawback: same pattern as withdraw, guarded on assetsRecovered > 0 and placed after the existing clamp-to-available. Gated on fixCleanup3_4_0.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
@@ -41,6 +42,27 @@ assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount co
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares);
|
||||
|
||||
/**
|
||||
* Clamps `delta` (positive when crediting the vault, negative when debiting
|
||||
* it) to the largest magnitude that changes sfAssetsTotal by an exact
|
||||
* multiple of its own STAmount grid step, rounding in `mode`. The returned
|
||||
* delta has the same sign convention as `delta` (i.e. this is a magnitude
|
||||
* adjustment toward zero, never away from it). Applying the returned delta
|
||||
* to both sfAssetsTotal and any other field derived from the same raw amount
|
||||
* (e.g. sfAssetsAvailable) keeps them exactly in sync, since those fields'
|
||||
* scale is always at least as fine as sfAssetsTotal's.
|
||||
*
|
||||
* @param vault The vault SLE (mutable, since sfAssetsTotal is read through a
|
||||
* non-const field proxy).
|
||||
* @param delta The signed amount by which sfAssetsTotal is about to change.
|
||||
* @param mode The rounding mode to apply when quantizing to sfAssetsTotal's
|
||||
* scale.
|
||||
*
|
||||
* @return The clamped delta.
|
||||
*/
|
||||
[[nodiscard]] STAmount
|
||||
clampToAssetsTotalScale(SLE::ref vault, STAmount const& delta, Number::RoundingMode mode);
|
||||
|
||||
/**
|
||||
* Controls whether to truncate shares instead of rounding.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user