From b17b61cea80f87bb69608b91b0c79639058c88eb Mon Sep 17 00:00:00 2001 From: Alpay Aldemir Date: Thu, 4 Jun 2026 19:31:18 -0700 Subject: [PATCH 1/2] fix(transaction): use single config for gas limit with fallback --- crates/core/src/gas/types/gas_limit.rs | 15 +++++++++++++++ .../queue_system/transactions_queue.rs | 2 +- .../queue_system/transactions_queues.rs | 3 +-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/core/src/gas/types/gas_limit.rs b/crates/core/src/gas/types/gas_limit.rs index 04c2a20b..560bdffa 100644 --- a/crates/core/src/gas/types/gas_limit.rs +++ b/crates/core/src/gas/types/gas_limit.rs @@ -13,11 +13,26 @@ use tokio_postgres::types::{FromSql, IsNull, ToSql, Type}; #[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq)] pub struct GasLimit(u128); +/// Default temporary gas limit used for gas estimation when no real limit is known yet. +const DEFAULT_TEMP_GAS_LIMIT: u128 = 10_000_000; + impl GasLimit { pub fn new(gas_limit: u128) -> Self { GasLimit(gas_limit) } + /// Returns the temporary gas limit used as an upper bound during gas estimation. + /// + /// Reads `RRELAYER_TEMP_GAS_LIMIT` from the environment, falling back to + /// [`DEFAULT_TEMP_GAS_LIMIT`] (10,000,000) when it is unset or invalid. + pub fn temp_for_estimation() -> Self { + let value = std::env::var("RRELAYER_TEMP_GAS_LIMIT") + .ok() + .and_then(|raw| raw.parse::().ok()) + .unwrap_or(DEFAULT_TEMP_GAS_LIMIT); + GasLimit(value) + } + pub fn into_inner(self) -> u128 { self.0 } diff --git a/crates/core/src/transaction/queue_system/transactions_queue.rs b/crates/core/src/transaction/queue_system/transactions_queue.rs index f1ccee2a..0ae63211 100644 --- a/crates/core/src/transaction/queue_system/transactions_queue.rs +++ b/crates/core/src/transaction/queue_system/transactions_queue.rs @@ -1172,7 +1172,7 @@ impl TransactionsQueue { } // Estimate gas limit by creating a temporary transaction with a high gas limit to avoid failing the estimate - let temp_gas_limit = GasLimit::new(10_000_000); + let temp_gas_limit = GasLimit::temp_for_estimation(); let temp_transaction_request = if working_transaction.is_blob_transaction() { info!( diff --git a/crates/core/src/transaction/queue_system/transactions_queues.rs b/crates/core/src/transaction/queue_system/transactions_queues.rs index cdbdbcdb..a80f7a00 100644 --- a/crates/core/src/transaction/queue_system/transactions_queues.rs +++ b/crates/core/src/transaction/queue_system/transactions_queues.rs @@ -524,8 +524,7 @@ impl TransactionsQueues { blob_gas_price: Option<&BlobGasPriceResult>, ) -> Result { // Use a reasonable temporary limit for gas estimation - const TEMP_GAS_LIMIT: u128 = 1_000_000; - let temp_gas_limit = GasLimit::new(TEMP_GAS_LIMIT); + let temp_gas_limit = GasLimit::temp_for_estimation(); let current_onchain_nonce = transactions_queue.get_nonce().await.map_err(|e| { AddTransactionError::CouldNotGetCurrentOnChainNonce(transaction.relayer_id, e) From bd5a5019437efe0bdfd9104acdc6de0f241f8182 Mon Sep 17 00:00:00 2001 From: Alpay Aldemir Date: Thu, 4 Jun 2026 20:01:12 -0700 Subject: [PATCH 2/2] refactor(transaction): drop static gas limit for gas estimation call --- crates/core/src/gas/types/gas_limit.rs | 15 --------------- crates/core/src/provider/evm_provider.rs | 3 +++ .../queue_system/transactions_queue.rs | 5 +++-- .../queue_system/transactions_queues.rs | 5 +++-- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/crates/core/src/gas/types/gas_limit.rs b/crates/core/src/gas/types/gas_limit.rs index 560bdffa..04c2a20b 100644 --- a/crates/core/src/gas/types/gas_limit.rs +++ b/crates/core/src/gas/types/gas_limit.rs @@ -13,26 +13,11 @@ use tokio_postgres::types::{FromSql, IsNull, ToSql, Type}; #[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq)] pub struct GasLimit(u128); -/// Default temporary gas limit used for gas estimation when no real limit is known yet. -const DEFAULT_TEMP_GAS_LIMIT: u128 = 10_000_000; - impl GasLimit { pub fn new(gas_limit: u128) -> Self { GasLimit(gas_limit) } - /// Returns the temporary gas limit used as an upper bound during gas estimation. - /// - /// Reads `RRELAYER_TEMP_GAS_LIMIT` from the environment, falling back to - /// [`DEFAULT_TEMP_GAS_LIMIT`] (10,000,000) when it is unset or invalid. - pub fn temp_for_estimation() -> Self { - let value = std::env::var("RRELAYER_TEMP_GAS_LIMIT") - .ok() - .and_then(|raw| raw.parse::().ok()) - .unwrap_or(DEFAULT_TEMP_GAS_LIMIT); - GasLimit(value) - } - pub fn into_inner(self) -> u128 { self.0 } diff --git a/crates/core/src/provider/evm_provider.rs b/crates/core/src/provider/evm_provider.rs index 7036f38c..cbbbea76 100644 --- a/crates/core/src/provider/evm_provider.rs +++ b/crates/core/src/provider/evm_provider.rs @@ -438,6 +438,9 @@ impl EvmProvider { let mut request: TransactionRequest = transaction.clone().into(); // need from here else it will fail gas estimating request.from = Some(from.into_address()); + // Omit the gas limit so the node uses the block gas limit as the estimation + // ceiling. Passing a fixed cap risks failing the estimate for heavy transactions. + request.gas = None; let request_with_other = WithOtherFields::new(request); diff --git a/crates/core/src/transaction/queue_system/transactions_queue.rs b/crates/core/src/transaction/queue_system/transactions_queue.rs index 0ae63211..c931cb2c 100644 --- a/crates/core/src/transaction/queue_system/transactions_queue.rs +++ b/crates/core/src/transaction/queue_system/transactions_queue.rs @@ -1171,8 +1171,9 @@ impl TransactionsQueue { working_transaction.value = TransactionValue::zero(); } - // Estimate gas limit by creating a temporary transaction with a high gas limit to avoid failing the estimate - let temp_gas_limit = GasLimit::temp_for_estimation(); + // Build a temporary transaction for gas estimation. The gas limit here is a + // placeholder only — `estimate_gas` omits it so the node uses the block gas limit. + let temp_gas_limit = GasLimit::new(0); let temp_transaction_request = if working_transaction.is_blob_transaction() { info!( diff --git a/crates/core/src/transaction/queue_system/transactions_queues.rs b/crates/core/src/transaction/queue_system/transactions_queues.rs index a80f7a00..9c9f9281 100644 --- a/crates/core/src/transaction/queue_system/transactions_queues.rs +++ b/crates/core/src/transaction/queue_system/transactions_queues.rs @@ -523,8 +523,9 @@ impl TransactionsQueues { gas_price: &GasPriceResult, blob_gas_price: Option<&BlobGasPriceResult>, ) -> Result { - // Use a reasonable temporary limit for gas estimation - let temp_gas_limit = GasLimit::temp_for_estimation(); + // Build a temporary transaction for gas estimation. The gas limit here is a + // placeholder only — `estimate_gas` omits it so the node uses the block gas limit. + let temp_gas_limit = GasLimit::new(0); let current_onchain_nonce = transactions_queue.get_nonce().await.map_err(|e| { AddTransactionError::CouldNotGetCurrentOnChainNonce(transaction.relayer_id, e)