* Fixes: #1822

* Fixes: gakonst#1822 :: update1

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

* update changelog
This commit is contained in:
halo3mic 2022-11-07 21:28:43 +01:00 committed by GitHub
parent 2ad787c756
commit ba9aa7838b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 27 deletions

View File

@ -4,6 +4,8 @@
### Unreleased ### 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` - 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) - 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 - Fix geth trace types for debug_traceTransaction rpc

12
Cargo.lock generated
View File

@ -1316,7 +1316,6 @@ dependencies = [
"rand 0.8.5", "rand 0.8.5",
"rlp", "rlp",
"rlp-derive", "rlp-derive",
"rust_decimal",
"serde", "serde",
"serde_json", "serde_json",
"strum", "strum",
@ -3280,17 +3279,6 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "rust_decimal"
version = "1.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee9164faf726e4f3ece4978b25ca877ddc6802fa77f38cdccb32c7f805ecd70c"
dependencies = [
"arrayvec 0.7.2",
"num-traits",
"serde",
]
[[package]] [[package]]
name = "rustc-hex" name = "rustc-hex"
version = "2.1.0" version = "2.1.0"

View File

@ -43,7 +43,6 @@ cargo_metadata = { version = "0.15.0", optional = true }
convert_case = { version = "0.6.0", optional = true } convert_case = { version = "0.6.0", optional = true }
syn = { version = "1.0.103", optional = true } syn = { version = "1.0.103", optional = true }
proc-macro2 = { version = "1.0.47", optional = true } proc-macro2 = { version = "1.0.47", optional = true }
rust_decimal = { version = "1.26.1", features = ["maths"] }
[dev-dependencies] [dev-dependencies]
serde_json = { version = "1.0.64", default-features = false } serde_json = { version = "1.0.64", default-features = false }

View File

@ -56,8 +56,8 @@ pub enum ConversionError {
InvalidFloat(#[from] std::num::ParseFloatError), InvalidFloat(#[from] std::num::ParseFloatError),
#[error(transparent)] #[error(transparent)]
FromDecStrError(#[from] FromDecStrErr), FromDecStrError(#[from] FromDecStrErr),
#[error(transparent)] #[error("Overflow parsing string")]
DecimalError(#[from] rust_decimal::Error), ParseOverflow,
} }
/// 1 Ether = 1e18 Wei == 0x0de0b6b3a7640000 Wei /// 1 Ether = 1e18 Wei == 0x0de0b6b3a7640000 Wei
@ -155,19 +155,27 @@ where
S: ToString, S: ToString,
K: TryInto<Units, Error = ConversionError> + Copy, K: TryInto<Units, Error = ConversionError> + Copy,
{ {
use rust_decimal::{Decimal, MathematicalOps}; 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 num: Decimal = amount.to_string().parse()?; if dec_len > exponent {
let exponent = units.try_into()?.as_num(); // 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 multiplier = Decimal::TEN let a_uint = U256::from_dec_str(amount_str)?;
.checked_powu(exponent.into()) Ok(a_uint)
.ok_or(rust_decimal::Error::ExceedsMaximumPossibleValue)?; } else {
let mut a_uint = U256::from_dec_str(&amount_str)?;
let val = a_uint *= U256::from(10)
num.checked_mul(multiplier).ok_or(rust_decimal::Error::ExceedsMaximumPossibleValue)?; .checked_pow(U256::from(exponent - dec_len))
let u256_n: U256 = U256::from_dec_str(&val.round().to_string())?; .ok_or(ConversionError::ParseOverflow)?;
Ok(u256_n) Ok(a_uint)
}
} }
/// The address for an Ethereum contract is deterministically computed from the /// The address for an Ethereum contract is deterministically computed from the
/// address of its creator (sender) and how many transactions the creator has /// address of its creator (sender) and how many transactions the creator has
@ -474,6 +482,22 @@ mod tests {
let val = parse_units("2.3", "ether").unwrap(); let val = parse_units("2.3", "ether").unwrap();
assert_eq!(val, U256::from_dec_str("2300000000000000000").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] #[test]