diff --git a/crates/builder/src/bundle_proposer.rs b/crates/builder/src/bundle_proposer.rs index ac9dcdbc0..48cd3230d 100644 --- a/crates/builder/src/bundle_proposer.rs +++ b/crates/builder/src/bundle_proposer.rs @@ -41,12 +41,8 @@ use crate::emit::{BuilderEvent, OpRejectionReason, SkipReason}; /// A user op must be valid for at least this long into the future to be included. const TIME_RANGE_BUFFER: Duration = Duration::from_secs(60); -/// Entrypoint requires a buffer over the user operation gas limits in the bundle transaction -const BUNDLE_TRANSACTION_GAS_OVERHEAD_BUFFER: u64 = 5000; /// Extra buffer percent to add on the bundle transaction gas estimate to be sure it will be enough const BUNDLE_TRANSACTION_GAS_OVERHEAD_PERCENT: u64 = 5; -/// The fixed gas overhead for any EVM transaction -const EVM_TRANSACTION_GAS_OVERHEAD: u64 = 21000; #[derive(Debug, Default)] pub(crate) struct Bundle { @@ -741,11 +737,7 @@ impl ProposalContext { } fn get_total_gas_limit(&self, chain_id: u64) -> U256 { - self.iter_ops() - .map(|op| gas::user_operation_gas_limit(op, chain_id, false)) - .fold(U256::zero(), |acc, c| acc + c) - + BUNDLE_TRANSACTION_GAS_OVERHEAD_BUFFER - + EVM_TRANSACTION_GAS_OVERHEAD + gas::bundle_gas_limit(self.iter_ops(), chain_id) } fn iter_ops_with_simulations(&self) -> impl Iterator + '_ { @@ -789,8 +781,8 @@ mod tests { op.pre_verification_gas + op.verification_gas_limit * 2 + op.call_gas_limit - + BUNDLE_TRANSACTION_GAS_OVERHEAD_BUFFER - + EVM_TRANSACTION_GAS_OVERHEAD, + + U256::from(5_000) + + U256::from(21_000), BUNDLE_TRANSACTION_GAS_OVERHEAD_PERCENT, ); @@ -1202,7 +1194,7 @@ mod tests { assert_eq!( bundle.gas_estimate, U256::from(math::increase_by_percent( - 10_000_000 + BUNDLE_TRANSACTION_GAS_OVERHEAD_BUFFER + EVM_TRANSACTION_GAS_OVERHEAD, + 10_000_000 + 5_000 + 21_000, BUNDLE_TRANSACTION_GAS_OVERHEAD_PERCENT )) ); diff --git a/crates/sim/src/gas/gas.rs b/crates/sim/src/gas/gas.rs index c15896cae..3988a7ccd 100644 --- a/crates/sim/src/gas/gas.rs +++ b/crates/sim/src/gas/gas.rs @@ -33,7 +33,8 @@ use super::polygon::Polygon; // see: https://github.com/eth-infinitism/bundler/blob/main/packages/sdk/src/calcPreVerificationGas.ts #[derive(Clone, Copy, Debug)] struct GasOverheads { - fixed: U256, + bundle_transaction_gas_buffer: U256, + transaction_gas_overhead: U256, per_user_op: U256, per_user_op_word: U256, zero_byte: U256, @@ -43,8 +44,9 @@ struct GasOverheads { impl Default for GasOverheads { fn default() -> Self { Self { - fixed: 21000.into(), - per_user_op: 18300.into(), + bundle_transaction_gas_buffer: 5_000.into(), // Entrypoint requires a buffer over the user operation gas limits in the bundle transaction + transaction_gas_overhead: 21_000.into(), // The fixed gas overhead for any EVM transaction + per_user_op: 18_300.into(), per_user_op_word: 4.into(), zero_byte: 4.into(), non_zero_byte: 16.into(), @@ -72,7 +74,7 @@ pub async fn calc_pre_verification_gas( provider: Arc

, chain_id: u64, ) -> anyhow::Result { - let static_gas = calc_static_pre_verification_gas(full_op, true); + let static_gas = calc_static_pre_verification_gas(full_op, GasOverheads::default(), true); let dynamic_gas = match chain_id { _ if ARBITRUM_CHAIN_IDS.contains(&chain_id) => { provider @@ -92,6 +94,20 @@ pub async fn calc_pre_verification_gas( Ok(static_gas + dynamic_gas) } +/// Compute the gas limit for the bundle composed of the given user operations +pub fn bundle_gas_limit<'a, I>(iter_ops: I, chain_id: u64) -> U256 +where + I: Iterator, +{ + let ov = GasOverheads::default(); + iter_ops + .map(|op| user_operation_gas_limit(op, chain_id, false)) + .fold( + ov.bundle_transaction_gas_buffer + ov.transaction_gas_overhead, + |acc, c| acc + c, + ) +} + /// Returns the gas limit for the user operation that applies to bundle transaction's limit pub fn user_operation_gas_limit( uo: &UserOperation, @@ -102,7 +118,7 @@ pub fn user_operation_gas_limit( // but this not part of the execution gas limit of the transaction. // In such cases we only consider the static portion of the pre_verification_gas in the gas limit. let pvg = if OP_BEDROCK_CHAIN_IDS.contains(&chain_id) | ARBITRUM_CHAIN_IDS.contains(&chain_id) { - calc_static_pre_verification_gas(uo, include_fixed_gas_overhead) + calc_static_pre_verification_gas(uo, GasOverheads::default(), include_fixed_gas_overhead) } else { uo.pre_verification_gas }; @@ -117,8 +133,11 @@ pub fn user_operation_max_gas_cost(uo: &UserOperation) -> U256 { * (uo.pre_verification_gas + uo.call_gas_limit + uo.verification_gas_limit * mul) } -fn calc_static_pre_verification_gas(op: &UserOperation, include_fixed_gas_overhead: bool) -> U256 { - let ov = GasOverheads::default(); +fn calc_static_pre_verification_gas( + op: &UserOperation, + ov: GasOverheads, + include_fixed_gas_overhead: bool, +) -> U256 { let encoded_op = op.clone().encode(); let length_in_words = encoded_op.len() / 32; // size of packed user op is always a multiple of 32 bytes let call_data_cost: U256 = encoded_op @@ -137,7 +156,7 @@ fn calc_static_pre_verification_gas(op: &UserOperation, include_fixed_gas_overhe + ov.per_user_op + ov.per_user_op_word * length_in_words + (if include_fixed_gas_overhead { - ov.fixed + ov.transaction_gas_overhead } else { 0.into() }) diff --git a/crates/sim/src/precheck.rs b/crates/sim/src/precheck.rs index eef954f71..74fddf1f2 100644 --- a/crates/sim/src/precheck.rs +++ b/crates/sim/src/precheck.rs @@ -180,7 +180,7 @@ impl PrecheckerImpl { max_verification_gas, )); } - let total_gas_limit = gas::user_operation_gas_limit(op, chain_id, false); + let total_gas_limit = gas::user_operation_gas_limit(op, chain_id, true); if total_gas_limit > max_total_execution_gas { violations.push(PrecheckViolation::TotalGasLimitTooHigh( total_gas_limit,