diff --git a/crates/blockifier/src/blockifier/block.rs b/crates/blockifier/src/blockifier/block.rs index 903bc6cdd9..0ac14eecb6 100644 --- a/crates/blockifier/src/blockifier/block.rs +++ b/crates/blockifier/src/blockifier/block.rs @@ -9,6 +9,7 @@ use crate::abi::constants; use crate::state::errors::StateError; use crate::state::state_api::{State, StateResult}; use crate::transaction::objects::FeeType; +use crate::versioned_constants::{VersionedConstants, VersionedConstantsOverrides}; #[cfg(test)] #[path = "block_test.rs"] @@ -27,13 +28,50 @@ 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: NonZeroU128, // In wei. + strk_l2_gas_price: NonZeroU128, // 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 { + // TODO(Aner): get gas prices from python. + let eth_l2_gas_price = NonZeroU128::new( + VersionedConstants::get_versioned_constants(VersionedConstantsOverrides { + validate_max_n_steps: 0, + max_recursion_depth: 0, + versioned_constants_base_overrides: None, + }) + .l1_to_l2_gas_price_conversion(eth_l1_gas_price.into()), + ) + .expect("L1 to L2 price conversion error (Rust side)."); + let strk_l2_gas_price = NonZeroU128::new( + VersionedConstants::get_versioned_constants(VersionedConstantsOverrides { + validate_max_n_steps: 0, + max_recursion_depth: 0, + versioned_constants_base_overrides: None, + }) + .l1_to_l2_gas_price_conversion(strk_l1_gas_price.into()), + ) + .expect("L1 to L2 price conversion error (Rust side)."); + 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_l1_gas_price_by_fee_type(&self, fee_type: &FeeType) -> NonZeroU128 { match fee_type { FeeType::Strk => self.strk_l1_gas_price, @@ -47,6 +85,13 @@ impl GasPrices { FeeType::Eth => self.eth_l1_data_gas_price, } } + + pub fn get_l2_gas_price_by_fee_type(&self, fee_type: &FeeType) -> NonZeroU128 { + 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 bcc791f723..52ce692290 100644 --- a/crates/blockifier/src/fee/fee_test.rs +++ b/crates/blockifier/src/fee/fee_test.rs @@ -7,6 +7,7 @@ use rstest::rstest; use starknet_api::transaction::Fee; use crate::abi::constants::N_STEPS_RESOURCE; +use crate::blockifier::block::GasPrices; use crate::context::BlockContext; use crate::fee::actual_cost::TransactionReceipt; use crate::fee::fee_checks::{FeeCheckError, FeeCheckReportFields, PostExecutionReport}; @@ -14,7 +15,12 @@ use crate::fee::fee_utils::calculate_l1_gas_by_vm_usage; use crate::invoke_tx_args; use crate::test_utils::contracts::FeatureContract; use crate::test_utils::initial_test_state::test_state; -use crate::test_utils::{CairoVersion, BALANCE}; +use crate::test_utils::{ + CairoVersion, + BALANCE, + DEFAULT_ETH_L1_DATA_GAS_PRICE, + DEFAULT_ETH_L1_GAS_PRICE, +}; use crate::transaction::objects::GasVector; use crate::transaction::test_utils::{account_invoke_tx, l1_resource_bounds}; use crate::utils::u128_from_usize; @@ -122,8 +128,12 @@ fn test_discounted_gas_overdraft( #[case] expect_failure: bool, ) { 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::new( + DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(), + gas_price.try_into().unwrap(), + DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(), + data_gas_price.try_into().unwrap(), + ); 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..6b6e83b859 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, } } diff --git a/crates/blockifier/src/transaction/account_transactions_test.rs b/crates/blockifier/src/transaction/account_transactions_test.rs index 933c2bae65..35f899ca2e 100644 --- a/crates/blockifier/src/transaction/account_transactions_test.rs +++ b/crates/blockifier/src/transaction/account_transactions_test.rs @@ -1005,7 +1005,9 @@ fn test_insufficient_max_fee_reverts( .unwrap(); assert!(!tx_execution_info1.is_reverted()); let actual_fee_depth1 = tx_execution_info1.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_l1_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 4e61d1a94e..78ff672651 100644 --- a/crates/blockifier/src/transaction/transactions_test.rs +++ b/crates/blockifier/src/transaction/transactions_test.rs @@ -908,7 +908,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_l1_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( @@ -926,7 +927,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_l1_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. @@ -993,7 +994,9 @@ 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_l1_gas_price_by_fee_type(&FeeType::Strk), + ), ); // The estimated minimal fee is lower than the actual fee. let invalid_tx = account_invoke_tx( @@ -1005,8 +1008,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_l1_gas_price_by_fee_type(&FeeType::Strk), + )); assert_eq!(execution_result.receipt.fee, minimal_fee); } diff --git a/crates/blockifier/src/versioned_constants.rs b/crates/blockifier/src/versioned_constants.rs index f6b50e855c..f0caa31446 100644 --- a/crates/blockifier/src/versioned_constants.rs +++ b/crates/blockifier/src/versioned_constants.rs @@ -124,6 +124,14 @@ impl VersionedConstants { Self::get(StarknetVersion::Latest) } + /// Converts from l1 gas cost to l2 gas cost with **upward rounding** + pub fn l1_to_l2_gas_price_conversion(&self, l1_gas_price: u128) -> u128 { + let l1_to_l2_gas_price_ratio: Ratio = + Ratio::new(1, u128::from(self.os_constants.gas_costs.step_gas_cost)) + * self.vm_resource_fee_cost()["n_steps"]; + *(l1_to_l2_gas_price_ratio * l1_gas_price).ceil().numer() + } + /// Returns the initial gas of any transaction to run with. pub fn tx_initial_gas(&self) -> u64 { let os_consts = &self.os_constants; 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 f08fadcebd..6236f3d534 100644 --- a/crates/papyrus_execution/src/lib.rs +++ b/crates/papyrus_execution/src/lib.rs @@ -359,16 +359,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 2cc1f8ad55..cbcbcbd76c 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; @@ -153,16 +153,16 @@ 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()), + let (gas_price, data_gas_price) = ( + GasPrice( + gas_prices.get_l1_gas_price_by_fee_type(&tx_execution_output.price_unit.into()).get(), ), - PriceUnit::Fri => ( - GasPrice(gas_prices.strk_l1_gas_price.get()), - GasPrice(gas_prices.strk_l1_data_gas_price.get()), + GasPrice( + gas_prices + .get_l1_data_gas_price_by_fee_type(&tx_execution_output.price_unit.into()) + .get(), ), - }; + ); let gas_vector = tx_execution_output.execution_info.receipt.gas; @@ -521,3 +521,12 @@ pub enum PriceUnit { /// Fri. Fri, } + +impl From for FeeType { + fn from(value: PriceUnit) -> Self { + match value { + PriceUnit::Wei => FeeType::Eth, + PriceUnit::Fri => FeeType::Strk, + } + } +}