Skip to content

Commit ecfbf80

Browse files
committed
Fix handling of AssetsAvailable in Clawback
1 parent 09190db commit ecfbf80

File tree

4 files changed

+25
-12
lines changed

4 files changed

+25
-12
lines changed

src/xrpld/app/tx/detail/VaultClawback.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,27 @@ VaultClawback::doApply()
195195
}
196196

197197
// Clamp to maximum.
198-
Number maxAssets = *vault->at(sfAssetsAvailable);
199-
if (assets > maxAssets)
198+
Number const assetsAvailable = *vault->at(sfAssetsAvailable);
199+
if (assets > assetsAvailable)
200200
{
201-
assets = maxAssets;
202-
shares = assetsToSharesWithdraw(vault, sleIssuance, assets);
203-
assets = std::min<Number>(
204-
sharesToAssetsWithdraw(vault, sleIssuance, shares),
205-
maxAssets);
201+
assets = assetsAvailable;
202+
// Note, it is important to truncate the number of shares, since
203+
// otherwise the corresponding assets might breach the AssetsAvailable
204+
shares = assetsToSharesWithdraw(
205+
vault, sleIssuance, assets, TruncateShares::yes);
206+
assets = sharesToAssetsWithdraw(vault, sleIssuance, shares);
207+
if (assets > assetsAvailable)
208+
{
209+
// LCOV_EXCL_START
210+
JLOG(j_.error()) << "VaultClawback: invalid rounding of shares.";
211+
return tefINTERNAL;
212+
// LCOV_EXCL_STOP
213+
}
206214
}
207215

208216
if (shares == beast::zero)
209217
return tecINSUFFICIENT_FUNDS;
210218

211-
// As per calculation in assetsToSharesWithdraw and sharesToAssetsWithdraw
212219
auto const sharesOutstanding = sleIssuance->at(sfOutstandingAmount);
213220
if (vaultAsset.holds<Issue>() && !vaultAsset.get<Issue>().native() &&
214221
Number(sharesOutstanding) == shares)

src/xrpld/app/tx/detail/VaultWithdraw.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ VaultWithdraw::doApply()
226226
return tecINSUFFICIENT_FUNDS;
227227
}
228228

229-
// As per calculation in assetsToSharesWithdraw and sharesToAssetsWithdraw
230229
auto const sharesOutstanding = sleIssuance->at(sfOutstandingAmount);
231230
if (vaultAsset.holds<Issue>() && !vaultAsset.get<Issue>().native() &&
232231
Number(sharesOutstanding) == shares)

src/xrpld/ledger/View.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,14 +930,17 @@ sharesToAssetsDeposit(
930930
std::shared_ptr<SLE const> const& issuance,
931931
STAmount const& shares);
932932

933+
enum class TruncateShares : bool { no = false, yes = true };
934+
933935
// From the perspective of a vault,
934936
// return the number of shares to demand from the depositor
935937
// when they ask to withdraw a fixed amount of assets.
936938
[[nodiscard]] STAmount
937939
assetsToSharesWithdraw(
938940
std::shared_ptr<SLE const> const& vault,
939941
std::shared_ptr<SLE const> const& issuance,
940-
STAmount const& assets);
942+
STAmount const& assets,
943+
TruncateShares truncate = TruncateShares::no);
941944

942945
// From the perspective of a vault,
943946
// return the number of assets to give the depositor

src/xrpld/ledger/detail/View.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,7 +2849,8 @@ sharesToAssetsDeposit(
28492849
assetsToSharesWithdraw(
28502850
std::shared_ptr<SLE const> const& vault,
28512851
std::shared_ptr<SLE const> const& issuance,
2852-
STAmount const& assets)
2852+
STAmount const& assets,
2853+
TruncateShares truncate)
28532854
{
28542855
XRPL_ASSERT(
28552856
assets.asset() == vault->at(sfAsset),
@@ -2860,7 +2861,10 @@ assetsToSharesWithdraw(
28602861
if (assetTotal == 0)
28612862
return shares;
28622863
Number shareTotal = issuance->at(sfOutstandingAmount);
2863-
shares = shareTotal * (assets / assetTotal);
2864+
Number result = shareTotal * (assets / assetTotal);
2865+
if (truncate == TruncateShares::yes)
2866+
result = result.truncate();
2867+
shares = result;
28642868
return shares;
28652869
}
28662870

0 commit comments

Comments
 (0)