refactor: extract IOUAmount exponent bounds check into a helper

The exponent bounds check appeared verbatim in both normalize() and
IOUAmount(Number const&). Extract it into a private
enforceExponentBounds() and call it from both.

Named "enforce" rather than "check" because the function acts on the
value as well as inspecting it: it throws above the range and truncates
to zero below it. That matches the codebase precedent of requireAuth
(a pure predicate) versus enforceMPTokenAuthorization (which mutates).

Defined out of line because a header inline would need STAmount's
offset constants, and STAmount.h already includes IOUAmount.h.

No behavior change: the extracted body is identical to both original
blocks, and the Number constructor still applies it after delegating
construction completes.
This commit is contained in:
Pratik Mankawde
2026-07-29 13:11:51 +01:00
parent b292d11797
commit 54e052d8bb
2 changed files with 30 additions and 18 deletions

View File

@@ -40,6 +40,20 @@ private:
void
normalize();
/**
* Constrains the exponent to IOUAmount's range, which is narrower than
* the one Number normalization enforces.
*
* The two ends are deliberately asymmetric, matching the class contract:
* an exponent above the range is unrepresentable and throws, while one
* below it is a silent underflow that truncates the amount to zero.
*
* @throws std::overflow_error if the exponent exceeds the largest
* representable IOU exponent.
*/
void
enforceExponentBounds();
static IOUAmount
fromNumber(Number const& number);

View File

@@ -43,19 +43,8 @@ IOUAmount::minPositiveAmount()
}
void
IOUAmount::normalize()
IOUAmount::enforceExponentBounds()
{
if (mantissa_ == 0)
{
*this = beast::kZero;
return;
}
std::tie(mantissa_, exponent_) =
Number::normalizeToRange<kMinMantissa, kMaxMantissa>(mantissa_, exponent_);
// normalizeToRange only enforces Number's much wider exponent bounds.
// Re-apply IOUAmount's narrower range here, matching the check
// IOUAmount(Number const&) applies on its own construction path.
if (exponent_ > kMaxExponent)
{
Throw<std::overflow_error>("value overflow");
@@ -66,16 +55,25 @@ IOUAmount::normalize()
}
}
IOUAmount::IOUAmount(Number const& other) : IOUAmount(fromNumber(other))
void
IOUAmount::normalize()
{
if (exponent_ > kMaxExponent)
{
Throw<std::overflow_error>("value overflow");
}
if (exponent_ < kMinExponent)
if (mantissa_ == 0)
{
*this = beast::kZero;
return;
}
std::tie(mantissa_, exponent_) =
Number::normalizeToRange<kMinMantissa, kMaxMantissa>(mantissa_, exponent_);
// normalizeToRange only enforces Number's much wider exponent bounds, so
// IOUAmount's narrower range still has to be applied on top.
enforceExponentBounds();
}
IOUAmount::IOUAmount(Number const& other) : IOUAmount(fromNumber(other))
{
enforceExponentBounds();
}
IOUAmount&