diff --git a/crates/blockifier/src/blockifier/block.rs b/crates/blockifier/src/blockifier/block.rs index 83be85d1a6..a46bf1d5d5 100644 --- a/crates/blockifier/src/blockifier/block.rs +++ b/crates/blockifier/src/blockifier/block.rs @@ -1,5 +1,6 @@ use std::num::NonZeroU128; +use num_rational::Ratio; use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp}; use starknet_api::core::ContractAddress; use starknet_api::state::StorageKey; @@ -13,6 +14,11 @@ use crate::transaction::objects::FeeType; #[cfg(test)] #[path = "block_test.rs"] pub mod block_test; +pub const L2_GAS_FOR_CAIRO_STEP: u128 = 100; +pub const CAIRO_STEPS_PER_L1_GAS: u128 = 400; +pub const L2_TO_L1_GAS_PRICE_RATIO: u128 = L2_GAS_FOR_CAIRO_STEP * CAIRO_STEPS_PER_L1_GAS; + +pub type L2Cost = Ratio; #[derive(Clone, Debug)] pub struct BlockInfo { @@ -27,13 +33,32 @@ pub struct BlockInfo { #[derive(Clone, Debug)] pub struct GasPrices { - pub eth_l1_gas_price: NonZeroU128, // In wei. - pub strk_l1_gas_price: NonZeroU128, // In fri. - pub eth_l1_data_gas_price: NonZeroU128, // In wei. - pub strk_l1_data_gas_price: NonZeroU128, // In fri. + eth_l1_gas_price: NonZeroU128, // In wei. + strk_l1_gas_price: NonZeroU128, // In fri. + eth_l1_data_gas_price: NonZeroU128, // In wei. + strk_l1_data_gas_price: NonZeroU128, // In fri. + eth_l2_gas_price: L2Cost, // In wei. + strk_l2_gas_price: L2Cost, // In fri. } impl GasPrices { + pub fn new( + eth_l1_gas_price: NonZeroU128, + strk_l1_gas_price: NonZeroU128, + eth_l1_data_gas_price: NonZeroU128, + strk_l1_data_gas_price: NonZeroU128, + ) -> Self { + let eth_l2_gas_price = L2Cost::new(eth_l1_gas_price.into(), L2_TO_L1_GAS_PRICE_RATIO); + let strk_l2_gas_price = L2Cost::new(strk_l1_gas_price.into(), L2_TO_L1_GAS_PRICE_RATIO); + GasPrices { + eth_l1_gas_price, + strk_l1_gas_price, + eth_l1_data_gas_price, + strk_l1_data_gas_price, + eth_l2_gas_price, + strk_l2_gas_price, + } + } pub fn get_gas_price_by_fee_type(&self, fee_type: &FeeType) -> NonZeroU128 { match fee_type { FeeType::Strk => self.strk_l1_gas_price, @@ -47,6 +72,13 @@ impl GasPrices { FeeType::Eth => self.eth_l1_data_gas_price, } } + + pub fn get_l2_gas_price_by_fee_type(&self, fee_type: &FeeType) -> L2Cost { + match fee_type { + FeeType::Strk => self.strk_l2_gas_price, + FeeType::Eth => self.eth_l2_gas_price, + } + } } // Block pre-processing. diff --git a/crates/blockifier/src/fee/fee_test.rs b/crates/blockifier/src/fee/fee_test.rs index 9fa32a18cc..91a989565d 100644 --- a/crates/blockifier/src/fee/fee_test.rs +++ b/crates/blockifier/src/fee/fee_test.rs @@ -121,9 +121,15 @@ fn test_discounted_gas_overdraft( #[case] gas_bound: u64, #[case] expect_failure: bool, ) { + use crate::blockifier::block::GasPrices; + let mut block_context = BlockContext::create_for_account_testing(); - block_context.block_info.gas_prices.strk_l1_gas_price = gas_price.try_into().unwrap(); - block_context.block_info.gas_prices.strk_l1_data_gas_price = data_gas_price.try_into().unwrap(); + block_context.block_info.gas_prices = GasPrices::create_for_testing_w_strk_gas_prices( + None, + Some(gas_price), + None, + Some(data_gas_price), + ); let account = FeatureContract::AccountWithoutValidations(CairoVersion::Cairo0); let mut state = test_state(&block_context.chain_info, BALANCE, &[(account, 1)]); diff --git a/crates/blockifier/src/test_utils/struct_impls.rs b/crates/blockifier/src/test_utils/struct_impls.rs index 664041671c..7f20232bbd 100644 --- a/crates/blockifier/src/test_utils/struct_impls.rs +++ b/crates/blockifier/src/test_utils/struct_impls.rs @@ -158,12 +158,12 @@ impl BlockInfo { block_number: BlockNumber(CURRENT_BLOCK_NUMBER), block_timestamp: BlockTimestamp(CURRENT_BLOCK_TIMESTAMP), sequencer_address: contract_address!(TEST_SEQUENCER_ADDRESS), - gas_prices: GasPrices { - eth_l1_gas_price: DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(), - strk_l1_gas_price: DEFAULT_STRK_L1_GAS_PRICE.try_into().unwrap(), - eth_l1_data_gas_price: DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(), - strk_l1_data_gas_price: DEFAULT_STRK_L1_DATA_GAS_PRICE.try_into().unwrap(), - }, + gas_prices: GasPrices::new( + DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(), + DEFAULT_STRK_L1_GAS_PRICE.try_into().unwrap(), + DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(), + DEFAULT_STRK_L1_DATA_GAS_PRICE.try_into().unwrap(), + ), use_kzg_da: false, } } @@ -173,6 +173,31 @@ impl BlockInfo { } } +impl GasPrices { + pub fn create_for_testing() -> Self { + Self::new( + DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(), + DEFAULT_STRK_L1_GAS_PRICE.try_into().unwrap(), + DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(), + DEFAULT_STRK_L1_DATA_GAS_PRICE.try_into().unwrap(), + ) + } + + pub fn create_for_testing_w_strk_gas_prices( + eth_gas_price: Option, + strk_gas_price: Option, + eth_data_gas_price: Option, + strk_data_gas_price: Option, + ) -> Self { + Self::new( + eth_gas_price.unwrap_or(DEFAULT_ETH_L1_GAS_PRICE).try_into().unwrap(), + strk_gas_price.unwrap_or(DEFAULT_STRK_L1_GAS_PRICE).try_into().unwrap(), + eth_data_gas_price.unwrap_or(DEFAULT_ETH_L1_DATA_GAS_PRICE).try_into().unwrap(), + strk_data_gas_price.unwrap_or(DEFAULT_STRK_L1_DATA_GAS_PRICE).try_into().unwrap(), + ) + } +} + impl BlockContext { pub fn create_for_testing() -> Self { Self { diff --git a/crates/blockifier/src/transaction/account_transactions_test.rs b/crates/blockifier/src/transaction/account_transactions_test.rs index 5e99b92386..e496056bf3 100644 --- a/crates/blockifier/src/transaction/account_transactions_test.rs +++ b/crates/blockifier/src/transaction/account_transactions_test.rs @@ -1005,7 +1005,8 @@ fn test_insufficient_max_fee_reverts( .unwrap(); assert!(!tx_execution_info1.is_reverted()); let actual_fee_depth1 = tx_execution_info1.transaction_receipt.fee; - let gas_price = u128::from(block_context.block_info.gas_prices.strk_l1_gas_price); + let gas_price = + u128::from(block_context.block_info.gas_prices.get_gas_price_by_fee_type(&FeeType::Strk)); let gas_ammount = u64::try_from(actual_fee_depth1.0 / gas_price).unwrap(); // Invoke the `recurse` function with depth of 2 and the actual fee of depth 1 as max_fee. diff --git a/crates/blockifier/src/transaction/transactions_test.rs b/crates/blockifier/src/transaction/transactions_test.rs index 6e7ef6058c..9e89b6c736 100644 --- a/crates/blockifier/src/transaction/transactions_test.rs +++ b/crates/blockifier/src/transaction/transactions_test.rs @@ -912,7 +912,8 @@ fn test_insufficient_resource_bounds( let gas_prices = &block_context.block_info.gas_prices; // TODO(Aner, 21/01/24) change to linear combination. - let minimal_fee = Fee(minimal_l1_gas * u128::from(gas_prices.eth_l1_gas_price)); + let minimal_fee = + Fee(minimal_l1_gas * u128::from(gas_prices.get_gas_price_by_fee_type(&FeeType::Eth))); // Max fee too low (lower than minimal estimated fee). let invalid_max_fee = Fee(minimal_fee.0 - 1); let invalid_v1_tx = account_invoke_tx( @@ -930,7 +931,7 @@ fn test_insufficient_resource_bounds( ); // Test V3 transaction. - let actual_strk_l1_gas_price = gas_prices.strk_l1_gas_price; + let actual_strk_l1_gas_price = gas_prices.get_gas_price_by_fee_type(&FeeType::Strk); // Max L1 gas amount too low. // TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion works. @@ -997,7 +998,7 @@ fn test_actual_fee_gt_resource_bounds( let minimal_l1_gas = estimate_minimal_gas_vector(block_context, tx).unwrap().l1_gas; let minimal_resource_bounds = l1_resource_bounds( u64::try_from(minimal_l1_gas).unwrap(), - u128::from(block_context.block_info.gas_prices.strk_l1_gas_price), + u128::from(block_context.block_info.gas_prices.get_gas_price_by_fee_type(&FeeType::Strk)), ); // The estimated minimal fee is lower than the actual fee. let invalid_tx = account_invoke_tx( @@ -1009,8 +1010,10 @@ fn test_actual_fee_gt_resource_bounds( // Test error. assert!(execution_error.starts_with("Insufficient max L1 gas:")); // Test that fee was charged. - let minimal_fee = - Fee(minimal_l1_gas * u128::from(block_context.block_info.gas_prices.strk_l1_gas_price)); + let minimal_fee = Fee(minimal_l1_gas + * u128::from( + block_context.block_info.gas_prices.get_gas_price_by_fee_type(&FeeType::Strk), + )); assert_eq!(execution_result.transaction_receipt.fee, minimal_fee); } diff --git a/crates/gateway/src/rpc_objects.rs b/crates/gateway/src/rpc_objects.rs index 15adf23c15..d6898d024f 100644 --- a/crates/gateway/src/rpc_objects.rs +++ b/crates/gateway/src/rpc_objects.rs @@ -85,12 +85,12 @@ impl TryInto for BlockHeader { block_number: self.block_number, sequencer_address: self.sequencer_address, block_timestamp: self.timestamp, - gas_prices: GasPrices { - eth_l1_gas_price: parse_gas_price(self.l1_gas_price.price_in_wei)?, - strk_l1_gas_price: parse_gas_price(self.l1_gas_price.price_in_fri)?, - eth_l1_data_gas_price: parse_gas_price(self.l1_data_gas_price.price_in_wei)?, - strk_l1_data_gas_price: parse_gas_price(self.l1_data_gas_price.price_in_fri)?, - }, + gas_prices: GasPrices::new( + parse_gas_price(self.l1_gas_price.price_in_wei)?, + parse_gas_price(self.l1_gas_price.price_in_fri)?, + parse_gas_price(self.l1_data_gas_price.price_in_wei)?, + parse_gas_price(self.l1_data_gas_price.price_in_fri)?, + ), use_kzg_da: matches!(self.l1_da_mode, L1DataAvailabilityMode::Blob), }) } diff --git a/crates/native_blockifier/src/py_state_diff.rs b/crates/native_blockifier/src/py_state_diff.rs index e312c8581b..634f6baac0 100644 --- a/crates/native_blockifier/src/py_state_diff.rs +++ b/crates/native_blockifier/src/py_state_diff.rs @@ -172,48 +172,36 @@ impl TryFrom for BlockInfo { block_number: BlockNumber(block_info.block_number), block_timestamp: BlockTimestamp(block_info.block_timestamp), sequencer_address: ContractAddress::try_from(block_info.sequencer_address.0)?, - gas_prices: GasPrices { - eth_l1_gas_price: block_info.l1_gas_price.price_in_wei.try_into().map_err( - |_| { - NativeBlockifierInputError::InvalidNativeBlockifierInputError( - InvalidNativeBlockifierInputError::InvalidGasPriceWei( - block_info.l1_gas_price.price_in_wei, - ), - ) - }, - )?, - strk_l1_gas_price: block_info.l1_gas_price.price_in_fri.try_into().map_err( - |_| { - NativeBlockifierInputError::InvalidNativeBlockifierInputError( - InvalidNativeBlockifierInputError::InvalidGasPriceFri( - block_info.l1_gas_price.price_in_fri, - ), - ) - }, - )?, - eth_l1_data_gas_price: block_info - .l1_data_gas_price - .price_in_wei - .try_into() - .map_err(|_| { - NativeBlockifierInputError::InvalidNativeBlockifierInputError( - InvalidNativeBlockifierInputError::InvalidDataGasPriceWei( - block_info.l1_data_gas_price.price_in_wei, - ), - ) - })?, - strk_l1_data_gas_price: block_info - .l1_data_gas_price - .price_in_fri - .try_into() - .map_err(|_| { - NativeBlockifierInputError::InvalidNativeBlockifierInputError( - InvalidNativeBlockifierInputError::InvalidDataGasPriceFri( - block_info.l1_data_gas_price.price_in_fri, - ), - ) - })?, - }, + gas_prices: GasPrices::new( + block_info.l1_gas_price.price_in_wei.try_into().map_err(|_| { + NativeBlockifierInputError::InvalidNativeBlockifierInputError( + InvalidNativeBlockifierInputError::InvalidGasPriceWei( + block_info.l1_gas_price.price_in_wei, + ), + ) + })?, + block_info.l1_gas_price.price_in_fri.try_into().map_err(|_| { + NativeBlockifierInputError::InvalidNativeBlockifierInputError( + InvalidNativeBlockifierInputError::InvalidGasPriceFri( + block_info.l1_gas_price.price_in_fri, + ), + ) + })?, + block_info.l1_data_gas_price.price_in_wei.try_into().map_err(|_| { + NativeBlockifierInputError::InvalidNativeBlockifierInputError( + InvalidNativeBlockifierInputError::InvalidDataGasPriceWei( + block_info.l1_data_gas_price.price_in_wei, + ), + ) + })?, + block_info.l1_data_gas_price.price_in_fri.try_into().map_err(|_| { + NativeBlockifierInputError::InvalidNativeBlockifierInputError( + InvalidNativeBlockifierInputError::InvalidDataGasPriceFri( + block_info.l1_data_gas_price.price_in_fri, + ), + ) + })?, + ), use_kzg_da: block_info.use_kzg_da, }) } diff --git a/crates/papyrus_execution/src/lib.rs b/crates/papyrus_execution/src/lib.rs index 46536125d4..3094f81820 100644 --- a/crates/papyrus_execution/src/lib.rs +++ b/crates/papyrus_execution/src/lib.rs @@ -354,16 +354,12 @@ fn create_block_context( use_kzg_da, block_number, // TODO(yair): What to do about blocks pre 0.13.1 where the data gas price were 0? - gas_prices: GasPrices { - eth_l1_gas_price: NonZeroU128::new(l1_gas_price.price_in_wei.0) - .unwrap_or(NonZeroU128::MIN), - strk_l1_gas_price: NonZeroU128::new(l1_gas_price.price_in_fri.0) - .unwrap_or(NonZeroU128::MIN), - eth_l1_data_gas_price: NonZeroU128::new(l1_data_gas_price.price_in_wei.0) - .unwrap_or(NonZeroU128::MIN), - strk_l1_data_gas_price: NonZeroU128::new(l1_data_gas_price.price_in_fri.0) - .unwrap_or(NonZeroU128::MIN), - }, + gas_prices: GasPrices::new( + NonZeroU128::new(l1_gas_price.price_in_wei.0).unwrap_or(NonZeroU128::MIN), + NonZeroU128::new(l1_gas_price.price_in_fri.0).unwrap_or(NonZeroU128::MIN), + NonZeroU128::new(l1_data_gas_price.price_in_wei.0).unwrap_or(NonZeroU128::MIN), + NonZeroU128::new(l1_data_gas_price.price_in_fri.0).unwrap_or(NonZeroU128::MIN), + ), }; let chain_info = ChainInfo { chain_id, diff --git a/crates/papyrus_execution/src/objects.rs b/crates/papyrus_execution/src/objects.rs index 96d2e627a8..2a1aabaff1 100644 --- a/crates/papyrus_execution/src/objects.rs +++ b/crates/papyrus_execution/src/objects.rs @@ -9,7 +9,7 @@ use blockifier::execution::call_info::{ Retdata as BlockifierRetdata, }; use blockifier::execution::entry_point::CallType as BlockifierCallType; -use blockifier::transaction::objects::{GasVector, TransactionExecutionInfo}; +use blockifier::transaction::objects::{FeeType, GasVector, TransactionExecutionInfo}; use cairo_vm::types::builtin_name::BuiltinName; use cairo_vm::vm::runners::cairo_runner::ExecutionResources as VmExecutionResources; use indexmap::IndexMap; @@ -158,16 +158,14 @@ pub(crate) fn tx_execution_output_to_fee_estimation( block_context: &BlockContext, ) -> ExecutionResult { let gas_prices = &block_context.block_info().gas_prices; - let (gas_price, data_gas_price) = match tx_execution_output.price_unit { - PriceUnit::Wei => ( - GasPrice(gas_prices.eth_l1_gas_price.get()), - GasPrice(gas_prices.eth_l1_data_gas_price.get()), - ), - PriceUnit::Fri => ( - GasPrice(gas_prices.strk_l1_gas_price.get()), - GasPrice(gas_prices.strk_l1_data_gas_price.get()), - ), + let fee_type = match tx_execution_output.price_unit { + PriceUnit::Wei => FeeType::Eth, + PriceUnit::Fri => FeeType::Strk, }; + let (gas_price, data_gas_price) = ( + GasPrice(gas_prices.get_gas_price_by_fee_type(&fee_type).get()), + GasPrice(gas_prices.get_data_gas_price_by_fee_type(&fee_type).get()), + ); let gas_vector = tx_execution_output.execution_info.transaction_receipt.gas;