-
Notifications
You must be signed in to change notification settings - Fork 308
feat(fortuna): add eip1559_fee_multiplier_pct to adjust gas fees #2191
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
Closed
devin-ai-integration
wants to merge
6
commits into
main
from
devin/1734012868-add-eip1559-fee-multiplier
Closed
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
5cc054e
feat(fortuna): add eip1559_fee_multiplier_pct to adjust gas fees
devin-ai-integration[bot] b3aaeb8
refactor: address PR feedback
devin-ai-integration[bot] c6a438e
refactor: restore original tracking functionality and fix balance con…
devin-ai-integration[bot] a1bb2ac
refactor: move fee multiplier to GasOracle
devin-ai-integration[bot] 632183b
style: apply cargo fmt changes
devin-ai-integration[bot] ec4d078
refactor: remove unnecessary span tracking and clean up keeper.rs
devin-ai-integration[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,44 +6,35 @@ use { | |
| GasOracle, | ||
| }, | ||
| providers::Middleware, | ||
| types::{I256, U256}, | ||
| types::U256, | ||
| }, | ||
| }; | ||
|
|
||
| // The default fee estimation logic in ethers.rs includes some hardcoded constants that do not | ||
| // work well in layer 2 networks because it lower bounds the priority fee at 3 gwei. | ||
| // Unfortunately this logic is not configurable in ethers.rs. | ||
| // | ||
| // Thus, this file is copy-pasted from places in ethers.rs with all of the fee constants divided by 1000000. | ||
| // See original logic here: | ||
| // https://github.com/gakonst/ethers-rs/blob/master/ethers-providers/src/rpc/provider.rs#L452 | ||
|
|
||
| /// The default max priority fee per gas, used in case the base fee is within a threshold. | ||
| pub const EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE: u64 = 3_000; | ||
| /// The threshold for base fee below which we use the default priority fee, and beyond which we | ||
| /// estimate an appropriate value for priority fee. | ||
| pub const EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER: u64 = 100_000; | ||
|
|
||
| /// Thresholds at which the base fee gets a multiplier | ||
| pub const SURGE_THRESHOLD_1: u64 = 40_000; | ||
| pub const SURGE_THRESHOLD_2: u64 = 100_000; | ||
| pub const SURGE_THRESHOLD_3: u64 = 200_000; | ||
|
|
||
| /// The threshold max change/difference (in %) at which we will ignore the fee history values | ||
| /// under it. | ||
| pub const EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE: i64 = 200; | ||
| /// Configuration for GasOracle | ||
| #[derive(Clone, Debug)] | ||
| pub struct GasOracleConfig { | ||
| pub eip1559_fee_multiplier_pct: u64, | ||
| } | ||
|
|
||
| /// Gas oracle from a [`Middleware`] implementation such as an | ||
| /// Ethereum RPC provider. | ||
| #[derive(Clone, Debug)] | ||
| #[must_use] | ||
| pub struct EthProviderOracle<M: Middleware> { | ||
| provider: M, | ||
| config: GasOracleConfig, | ||
| } | ||
|
|
||
| impl<M: Middleware> EthProviderOracle<M> { | ||
| pub fn new(provider: M) -> Self { | ||
| Self { provider } | ||
| /// Creates a new EthProviderOracle with the given provider and optional fee multiplier. | ||
| /// If no multiplier is provided, defaults to 100% (no change to fees). | ||
| pub fn new(provider: M, eip1559_fee_multiplier_pct: Option<u64>) -> Self { | ||
| Self { | ||
| provider, | ||
| config: GasOracleConfig { | ||
| eip1559_fee_multiplier_pct: eip1559_fee_multiplier_pct.unwrap_or(100), | ||
| }, | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -61,93 +52,15 @@ where | |
| } | ||
|
|
||
| async fn estimate_eip1559_fees(&self) -> Result<(U256, U256)> { | ||
| self.provider | ||
| .estimate_eip1559_fees(Some(eip1559_default_estimator)) | ||
| let (max_fee_per_gas, max_priority_fee_per_gas) = self | ||
| .provider | ||
| .estimate_eip1559_fees(None) | ||
| .await | ||
| .map_err(|err| GasOracleError::ProviderError(Box::new(err))) | ||
| } | ||
| } | ||
|
|
||
| /// The default EIP-1559 fee estimator which is based on the work by [MyCrypto](https://github.com/MyCryptoHQ/MyCrypto/blob/master/src/services/ApiService/Gas/eip1559.ts) | ||
| pub fn eip1559_default_estimator(base_fee_per_gas: U256, rewards: Vec<Vec<U256>>) -> (U256, U256) { | ||
| let max_priority_fee_per_gas = | ||
| if base_fee_per_gas < U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) { | ||
| U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE) | ||
| } else { | ||
| std::cmp::max( | ||
| estimate_priority_fee(rewards), | ||
| U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE), | ||
| ) | ||
| }; | ||
| let potential_max_fee = base_fee_surged(base_fee_per_gas); | ||
| let max_fee_per_gas = if max_priority_fee_per_gas > potential_max_fee { | ||
| max_priority_fee_per_gas + potential_max_fee | ||
| } else { | ||
| potential_max_fee | ||
| }; | ||
| (max_fee_per_gas, max_priority_fee_per_gas) | ||
| } | ||
|
|
||
| fn estimate_priority_fee(rewards: Vec<Vec<U256>>) -> U256 { | ||
| let mut rewards: Vec<U256> = rewards | ||
| .iter() | ||
| .map(|r| r[0]) | ||
| .filter(|r| *r > U256::zero()) | ||
| .collect(); | ||
| if rewards.is_empty() { | ||
| return U256::zero(); | ||
| } | ||
| if rewards.len() == 1 { | ||
| return rewards[0]; | ||
| } | ||
| // Sort the rewards as we will eventually take the median. | ||
| rewards.sort(); | ||
|
|
||
| // A copy of the same vector is created for convenience to calculate percentage change | ||
| // between subsequent fee values. | ||
| let mut rewards_copy = rewards.clone(); | ||
| rewards_copy.rotate_left(1); | ||
|
|
||
| let mut percentage_change: Vec<I256> = rewards | ||
| .iter() | ||
| .zip(rewards_copy.iter()) | ||
| .map(|(a, b)| { | ||
| let a = I256::try_from(*a).expect("priority fee overflow"); | ||
| let b = I256::try_from(*b).expect("priority fee overflow"); | ||
| ((b - a) * 100) / a | ||
| }) | ||
| .collect(); | ||
| percentage_change.pop(); | ||
|
|
||
| // Fetch the max of the percentage change, and that element's index. | ||
| let max_change = percentage_change.iter().max().unwrap(); | ||
| let max_change_index = percentage_change | ||
| .iter() | ||
| .position(|&c| c == *max_change) | ||
| .unwrap(); | ||
|
|
||
| // 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.into() | ||
| && (max_change_index >= (rewards.len() / 2)) | ||
| { | ||
| rewards[max_change_index..].to_vec() | ||
| } else { | ||
| rewards | ||
| }; | ||
|
|
||
| // Return the median. | ||
| values[values.len() / 2] | ||
| } | ||
| .map_err(|err| GasOracleError::ProviderError(Box::new(err)))?; | ||
|
|
||
| fn base_fee_surged(base_fee_per_gas: U256) -> U256 { | ||
| if base_fee_per_gas <= U256::from(SURGE_THRESHOLD_1) { | ||
| base_fee_per_gas * 2 | ||
| } else if base_fee_per_gas <= U256::from(SURGE_THRESHOLD_2) { | ||
| base_fee_per_gas * 16 / 10 | ||
| } else if base_fee_per_gas <= U256::from(SURGE_THRESHOLD_3) { | ||
| base_fee_per_gas * 14 / 10 | ||
| } else { | ||
| base_fee_per_gas * 12 / 10 | ||
| // Apply the fee multiplier | ||
| let multiplier = U256::from(self.config.eip1559_fee_multiplier_pct); | ||
| let adjusted_max_fee = (max_fee_per_gas * multiplier) / U256::from(100); | ||
|
Contributor
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. we should be adjusting max_priority_fee_per_gas, not max_fee_per_gas |
||
| Ok((adjusted_max_fee, max_priority_fee_per_gas)) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This line should still be using eip1559_default_estimator. Please undo the deletion of that here.