Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
Comment thread
StackOverflowExcept1on marked this conversation as resolved.

# 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.
Outdated

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