diff --git a/ethers-core/Cargo.toml b/ethers-core/Cargo.toml index 6358c3ae..0a51182c 100644 --- a/ethers-core/Cargo.toml +++ b/ethers-core/Cargo.toml @@ -41,7 +41,7 @@ cargo_metadata = { version = "0.15.0", optional = true } convert_case = { version = "0.5.0", optional = true } syn = { version = "1.0.99", optional = true } proc-macro2 = { version = "1.0.43", optional = true } -rust_decimal = "1.26.1" +rust_decimal = { version = "1.26.1", features = ["maths"] } [dev-dependencies] serde_json = { version = "1.0.64", default-features = false } diff --git a/ethers-core/src/utils/mod.rs b/ethers-core/src/utils/mod.rs index b1cf9ca2..5e3b1c2d 100644 --- a/ethers-core/src/utils/mod.rs +++ b/ethers-core/src/utils/mod.rs @@ -155,9 +155,15 @@ where S: ToString, K: TryInto + Copy, { - use rust_decimal::Decimal; + use rust_decimal::{Decimal, MathematicalOps}; + let num: Decimal = amount.to_string().parse()?; - let multiplier: Decimal = 10u64.pow(units.try_into()?.as_num()).into(); + let exponent = units.try_into()?.as_num(); + + let multiplier = Decimal::TEN + .checked_powu(exponent.into()) + .ok_or(rust_decimal::Error::ExceedsMaximumPossibleValue)?; + let val = num.checked_mul(multiplier).ok_or(rust_decimal::Error::ExceedsMaximumPossibleValue)?; let u256_n: U256 = U256::from_dec_str(&val.round().to_string())?; @@ -441,6 +447,14 @@ mod tests { assert_eq!(eth, "1.005633240123456789"); } + #[test] + fn parse_large_units() { + let decimals = 27u32; + let val = "10.55"; + let unit = parse_units(val, decimals).unwrap(); + assert_eq!(unit.to_string(), "10550000000000000000000000000"); + } + #[test] fn test_parse_units() { let gwei = parse_units(1.5, 9).unwrap();