From 58993a94235725493d314eb3859e62ee8e56623a Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Tue, 28 Jan 2025 15:58:42 +0100 Subject: [PATCH 1/3] fix(sidecar): validate max slot diff explicitly --- bolt-sidecar/src/state/execution.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index c702e9946..5ef2e85e9 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -74,6 +74,9 @@ pub enum ValidationError { /// The maximum commitments have been reached for the slot. #[error("Already requested a preconfirmation for slot {0}. Slot must be >= {0}")] SlotTooLow(u64), + /// The slot is too high (> current_slot + 64) + #[error("Target slot {0} is too high. Max target slot: {1}")] + SlotTooHigh(u64, u64), /// The maximum committed gas has been reached for the slot. #[error("Max committed gas reached for slot {0}: {1}")] MaxCommittedGasReachedForSlot(u64, u64), @@ -115,6 +118,7 @@ impl ValidationError { Self::Pricing(_) => "pricing", Self::Eip4844Limit => "eip4844_limit", Self::SlotTooLow(_) => "slot_too_low", + Self::SlotTooHigh(_, _) => "slot_too_high", Self::MaxCommittedGasReachedForSlot(_, _) => "max_committed_gas_reached_for_slot", Self::Signature(_) => "signature", Self::RecoverSigner => "recover_signer", @@ -291,6 +295,11 @@ impl ExecutionState { // Check if the max_fee_per_gas would cover the maximum possible basefee. let slot_diff = target_slot.saturating_sub(self.slot); + // Verify max slot diff + if slot_diff > 64 { + return Err(ValidationError::SlotTooHigh(target_slot, self.slot + 64)); + } + // Calculate the max possible basefee given the slot diff let max_basefee = calculate_max_basefee(self.basefee, slot_diff) .ok_or(ValidationError::MaxBaseFeeCalcOverflow)?; From f553103879ce6aec5a7ec1a06d7f14bc9b9c5746 Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Tue, 28 Jan 2025 16:02:04 +0100 Subject: [PATCH 2/3] test(sidecar): add basefee overflow test --- bolt-sidecar/src/common/transactions.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/common/transactions.rs b/bolt-sidecar/src/common/transactions.rs index 812e538a7..b65ee82e0 100644 --- a/bolt-sidecar/src/common/transactions.rs +++ b/bolt-sidecar/src/common/transactions.rs @@ -8,6 +8,9 @@ use crate::{primitives::AccountState, state::ValidationError}; /// Calculates the max_basefee `slot_diff` blocks in the future given a current basefee (in wei). /// Returns None if an overflow would occur. /// Cfr. https://github.com/flashbots/ethers-provider-flashbots-bundle/blob/7ddaf2c9d7662bef400151e0bfc89f5b13e72b4c/src/index.ts#L308 +/// +/// # Overflows +/// For 10 gwei, the max slot diff is 499. /// /// NOTE: this increase is correct also for the EIP-4844 blob base fee: /// See https://eips.ethereum.org/EIPS/eip-4844#base-fee-per-blob-gas-update-rule @@ -87,14 +90,31 @@ pub fn validate_transaction( #[cfg(test)] mod tests { + use alloy::consensus::constants::GWEI_TO_WEI; + use super::*; #[test] fn test_calculate_max_basefee() { - let current = 10_000_000_000; // 10 gwei + let current = GWEI_TO_WEI as u128 * 10; // 10 gwei let slot_diff = 9; // 9 full blocks in the future let result = calculate_max_basefee(current, slot_diff); - assert_eq!(result, Some(28865075793)) + assert_eq!(result, Some(28865075793)); + + let slot_diff = 84; + + let result = calculate_max_basefee(current, slot_diff); + + assert!(result.is_some()); + + // Max slot diff is 499 + let slot_diff = 500; + + let result = calculate_max_basefee(current, slot_diff); + + println!("result: {:?}", result); + + assert!(result.is_none()); } } From 795e3d6f10e166654966419dd6ade67c3d274ae5 Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Tue, 28 Jan 2025 16:17:04 +0100 Subject: [PATCH 3/3] refactor(sidecar): rm redundant slot diff check --- bolt-sidecar/src/state/execution.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 5ef2e85e9..c702e9946 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -74,9 +74,6 @@ pub enum ValidationError { /// The maximum commitments have been reached for the slot. #[error("Already requested a preconfirmation for slot {0}. Slot must be >= {0}")] SlotTooLow(u64), - /// The slot is too high (> current_slot + 64) - #[error("Target slot {0} is too high. Max target slot: {1}")] - SlotTooHigh(u64, u64), /// The maximum committed gas has been reached for the slot. #[error("Max committed gas reached for slot {0}: {1}")] MaxCommittedGasReachedForSlot(u64, u64), @@ -118,7 +115,6 @@ impl ValidationError { Self::Pricing(_) => "pricing", Self::Eip4844Limit => "eip4844_limit", Self::SlotTooLow(_) => "slot_too_low", - Self::SlotTooHigh(_, _) => "slot_too_high", Self::MaxCommittedGasReachedForSlot(_, _) => "max_committed_gas_reached_for_slot", Self::Signature(_) => "signature", Self::RecoverSigner => "recover_signer", @@ -295,11 +291,6 @@ impl ExecutionState { // Check if the max_fee_per_gas would cover the maximum possible basefee. let slot_diff = target_slot.saturating_sub(self.slot); - // Verify max slot diff - if slot_diff > 64 { - return Err(ValidationError::SlotTooHigh(target_slot, self.slot + 64)); - } - // Calculate the max possible basefee given the slot diff let max_basefee = calculate_max_basefee(self.basefee, slot_diff) .ok_or(ValidationError::MaxBaseFeeCalcOverflow)?;