-
Notifications
You must be signed in to change notification settings - Fork 129
fix(utils): return AmountTooLarge instead of ParseU64 on u64 overflow #2506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from 3 commits
5a482ac
7bc582c
fccd2bb
37f4b9e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,8 @@ pub enum TokenParseError { | |
| ParseU64(#[source] ParseIntError), | ||
| #[error("Amount has more than {0} decimal places")] | ||
| TooManyDecimals(u8), | ||
| #[error("Amount is too large to fit in a u64")] | ||
| AmountTooLarge, | ||
| #[error("Amount is not a valid asset amount")] | ||
| InvalidAmount(#[source] AssetError), | ||
| } | ||
|
|
@@ -75,7 +77,9 @@ pub fn tokens_to_base_units( | |
| return Err(TokenParseError::MultipleDecimalPoints); | ||
| } | ||
|
|
||
| // Validate that the parts are valid numbers | ||
| // Validate that the parts contain only valid digits (catches non-numeric chars). | ||
| // Note: each part is validated individually, so a large combined value is NOT | ||
| // caught here — that case is handled by the AmountTooLarge error below. | ||
| for part in &parts { | ||
| part.parse::<u64>().map_err(TokenParseError::ParseU64)?; | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This still reports overflow as |
||
|
|
@@ -103,8 +107,10 @@ pub fn tokens_to_base_units( | |
| // Combine the integer and padded fractional part | ||
| let combined = format!("{}{}", integer_part, &fractional_part[0..n_decimals.into()]); | ||
|
|
||
| // Convert the combined string to an integer | ||
| let units = combined.parse::<u64>().map_err(TokenParseError::ParseU64)?; | ||
| // Convert the combined string to an integer; a parse failure here means the | ||
| // combined value overflows u64, not that it contains invalid digits (those | ||
| // are already caught by the split/trim logic above). | ||
| let units = combined.parse::<u64>().map_err(|_| TokenParseError::AmountTooLarge)?; | ||
|
|
||
| AssetAmount::new(units).map_err(TokenParseError::InvalidAmount) | ||
| } | ||
|
|
@@ -147,6 +153,13 @@ mod tests { | |
| tokens_to_base_units("18446744.073709551615", 12), | ||
| Err(TokenParseError::InvalidAmount(_)) | ||
| ),); | ||
| // Combined string overflows u64 entirely — must return AmountTooLarge, | ||
| // not a confusing ParseU64 error. | ||
| // "184467440737095516.16" with 2 decimals → "18446744073709551616" = u64::MAX + 1 | ||
| assert!(matches!( | ||
| tokens_to_base_units("184467440737095516.16", 2), | ||
| Err(TokenParseError::AmountTooLarge) | ||
| )); | ||
| } | ||
|
|
||
| #[test] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would avoid mentioning
u64here and instead we should just say the amount is too large.InvalidAmountalready covers the asset amount not being representableThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't fully get why we would need to add this error type, considering
ParseU64(#[source] ParseIntError)already has in its inner error the specifics of the failure (overflow in this case). If we are to add it because we don't want the user to seeu64then we should take the extra effort and removeParseU64altogether.