Skip to content
Open
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
4 changes: 4 additions & 0 deletions .ethexe.example.local.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ block-time = 1
# (optional, default: 15).
# eip1559-fee-increase-percentage = 15

# EIP-1559 max fee per gas in gwei for transaction fee estimation (for batch commitments).
# (optional, default: 0).
# eip1559-max-fee-per-gas-in-gwei = 0

# Blob gas multiplier.
# (optional, default: 3).
# blob-gas-multiplier = 3
Expand Down
4 changes: 4 additions & 0 deletions .ethexe.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@
# (optional, default: 15).
# eip1559-fee-increase-percentage = 15

# EIP-1559 max fee per gas in gwei for transaction fee estimation (for batch commitments).
# (optional, default: 0).
# eip1559-max-fee-per-gas-in-gwei = 0
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max_fee_per_gas = 0 means, that TX will never be included, because at least base_fee always > 0.

Did you mean max_priority_fee_per_gas = 0?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 means limit is disabled by default


# Blob gas multiplier.
# (optional, default: 3).
# blob-gas-multiplier = 3
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:
linux-aarch64: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'E5-forcelinuxaarch64') }}
release: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'E3-forcerelease') }}
production: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'E4-forceproduction') }}
docker: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'E0-forcedocker') }}

validator:
needs: gate
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ on:
production:
type: boolean
default: false
docker:
type: boolean
default: false

run-name: ${{ inputs.title }} ( ${{ format('#{0}', inputs.number) }} )

Expand Down Expand Up @@ -595,7 +598,7 @@ jobs:
name: Build Docker images for gear-cli, ethexe-cli (linux-x86_64)
runs-on: ubuntu-latest
needs: [dynamic-matrix, gear-cli, ethexe-cli]
if: ${{ contains(fromJSON(needs.dynamic-matrix.outputs.profiles).*.name, 'release') }}
if: ${{ contains(fromJSON(needs.dynamic-matrix.outputs.profiles).*.name, 'release') || inputs.docker }}
steps:
- name: "ACTIONS: Checkout"
uses: actions/checkout@v6
Expand Down
1 change: 1 addition & 0 deletions ethexe/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ beacon-rpc = "http://127.0.0.1:8545"
router = "0x..."
block-time = 12
eip1559-fee-increase-percentage = 20
eip1559-max-fee-per-gas-in-gwei = 0
blob-gas-multiplier = 2

[network]
Expand Down
15 changes: 15 additions & 0 deletions ethexe/cli/src/params/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ pub struct EthereumParams {
#[serde(rename = "eip1559-fee-increase-percentage")]
pub eip1559_fee_increase_percentage: Option<u64>,

/// EIP-1559 max fee per gas in gwei for transaction fee estimation (for batch commitments).
#[arg(long, alias = "eip1559-max-fee-per-gas-in-gwei")]
#[serde(rename = "eip1559-max-fee-per-gas-in-gwei")]
pub eip1559_max_fee_per_gas_in_gwei: Option<u128>,

/// Blob gas multiplier.
#[arg(long, alias = "blob-gas-multiplier")]
#[serde(rename = "blob-gas-multiplier")]
Expand All @@ -76,6 +81,10 @@ impl EthereumParams {
pub const DEFAULT_EIP1559_FEE_INCREASE_PERCENTAGE: u64 =
Ethereum::INCREASED_EIP1559_FEE_INCREASE_PERCENTAGE;

/// Default EIP-1559 max fee per gas in gwei for transaction fee estimation (for batch commitments).
pub const DEFAULT_EIP1559_MAX_FEE_PER_GAS_IN_GWEI: u128 =
Ethereum::NO_EIP1559_MAX_FEE_PER_GAS_IN_GWEI;

/// Default blob gas multiplier.
pub const DEFAULT_BLOB_GAS_MULTIPLIER: u128 = Ethereum::INCREASED_BLOB_GAS_MULTIPLIER;

Expand All @@ -98,6 +107,9 @@ impl EthereumParams {
eip1559_fee_increase_percentage: self
.eip1559_fee_increase_percentage
.unwrap_or(Self::DEFAULT_EIP1559_FEE_INCREASE_PERCENTAGE),
eip1559_max_fee_per_gas_in_gwei: self
.eip1559_max_fee_per_gas_in_gwei
.unwrap_or(Self::DEFAULT_EIP1559_MAX_FEE_PER_GAS_IN_GWEI),
blob_gas_multiplier: self
.blob_gas_multiplier
.unwrap_or(Self::DEFAULT_BLOB_GAS_MULTIPLIER),
Expand All @@ -115,6 +127,9 @@ impl MergeParams for EthereumParams {
eip1559_fee_increase_percentage: self
.eip1559_fee_increase_percentage
.or(with.eip1559_fee_increase_percentage),
eip1559_max_fee_per_gas_in_gwei: self
.eip1559_max_fee_per_gas_in_gwei
.or(with.eip1559_max_fee_per_gas_in_gwei),
blob_gas_multiplier: self.blob_gas_multiplier.or(with.blob_gas_multiplier),
}
}
Expand Down
61 changes: 47 additions & 14 deletions ethexe/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub struct EthereumBuilder {
signer: Option<Signer>,
sender_address: Option<Address>,
eip1559_fee_increase_percentage: Option<u64>,
eip1559_max_fee_per_gas_in_gwei: Option<u128>,
blob_gas_multiplier: Option<u128>,
initialize_addresses: Option<bool>,
}
Expand Down Expand Up @@ -138,6 +139,16 @@ impl EthereumBuilder {
self.eip1559_fee_increase_percentage(Ethereum::INCREASED_EIP1559_FEE_INCREASE_PERCENTAGE)
}

/// Sets the EIP-1559 max fee per gas in gwei to use for transaction fee estimation
/// (for batch commitments).
pub fn eip1559_max_fee_per_gas_in_gwei(
mut self,
eip1559_max_fee_per_gas_in_gwei: u128,
) -> Self {
self.eip1559_max_fee_per_gas_in_gwei = Some(eip1559_max_fee_per_gas_in_gwei);
self
}

/// Sets the blob gas multiplier to use for transaction fee estimation.
pub fn blob_gas_multiplier_opt(mut self, blob_gas_multiplier: Option<u128>) -> Self {
self.blob_gas_multiplier = blob_gas_multiplier;
Expand Down Expand Up @@ -182,6 +193,9 @@ impl EthereumBuilder {
let eip1559_fee_increase_percentage = self
.eip1559_fee_increase_percentage
.unwrap_or(Ethereum::NO_EIP1559_FEE_INCREASE_PERCENTAGE);
let eip1559_max_fee_per_gas_in_gwei = self
.eip1559_max_fee_per_gas_in_gwei
.unwrap_or(Ethereum::NO_EIP1559_MAX_FEE_PER_GAS_IN_GWEI);
let blob_gas_multiplier = self
.blob_gas_multiplier
.unwrap_or(Ethereum::NO_BLOB_GAS_MULTIPLIER);
Expand All @@ -193,6 +207,7 @@ impl EthereumBuilder {
signer,
sender_address,
eip1559_fee_increase_percentage,
eip1559_max_fee_per_gas_in_gwei,
blob_gas_multiplier,
initialize_addresses,
)
Expand All @@ -210,6 +225,8 @@ pub struct Ethereum {
provider: AlloyProvider,
signer: Signer,
sender_address: Address,
eip1559_estimator: Eip1559Estimator,
eip1559_max_fee_per_gas_in_gwei: u128,
}

impl Ethereum {
Expand All @@ -221,6 +238,8 @@ impl Ethereum {

/// Default EIP-1559 fee increase percentage for transaction fee estimation.
pub const NO_EIP1559_FEE_INCREASE_PERCENTAGE: u64 = 0;
/// Default EIP-1559 max fee per gas in gwei for transaction fee estimation (for batch commitments).
pub const NO_EIP1559_MAX_FEE_PER_GAS_IN_GWEI: u128 = 0;
/// EIP-1559 fee increase percentage for transaction fee estimation that increases the estimated fee
/// by 15% compared to "medium" estimation.
///
Expand All @@ -234,16 +253,18 @@ impl Ethereum {
/// This is useful mostly on testnets, where a lot of L2s can spam the network with blob transactions.
pub const INCREASED_BLOB_GAS_MULTIPLIER: u128 = 3;

#[allow(clippy::too_many_arguments)]
pub(crate) async fn new(
ethereum_rpc_url: &str,
router_address: Address,
signer: Signer,
sender_address: Address,
eip1559_fee_increase_percentage: u64,
eip1559_max_fee_per_gas_in_gwei: u128,
blob_gas_multiplier: u128,
initialize_addresses: bool,
) -> Result<Ethereum> {
let provider = create_provider(
let (provider, eip1559_estimator) = create_provider(
ethereum_rpc_url,
signer.clone(),
sender_address,
Expand All @@ -268,6 +289,8 @@ impl Ethereum {
provider,
signer,
sender_address,
eip1559_estimator,
eip1559_max_fee_per_gas_in_gwei,
})
}

Expand Down Expand Up @@ -341,7 +364,13 @@ impl Ethereum {
}

pub fn router(&self) -> Router {
Router::new(self.router, self.wvara, self.provider())
Router::new(
self.router,
self.wvara,
self.eip1559_estimator.clone(),
self.eip1559_max_fee_per_gas_in_gwei,
self.provider(),
)
}

pub fn wrapped_vara(&self) -> WVara {
Expand All @@ -364,18 +393,22 @@ pub(crate) async fn create_provider(
sender_address: Address,
eip1559_fee_increase_percentage: u64,
blob_gas_multiplier: u128,
) -> Result<AlloyProvider> {
Ok(ProviderBuilder::default()
.with_eip1559_estimator(Eip1559Estimator::new(move |base_fee_per_gas, rewards| {
utils::eip1559_default_estimator(base_fee_per_gas, rewards)
.scaled_by_pct(eip1559_fee_increase_percentage)
}))
.with_blob_gas_estimator(BlobGasEstimator::scaled(blob_gas_multiplier))
.with_simple_nonce_management()
.fetch_chain_id()
.wallet(EthereumWallet::new(Sender::new(signer, sender_address)?))
.connect(rpc_url)
.await?)
) -> Result<(AlloyProvider, Eip1559Estimator)> {
let eip1559_estimator = Eip1559Estimator::new(move |base_fee_per_gas, rewards| {
utils::eip1559_default_estimator(base_fee_per_gas, rewards)
.scaled_by_pct(eip1559_fee_increase_percentage)
});
Ok((
ProviderBuilder::default()
.with_eip1559_estimator(eip1559_estimator.clone())
.with_blob_gas_estimator(BlobGasEstimator::scaled(blob_gas_multiplier))
.with_simple_nonce_management()
.fetch_chain_id()
.wallet(EthereumWallet::new(Sender::new(signer, sender_address)?))
.connect(rpc_url)
.await?,
eip1559_estimator,
))
}

#[derive(Debug, Clone)]
Expand Down
47 changes: 43 additions & 4 deletions ethexe/ethereum/src/router/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ use crate::{
wvara::WVara,
};
use alloy::{
consensus::{SidecarBuilder, SimpleCoder},
consensus::{SidecarBuilder, SimpleCoder, constants::GWEI_TO_WEI},
eips::BlockId,
hex,
primitives::{Address as AlloyAddress, Bytes, fixed_bytes},
providers::{PendingTransactionBuilder, Provider, ProviderBuilder, RootProvider},
providers::{
PendingTransactionBuilder, Provider, ProviderBuilder, RootProvider,
utils::{Eip1559Estimation, Eip1559Estimator},
},
rpc::types::{TransactionReceipt, eth::state::AccountOverride},
};
use anyhow::{Result, anyhow};
Expand Down Expand Up @@ -64,6 +67,8 @@ type QueryInstance = IRouter::IRouterInstance<RootProvider>;
pub struct Router {
instance: Instance,
wvara_address: AlloyAddress,
eip1559_estimator: Eip1559Estimator,
eip1559_max_fee_per_gas_in_gwei: u128,
}

impl Router {
Expand All @@ -75,11 +80,15 @@ impl Router {
pub(crate) fn new(
address: AlloyAddress,
wvara_address: AlloyAddress,
eip1559_estimator: Eip1559Estimator,
eip1559_max_fee_per_gas_in_gwei: u128,
provider: AlloyProvider,
) -> Self {
Self {
instance: Instance::new(address, provider),
wvara_address,
eip1559_estimator,
eip1559_max_fee_per_gas_in_gwei,
}
}

Expand Down Expand Up @@ -378,8 +387,38 @@ impl Router {
));
}
};
let gas_limit =
Self::HUGE_GAS_LIMIT.max(estimated_gas_limit + Self::GEAR_BLOCK_IS_PREDECESSOR_GAS);

let Eip1559Estimation {
max_fee_per_gas, ..
} = self
.instance
.provider()
.estimate_eip1559_fees_with(self.eip1559_estimator.clone())
.await?;
let max_fee_per_gas_in_gwei = max_fee_per_gas.div_ceil(GWEI_TO_WEI as u128);
let eip1559_max_fee_per_gas_in_gwei = self.eip1559_max_fee_per_gas_in_gwei;

if eip1559_max_fee_per_gas_in_gwei > 0
&& max_fee_per_gas_in_gwei > eip1559_max_fee_per_gas_in_gwei
{
log::error!(
"Estimated max fee per gas {max_fee_per_gas_in_gwei} gwei is higher than the configured maximum of {eip1559_max_fee_per_gas_in_gwei} gwei, refusing to commit batch (commitment: {commitment:?})"
);
return Err(anyhow!(
"Estimated max fee per gas {max_fee_per_gas_in_gwei} gwei is higher than the configured maximum of {eip1559_max_fee_per_gas_in_gwei} gwei, refusing to commit batch",
));
}

let gas_limit = estimated_gas_limit + Self::GEAR_BLOCK_IS_PREDECESSOR_GAS;

if gas_limit > Self::HUGE_GAS_LIMIT {
log::error!(
"Estimated gas limit {gas_limit} is too high for batch commitment: {commitment:?}",
);
return Err(anyhow!(
"Estimated gas limit {gas_limit} is too high for batch commitment",
));
}
Comment thread
StackOverflowExcept1on marked this conversation as resolved.

builder.gas(gas_limit).send().await.map_err(Into::into)
}
Expand Down
1 change: 1 addition & 0 deletions ethexe/service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,6 @@ pub struct EthereumConfig {
pub router_address: Address,
pub block_time: Duration,
pub eip1559_fee_increase_percentage: u64,
pub eip1559_max_fee_per_gas_in_gwei: u128,
pub blob_gas_multiplier: u128,
}
1 change: 1 addition & 0 deletions ethexe/service/src/tests/utils/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ impl TestEnv {
router_address,
block_time,
eip1559_fee_increase_percentage: Ethereum::NO_EIP1559_FEE_INCREASE_PERCENTAGE,
eip1559_max_fee_per_gas_in_gwei: Ethereum::NO_EIP1559_MAX_FEE_PER_GAS_IN_GWEI,
blob_gas_multiplier: Ethereum::NO_BLOB_GAS_MULTIPLIER,
};
let mut observer = ObserverService::new(
Expand Down
1 change: 1 addition & 0 deletions ethexe/service/tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ async fn constructor() {
.expect("infallible"),
block_time: Duration::from_secs(12),
eip1559_fee_increase_percentage: Ethereum::NO_EIP1559_FEE_INCREASE_PERCENTAGE,
eip1559_max_fee_per_gas_in_gwei: Ethereum::NO_EIP1559_MAX_FEE_PER_GAS_IN_GWEI,
blob_gas_multiplier: Ethereum::NO_BLOB_GAS_MULTIPLIER,
};

Expand Down
Loading