Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* Fixes: gakonst#1822

* Fixes: gakonst#1822 :: update1

* Fixes: gakonst#1822 :: Add ParseOverflow err & rm rust_decimals from ethers-core

* update changelog
  • Loading branch information
halo3mic authored and hexiaoyuan committed Nov 9, 2022
1 parent ae2dfad commit c436473
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 27 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Unreleased

- Remove rust_decimals dependency for ethers-core
- Add support for numbers greater than 2^96 for `ethers_core::utils::parse_units` [#1822](https://github.com/gakonst/ethers-rs/issues/1822)
- Add comment about safety of u8 -> u64 cast in `ethers_core::types::Signature`
- Stop defaulting to the `"latest"` block in `eth_estimateGas` params [#1657](https://github.com/gakonst/ethers-rs/pull/1657)
- Fix geth trace types for debug_traceTransaction rpc
Expand Down
12 changes: 0 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion ethers-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ cargo_metadata = { version = "0.15.0", optional = true }
convert_case = { version = "0.6.0", optional = true }
syn = { version = "1.0.103", optional = true }
proc-macro2 = { version = "1.0.47", optional = true }
rust_decimal = { version = "1.26.1", features = ["maths"] }

[dev-dependencies]
serde_json = { version = "1.0.64", default-features = false }
Expand Down
52 changes: 38 additions & 14 deletions ethers-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ pub enum ConversionError {
InvalidFloat(#[from] std::num::ParseFloatError),
#[error(transparent)]
FromDecStrError(#[from] FromDecStrErr),
#[error(transparent)]
DecimalError(#[from] rust_decimal::Error),
#[error("Overflow parsing string")]
ParseOverflow,
}

/// 1 Ether = 1e18 Wei == 0x0de0b6b3a7640000 Wei
Expand Down Expand Up @@ -155,19 +155,27 @@ where
S: ToString,
K: TryInto<Units, Error = ConversionError> + Copy,
{
use rust_decimal::{Decimal, MathematicalOps};

let num: Decimal = amount.to_string().parse()?;
let exponent = units.try_into()?.as_num();

let multiplier = Decimal::TEN
.checked_powu(exponent.into())
.ok_or(rust_decimal::Error::ExceedsMaximumPossibleValue)?;
let exponent: u32 = units.try_into()?.as_num();
let mut amount_str = amount.to_string().replace("_", "");
let dec_len = if let Some(di) = amount_str.find('.') {
amount_str.remove(di);
amount_str[di..].len() as u32
} else {
0
};

let val =
num.checked_mul(multiplier).ok_or(rust_decimal::Error::ExceedsMaximumPossibleValue)?;
let u256_n: U256 = U256::from_dec_str(&val.round().to_string())?;
Ok(u256_n)
if dec_len > exponent {
// Truncate the decimal part if it is longer than the exponent
let amount_str = &amount_str[..(amount_str.len() - (dec_len - exponent) as usize)];
let a_uint = U256::from_dec_str(amount_str)?;
Ok(a_uint)
} else {
let mut a_uint = U256::from_dec_str(&amount_str)?;
a_uint *= U256::from(10)
.checked_pow(U256::from(exponent - dec_len))
.ok_or(ConversionError::ParseOverflow)?;
Ok(a_uint)
}
}
/// The address for an Ethereum contract is deterministically computed from the
/// address of its creator (sender) and how many transactions the creator has
Expand Down Expand Up @@ -474,6 +482,22 @@ mod tests {

let val = parse_units("2.3", "ether").unwrap();
assert_eq!(val, U256::from_dec_str("2300000000000000000").unwrap());

assert_eq!(parse_units(".2", 2).unwrap(), U256::from(20), "leading dot");
assert_eq!(parse_units("333.21", 2).unwrap(), U256::from(33321), "trailing dot");
assert_eq!(
parse_units("98766", 16).unwrap(),
U256::from_dec_str("987660000000000000000").unwrap(),
"no dot"
);
assert_eq!(parse_units("3_3_0", 3).unwrap(), U256::from(330000), "underscore");
assert_eq!(parse_units("330", 0).unwrap(), U256::from(330), "zero decimals");
assert_eq!(parse_units(".1234", 3).unwrap(), U256::from(123), "truncate too many decimals");
assert_eq!(parse_units("1", 80).is_err(), true, "overflow");
assert_eq!(parse_units("1", -1).is_err(), true, "neg units");
let two_e30 = U256::from(2) * U256([0x4674edea40000000, 0xc9f2c9cd0, 0x0, 0x0]);
assert_eq!(parse_units("2", 30).unwrap(), two_e30, "2e30");
assert_eq!(parse_units(".33_319_2", 0).unwrap(), U256::zero(), "mix");
}

#[test]
Expand Down

0 comments on commit c436473

Please sign in to comment.