Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
core: fix overflow and panic in priority fee estimation (#839)
Browse files Browse the repository at this point in the history
The U256 priority fees were being coerced into u32, which was not big
enough for actual values. The overflow was happening but not checked.
This led to a possible divide-by-zero panic in this code as well.

This change does the math as I256 -- overkill, but it works.
  • Loading branch information
juniorbeef authored Jan 29, 2022
1 parent 8b9a18c commit 97744b8
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Unreleased

- Fix overflow and possible divide-by-zero in `estimate_priority_fee`
- Add BSC mainnet and testnet to the list of known chains
[831](https://github.com/gakonst/ethers-rs/pull/831)
- Returns error on invalid type conversion instead of panicking
Expand Down
22 changes: 13 additions & 9 deletions ethers-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ pub use rlp;
/// Re-export hex
pub use hex;

use crate::types::{Address, Bytes, U256};
use crate::types::{Address, Bytes, I256, U256};
use elliptic_curve::sec1::ToEncodedPoint;
use ethabi::ethereum_types::FromDecStrErr;
use k256::{ecdsa::SigningKey, PublicKey as K256PublicKey};
use std::{convert::TryInto, ops::Neg};
use std::convert::{TryFrom, TryInto};
use thiserror::Error;

#[derive(Error, Debug)]
Expand Down Expand Up @@ -335,15 +335,13 @@ fn estimate_priority_fee(rewards: Vec<Vec<U256>>) -> U256 {
let mut rewards_copy = rewards.clone();
rewards_copy.rotate_left(1);

let mut percentage_change: Vec<i64> = rewards
let mut percentage_change: Vec<I256> = rewards
.iter()
.zip(rewards_copy.iter())
.map(|(a, b)| {
if b > a {
((b - a).low_u32() as i64 * 100) / (a.low_u32() as i64)
} else {
(((a - b).low_u32() as i64 * 100) / (a.low_u32() as i64)).neg()
}
let a = I256::try_from(*a).expect("priority fee overflow");
let b = I256::try_from(*b).expect("priority fee overflow");
((b - a) * 100.into()) / a
})
.collect();
percentage_change.pop();
Expand All @@ -354,7 +352,7 @@ fn estimate_priority_fee(rewards: Vec<Vec<U256>>) -> U256 {

// If we encountered a big change in fees at a certain position, then consider only
// the values >= it.
let values = if *max_change >= EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE &&
let values = if *max_change >= EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE.into() &&
(max_change_index >= (rewards.len() / 2))
{
rewards[max_change_index..].to_vec()
Expand Down Expand Up @@ -682,5 +680,11 @@ mod tests {

// The median should be taken because none of the changes are big enough to ignore values.
assert_eq!(estimate_priority_fee(rewards), 102_000_000_000u64.into());

// Ensure fee estimation doesn't panic when overflowing a u32. This had been a divide by
// zero.
let overflow = U256::from(u32::MAX) + 1;
let rewards_overflow: Vec<Vec<U256>> = vec![vec![overflow], vec![overflow]];
assert_eq!(estimate_priority_fee(rewards_overflow), overflow);
}
}

0 comments on commit 97744b8

Please sign in to comment.