From 77296557bcbe433e290b2c331c55e32d33c2a318 Mon Sep 17 00:00:00 2001 From: Vito <5780819+Tapanito@users.noreply.github.com> Date: Tue, 13 Oct 2026 14:14:22 +0200 Subject: [PATCH] fix: Reject out-of-range values in isOnVaultBaseGrid Check isRepresentable before building an STAmount, so an out-of-range user-supplied value is rejected in preclaim instead of throwing. --- include/xrpl/ledger/helpers/VaultHelpers.h | 3 ++- src/libxrpl/ledger/helpers/VaultHelpers.cpp | 4 +++- src/tests/libxrpl/protocol/VaultGridTests.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/xrpl/ledger/helpers/VaultHelpers.h b/include/xrpl/ledger/helpers/VaultHelpers.h index 17f7f6e300..c9074f8d47 100644 --- a/include/xrpl/ledger/helpers/VaultHelpers.h +++ b/include/xrpl/ledger/helpers/VaultHelpers.h @@ -320,7 +320,8 @@ vaultBaseScale(Asset const& asset, std::uint8_t scale); /** * Returns true iff value is exactly representable both as an STAmount of * asset and on the base grid at baseScale (no precision lost rounding - * TowardsZero at baseScale). Shared representability check for + * TowardsZero at baseScale). Returns false, rather than throwing, for a value + * out of range for the asset. Shared representability check for * VaultCreate::preclaim, VaultSet::preclaim and LoanBrokerSet::preclaim's * AssetsMaximum / DebtMaximum / cover-rate field checks. * diff --git a/src/libxrpl/ledger/helpers/VaultHelpers.cpp b/src/libxrpl/ledger/helpers/VaultHelpers.cpp index f967ecf77d..947e5efe76 100644 --- a/src/libxrpl/ledger/helpers/VaultHelpers.cpp +++ b/src/libxrpl/ledger/helpers/VaultHelpers.cpp @@ -569,7 +569,9 @@ vaultBaseScale(Asset const& asset, std::uint8_t scale) [[nodiscard]] bool isOnVaultBaseGrid(Asset const& asset, Number const& value, int baseScale) { - return STAmount{asset, value} == value && + // isRepresentable first: building an STAmount from an out-of-range value + // throws, and this checks user-supplied values in preclaim. + return isRepresentable(asset, value) && STAmount{asset, value} == value && roundToAsset(asset, value, baseScale, Number::RoundingMode::TowardsZero) == value; } diff --git a/src/tests/libxrpl/protocol/VaultGridTests.cpp b/src/tests/libxrpl/protocol/VaultGridTests.cpp index 4e947f4592..db6e31f58e 100644 --- a/src/tests/libxrpl/protocol/VaultGridTests.cpp +++ b/src/tests/libxrpl/protocol/VaultGridTests.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -242,6 +243,11 @@ TEST(VaultGrid, is_on_vault_base_grid) EXPECT_EQ(vaultBaseScale(xrpIssue(), 6), 0); EXPECT_TRUE(isOnVaultBaseGrid(xrpIssue(), Number{7}, 0)); + + // Out of range for the asset: rejected instead of throwing. + EXPECT_FALSE(isOnVaultBaseGrid( + xrpIssue(), Number{static_cast(STAmount::kMaxNativeN)} + 1, 0)); + EXPECT_FALSE(isOnVaultBaseGrid(iou, Number{1, 100}, baseScale)); } TEST(VaultGrid, clamp_vault_outflow)