Skip to content
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

Fix BSC gas price issues by treating chains with a base fee of 0 as non-1559 #3462

Merged
merged 4 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions rust/chains/hyperlane-ethereum/src/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ use std::time::Duration;
use ethers::{
abi::Detokenize,
prelude::{NameOrAddress, TransactionReceipt},
providers::ProviderError,
types::Eip1559TransactionRequest,
};
use ethers_contract::builders::ContractCall;
use ethers_core::types::BlockNumber;
use ethers_core::{
types::{BlockNumber, U256 as EthersU256},
utils::{
eip1559_default_estimator, EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE,
},
};
use hyperlane_core::{utils::bytes_to_hex, ChainCommunicationError, ChainResult, H256, U256};
use tracing::{error, info};

Expand Down Expand Up @@ -84,10 +91,22 @@ where
.saturating_add(U256::from(GAS_ESTIMATE_BUFFER).into())
.into()
};
let Ok((max_fee, max_priority_fee)) = provider.estimate_eip1559_fees(None).await else {

let Ok((base_fee, max_fee, max_priority_fee)) = estimate_eip1559_fees(provider, None).await
else {
// Is not EIP 1559 chain
return Ok(tx.gas(gas_limit));
};

// If the base fee is zero, just treat the chain as a non-EIP-1559 chain.
// This is useful for BSC, where the base fee is zero, there's a minimum gas price
// generally enforced by nodes of 3 gwei, but EIP 1559 estimation suggests a priority
// fee lower than 3 gwei because of privileged transactions being included by block
// producers that have a lower priority fee.
if base_fee.is_zero() {
return Ok(tx.gas(gas_limit));
}

// Is EIP 1559 chain
let mut request = Eip1559TransactionRequest::new();
if let Some(from) = tx.tx.from() {
Expand All @@ -109,6 +128,46 @@ where
Ok(eip_1559_tx.gas(gas_limit))
}

type FeeEstimator = fn(EthersU256, Vec<Vec<EthersU256>>) -> (EthersU256, EthersU256);

/// Pretty much a copy of the logic in ethers-rs (https://github.com/hyperlane-xyz/ethers-rs/blob/c9ced035628da59376c369be035facda1648577a/ethers-providers/src/provider.rs#L478)
/// but returns the base fee as well as the max fee and max priority fee.
/// Gets a heuristic recommendation of max fee per gas and max priority fee per gas for
/// EIP-1559 compatible transactions.
async fn estimate_eip1559_fees<M>(
provider: Arc<M>,
estimator: Option<FeeEstimator>,
) -> ChainResult<(EthersU256, EthersU256, EthersU256)>
where
M: Middleware + 'static,
{
let base_fee_per_gas = provider
.get_block(BlockNumber::Latest)
.await
.map_err(ChainCommunicationError::from_other)?
.ok_or_else(|| ProviderError::CustomError("Latest block not found".into()))?
.base_fee_per_gas
.ok_or_else(|| ProviderError::CustomError("EIP-1559 not activated".into()))?;

let fee_history = provider
.fee_history(
EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
BlockNumber::Latest,
&[EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
)
.await
.map_err(ChainCommunicationError::from_other)?;

// use the provided fee estimator function, or fallback to the default implementation.
let (max_fee_per_gas, max_priority_fee_per_gas) = if let Some(es) = estimator {
es(base_fee_per_gas, fee_history.reward)
} else {
eip1559_default_estimator(base_fee_per_gas, fee_history.reward)
};

Ok((base_fee_per_gas, max_fee_per_gas, max_priority_fee_per_gas))
}

pub(crate) async fn call_with_lag<M, T>(
call: ethers::contract::builders::ContractCall<M, T>,
provider: &M,
Expand Down
2 changes: 1 addition & 1 deletion typescript/infra/config/environments/mainnet3/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const hyperlane: RootAgentConfig = {
docker: {
repo,
// Includes Cosmos block-by-block indexing.
tag: 'a72c3cf-20240314-173418',
tag: '39df4ca-20240321-100543',
},
gasPaymentEnforcement: [
// Temporary measure to ensure all inEVM warp route messages are delivered -
Expand Down
Loading