Packages versions
main branch, crates/rust-client
Bug description
In tokens_to_base_units (crates/rust-client/src/utils.rs), each numeric part is validated independently via u64::parse, but then the parts are concatenated and re-parsed as a combined string:
// Early validation each part checked independently
for part in &parts {
part.parse::<u64>().map_err(TokenParseError::ParseU64)?;
}
// ...later...
let combined = format!("{}{}", integer_part, &fractional_part[0..n_decimals.into()]);
let units = combined.parse::<u64>().map_err(TokenParseError::ParseU64)?;
The combined string can overflow u64 even when both parts individually fit. For example:
integer_part = "18446744073" (valid u64)
fractional_part = "709551616" with n_decimals = 9
- Combined:
"18446744073709551616" = u64::MAX + 1 → parse fails
The error returned is TokenParseError::ParseU64("invalid digit found in string") or similar not a meaningful "amount too large" message. The early per-part validation gives false confidence and is a latent refactoring hazard: if someone trusts the early check and removes the late parse::<u64>(), combined overflow would pass silently.
Affected: crates/rust-client/src/utils.rs, tokens_to_base_units.
How can this be reproduced?
Call tokens_to_base_units("18446744073.709551616", 9). Both parts parse as valid u64 individually, but the combined value exceeds u64::MAX. The function returns Err(TokenParseError::ParseU64(...)) with a misleading message instead of a clear overflow error.
Fix: remove the redundant per-part pre-validation loop and add a dedicated overflow check after the combined parse, returning a descriptive TokenParseError::AmountTooLarge (or similar) variant.
Relevant log output
Packages versions
main branch, crates/rust-client
Bug description
In
tokens_to_base_units(crates/rust-client/src/utils.rs), each numeric part is validated independently viau64::parse, but then the parts are concatenated and re-parsed as a combined string:The combined string can overflow
u64even when both parts individually fit. For example:integer_part = "18446744073"(valid u64)fractional_part = "709551616"withn_decimals = 9"18446744073709551616"=u64::MAX + 1→ parse failsThe error returned is
TokenParseError::ParseU64("invalid digit found in string")or similar not a meaningful "amount too large" message. The early per-part validation gives false confidence and is a latent refactoring hazard: if someone trusts the early check and removes the lateparse::<u64>(), combined overflow would pass silently.Affected:
crates/rust-client/src/utils.rs,tokens_to_base_units.How can this be reproduced?
Call
tokens_to_base_units("18446744073.709551616", 9). Both parts parse as valid u64 individually, but the combined value exceeds u64::MAX. The function returnsErr(TokenParseError::ParseU64(...))with a misleading message instead of a clear overflow error.Fix: remove the redundant per-part pre-validation loop and add a dedicated overflow check after the combined parse, returning a descriptive
TokenParseError::AmountTooLarge(or similar) variant.Relevant log output