diff --git a/crates/blockifier/src/execution/entry_point.rs b/crates/blockifier/src/execution/entry_point.rs index 8c9cf87d79..7ec5662b37 100644 --- a/crates/blockifier/src/execution/entry_point.rs +++ b/crates/blockifier/src/execution/entry_point.rs @@ -279,6 +279,7 @@ impl EntryPointExecutionContext { // transactions derive this value from the `max_fee`. let tx_gas_upper_bound = match tx_info { // Fee is a larger uint type than GasAmount, so we need to saturate the division. + // This is just a computation of an upper bound, so it's safe to saturate. TransactionInfo::Deprecated(context) => context.max_fee.saturating_div( block_info.gas_prices.get_l1_gas_price_by_fee_type(&tx_info.fee_type()), ), @@ -287,7 +288,6 @@ impl EntryPointExecutionContext { // Use saturating upper bound to avoid overflow. This is safe because the upper bound is // bounded above by the block's limit, which is a usize. - let upper_bound_u64 = if gas_per_step.is_zero() { u64::MAX } else { diff --git a/crates/starknet_api/src/execution_resources.rs b/crates/starknet_api/src/execution_resources.rs index c29ce281f9..0e71baaf92 100644 --- a/crates/starknet_api/src/execution_resources.rs +++ b/crates/starknet_api/src/execution_resources.rs @@ -49,6 +49,10 @@ impl_from_uint_for_gas_amount!(u8, u16, u32, u64); impl GasAmount { pub const MAX: Self = Self(u64::MAX); + pub fn checked_add(self, rhs: Self) -> Option { + self.0.checked_add(rhs.0).map(Self) + } + pub fn saturating_add(self, rhs: Self) -> Self { self.0.saturating_add(rhs.0).into() } @@ -142,21 +146,26 @@ impl GasVector { /// X non-data-related gas consumption and Y bytes of data, in non-blob mode, would /// cost (X + 16*Y) units of gas. Applying the discount ratio to the data-related /// summand, we get total_gas = (X + Y * DGP / GP). - /// If this function is called with kzg_flag==false, then l1_data_gas==0, and this dicount + /// If this function is called with kzg_flag==false, then l1_data_gas==0, and this discount /// function does nothing. + /// Panics on overflow. pub fn to_discounted_l1_gas(&self, gas_prices: &GasPriceVector) -> GasAmount { let l1_data_gas_fee = self.l1_data_gas.nonzero_saturating_mul(gas_prices.l1_data_gas_price); let l1_data_gas_in_l1_gas_units = l1_data_gas_fee.checked_div_ceil(gas_prices.l1_gas_price).unwrap_or_else(|| { - log::warn!( + panic!( "Discounted L1 gas cost overflowed: division of L1 data fee ({}) by regular \ L1 gas price ({}) resulted in overflow.", - l1_data_gas_fee, - gas_prices.l1_gas_price + l1_data_gas_fee, gas_prices.l1_gas_price ); - GasAmount::MAX }); - self.l1_gas.saturating_add(l1_data_gas_in_l1_gas_units) + self.l1_gas.checked_add(l1_data_gas_in_l1_gas_units).unwrap_or_else(|| { + panic!( + "Overflow while computing discounted L1 gas: L1 gas ({}) + L1 data gas in L1 gas \ + units ({}) resulted in overflow.", + self.l1_gas, l1_data_gas_in_l1_gas_units + ) + }) } } diff --git a/crates/starknet_api/src/transaction.rs b/crates/starknet_api/src/transaction.rs index a3d3e28e0b..8008885b4d 100644 --- a/crates/starknet_api/src/transaction.rs +++ b/crates/starknet_api/src/transaction.rs @@ -1108,6 +1108,9 @@ impl ValidResourceBounds { } } + /// Returns the maximum possible fee that can be charged for the transaction. + /// The computation is saturating, meaning that if the result is larger than the maximum + /// possible fee, the maximum possible fee is returned. pub fn max_possible_fee(&self) -> Fee { match self { ValidResourceBounds::L1Gas(l1_bounds) => {