From 0a7daece05d43786335747dc9691d2580f946e01 Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Fri, 19 Jan 2024 11:31:58 +0000 Subject: [PATCH] Kernel/EVM: introduce fee struct for pass-through We are introducing base_fee - which touches a lot of places to introduce it properly. Since we will need to do the same in future for data_availability_fee_per_byte - and indeed additional logic for adjustment of gas_price, we introduce a containing structure. --- etherlink/kernel_evm/ethereum/src/block.rs | 36 ++++++++-- .../kernel_evm/evm_evaluation/src/runner.rs | 6 +- .../kernel_evm/evm_execution/src/handler.rs | 9 +-- etherlink/kernel_evm/evm_execution/src/lib.rs | 31 ++++----- .../evm_execution/src/precompiles.rs | 5 +- etherlink/kernel_evm/kernel/src/apply.rs | 11 +-- etherlink/kernel_evm/kernel/src/block.rs | 68 +++++++++---------- .../kernel/src/block_in_progress.rs | 2 +- etherlink/kernel_evm/kernel/src/lib.rs | 30 +++++--- etherlink/kernel_evm/kernel/src/simulation.rs | 25 +++---- 10 files changed, 126 insertions(+), 97 deletions(-) diff --git a/etherlink/kernel_evm/ethereum/src/block.rs b/etherlink/kernel_evm/ethereum/src/block.rs index bedfc68382af..f0634947b8a4 100644 --- a/etherlink/kernel_evm/ethereum/src/block.rs +++ b/etherlink/kernel_evm/ethereum/src/block.rs @@ -17,6 +17,25 @@ use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; use sha3::{Digest, Keccak256}; use tezos_smart_rollup_encoding::timestamp::Timestamp; +/// Container for fee calculation. +#[derive(Debug, Clone, Copy)] +pub struct BlockFees { + base_fee_per_gas: U256, +} + +impl BlockFees { + /// Setup fee information for the current block + pub const fn new(base_fee_per_gas: U256) -> Self { + Self { base_fee_per_gas } + } + + /// The base fee per gas for doing a transaction within the current block. + #[inline(always)] + pub const fn base_fee_per_gas(&self) -> U256 { + self.base_fee_per_gas + } +} + /// All data for an Ethereum block. /// /// This data does not change for the duration of the block. All values are @@ -31,8 +50,8 @@ pub struct BlockConstants { /// Mining difficulty of the current block. This relates to PoW, and we can set /// Gas limit for the current block. pub gas_limit: u64, - /// The base fee per gas for doing a transaction. - pub base_fee_per_gas: U256, + /// Basis of fee calculation when performing transactions in the current block. + pub block_fees: BlockFees, /// Identifier for the chain. Normally this would identify the chain (Ethereum /// main net, or some other net). We can use it to identify rollup EVM kernel. pub chain_id: U256, @@ -42,16 +61,21 @@ impl BlockConstants { /// Return the first block of the chain (genisis). /// TODO find suitable values for gas_limit et.c. /// To be done in . - pub fn first_block(timestamp: U256, chain_id: U256, base_fee_per_gas: U256) -> Self { + pub fn first_block(timestamp: U256, chain_id: U256, block_fees: BlockFees) -> Self { Self { number: U256::zero(), coinbase: H160::zero(), timestamp, gas_limit: 1u64, - base_fee_per_gas, + block_fees, chain_id, } } + + #[inline(always)] + pub const fn base_fee_per_gas(&self) -> U256 { + self.block_fees.base_fee_per_gas + } } #[derive(Debug, PartialEq, Eq, Clone)] @@ -130,14 +154,14 @@ impl L2Block { } } - pub fn constants(&self, chain_id: U256, base_fee_per_gas: U256) -> BlockConstants { + pub fn constants(&self, chain_id: U256, block_fees: BlockFees) -> BlockConstants { let timestamp = U256::from(self.timestamp.as_u64()); BlockConstants { number: self.number, coinbase: H160::zero(), timestamp, gas_limit: self.gas_limit.unwrap_or(1u64), - base_fee_per_gas, + block_fees, chain_id, } } diff --git a/etherlink/kernel_evm/evm_evaluation/src/runner.rs b/etherlink/kernel_evm/evm_evaluation/src/runner.rs index ed8d026aa223..00177a35a93d 100644 --- a/etherlink/kernel_evm/evm_evaluation/src/runner.rs +++ b/etherlink/kernel_evm/evm_evaluation/src/runner.rs @@ -11,7 +11,7 @@ use evm_execution::handler::ExecutionOutcome; use evm_execution::precompiles::{precompile_set, PrecompileBTreeMap}; use evm_execution::{run_transaction, Config, EthereumError}; -use tezos_ethereum::block::BlockConstants; +use tezos_ethereum::block::{BlockConstants, BlockFees}; use hex_literal::hex; use primitive_types::{H160, H256, U256}; @@ -195,12 +195,14 @@ fn execute_transaction( env.tx.value = *unit.transaction.value.get(test.indexes.value).unwrap(); env.tx.transact_to = unit.transaction.to; + let block_fees = BlockFees::new(env.block.basefee); + let block_constants = BlockConstants { number: env.block.number, coinbase: env.block.coinbase.to_fixed_bytes().into(), timestamp: env.block.timestamp, gas_limit: env.block.gas_limit.as_u64(), - base_fee_per_gas: env.block.basefee, + block_fees, chain_id: U256::from(1337), }; let address = env.tx.transact_to.map(|addr| addr.to_fixed_bytes().into()); diff --git a/etherlink/kernel_evm/evm_execution/src/handler.rs b/etherlink/kernel_evm/evm_execution/src/handler.rs index b7c14940a63f..45ebfa34ff0f 100644 --- a/etherlink/kernel_evm/evm_execution/src/handler.rs +++ b/etherlink/kernel_evm/evm_execution/src/handler.rs @@ -1631,7 +1631,7 @@ impl<'a, Host: Runtime> Handler for EvmHandler<'a, Host> { } fn block_base_fee_per_gas(&self) -> U256 { - self.block.base_fee_per_gas + self.block.base_fee_per_gas() } fn block_randomness(&self) -> Option { @@ -1843,6 +1843,7 @@ mod test { use primitive_types::{H160, H256}; use std::cmp::Ordering; use std::str::FromStr; + use tezos_ethereum::block::BlockFees; use tezos_smart_rollup_mock::MockHost; const DUMMY_ALLOCATED_TICKS: u64 = 1_000_000; @@ -1895,7 +1896,8 @@ mod test { } fn dummy_first_block() -> BlockConstants { - BlockConstants::first_block(U256::zero(), U256::one(), U256::from(21000)) + let block_fees = BlockFees::new(U256::from(12345)); + BlockConstants::first_block(U256::zero(), U256::one(), block_fees) } #[test] @@ -2755,8 +2757,7 @@ mod test { #[test] fn return_hash_of_zero_for_unavailable_block() { let mut mock_runtime = MockHost::default(); - let block = - BlockConstants::first_block(U256::zero(), U256::one(), U256::from(21000)); + let block = dummy_first_block(); let precompiles = precompiles::precompile_set::(); let mut evm_account_storage = init_account_storage().unwrap(); let config = Config::shanghai(); diff --git a/etherlink/kernel_evm/evm_execution/src/lib.rs b/etherlink/kernel_evm/evm_execution/src/lib.rs index 7416b6d55cd9..21a827c8204a 100644 --- a/etherlink/kernel_evm/evm_execution/src/lib.rs +++ b/etherlink/kernel_evm/evm_execution/src/lib.rs @@ -207,6 +207,7 @@ mod test { use primitive_types::{H160, H256}; use std::str::FromStr; use std::vec; + use tezos_ethereum::block::BlockFees; use tezos_ethereum::tx_common::EthereumTransactionCommon; use tezos_smart_rollup_mock::MockHost; @@ -282,7 +283,8 @@ mod test { } fn dummy_first_block() -> BlockConstants { - BlockConstants::first_block(U256::zero(), U256::one(), U256::from(21000)) + let block_fees = BlockFees::new(U256::from(12345)); + BlockConstants::first_block(U256::zero(), U256::one(), block_fees) } #[test] @@ -1969,13 +1971,13 @@ mod test { let chain_id = U256::from(42); let mut chain_id_bytes = [0u8; 32]; chain_id.to_big_endian(&mut chain_id_bytes); - let block = - BlockConstants::first_block(U256::zero(), chain_id, U256::from(21000)); + let block_fees = BlockFees::new(U256::from(54321)); + let block = BlockConstants::first_block(U256::zero(), chain_id, block_fees); let precompiles = precompiles::precompile_set::(); let mut evm_account_storage = init_evm_account_storage().unwrap(); let target = H160::from_low_u64_be(117u64); let caller = H160::from_low_u64_be(118u64); - let gas_price = U256::from(21000); + let gas_price = U256::from(12345); let code = vec![ Opcode::CHAINID.as_u8(), // cost 2 Opcode::PUSH1.as_u8(), // push ost, cost 3 @@ -2041,8 +2043,8 @@ mod test { let base_fee_per_gas = U256::from(23000); let mut base_fee_per_gas_bytes = [0u8; 32]; base_fee_per_gas.to_big_endian(&mut base_fee_per_gas_bytes); - let block = - BlockConstants::first_block(U256::zero(), U256::one(), base_fee_per_gas); + let block_fees = BlockFees::new(base_fee_per_gas); + let block = BlockConstants::first_block(U256::zero(), U256::one(), block_fees); let precompiles = precompiles::precompile_set::(); let mut evm_account_storage = init_evm_account_storage().unwrap(); let target = H160::from_low_u64_be(117u64); @@ -2285,10 +2287,8 @@ mod test { // Arrange let mut mock_runtime = MockHost::default(); let base_fee_per_gas = U256::from(23000); - let mut base_fee_per_gas_bytes = [0u8; 32]; - base_fee_per_gas.to_big_endian(&mut base_fee_per_gas_bytes); - let block = - BlockConstants::first_block(U256::zero(), U256::one(), base_fee_per_gas); + let block_fees = BlockFees::new(base_fee_per_gas); + let block = BlockConstants::first_block(U256::zero(), U256::one(), block_fees); let precompiles = precompiles::precompile_set::(); let mut evm_account_storage = init_evm_account_storage().unwrap(); let target = H160::from_low_u64_be(117u64); @@ -2344,10 +2344,8 @@ mod test { // Arrange let mut mock_runtime = MockHost::default(); let base_fee_per_gas = U256::from(23000); - let mut base_fee_per_gas_bytes = [0u8; 32]; - base_fee_per_gas.to_big_endian(&mut base_fee_per_gas_bytes); - let block = - BlockConstants::first_block(U256::zero(), U256::one(), base_fee_per_gas); + let block_fees = BlockFees::new(base_fee_per_gas); + let block = BlockConstants::first_block(U256::zero(), U256::one(), block_fees); let precompiles = precompiles::precompile_set::(); let mut evm_account_storage = init_evm_account_storage().unwrap(); let target = H160::from_low_u64_be(117u64); @@ -2400,9 +2398,8 @@ mod test { fn first_block() -> BlockConstants { let base_fee_per_gas = U256::from(23000); - let mut base_fee_per_gas_bytes = [0u8; 32]; - base_fee_per_gas.to_big_endian(&mut base_fee_per_gas_bytes); - BlockConstants::first_block(U256::zero(), U256::one(), base_fee_per_gas) + let block_fees = BlockFees::new(base_fee_per_gas); + BlockConstants::first_block(U256::zero(), U256::one(), block_fees) } fn deploy( diff --git a/etherlink/kernel_evm/evm_execution/src/precompiles.rs b/etherlink/kernel_evm/evm_execution/src/precompiles.rs index a9dcbc71ac82..e0a024157610 100644 --- a/etherlink/kernel_evm/evm_execution/src/precompiles.rs +++ b/etherlink/kernel_evm/evm_execution/src/precompiles.rs @@ -483,6 +483,7 @@ mod tests { use evm::Config; use primitive_types::{H160, U256}; use tezos_ethereum::block::BlockConstants; + use tezos_ethereum::block::BlockFees; use tezos_smart_rollup_encoding::contract::Contract; use tezos_smart_rollup_mock::MockHost; @@ -517,8 +518,8 @@ mod tests { ) -> Result { let caller = H160::from_low_u64_be(118u64); let mut mock_runtime = MockHost::default(); - let block = - BlockConstants::first_block(U256::zero(), U256::one(), U256::from(21000)); + let block_fees = BlockFees::new(U256::from(21000)); + let block = BlockConstants::first_block(U256::zero(), U256::one(), block_fees); let mut evm_account_storage = init_evm_account_storage().unwrap(); let precompiles = precompile_set::(); let config = Config::shanghai(); diff --git a/etherlink/kernel_evm/kernel/src/apply.rs b/etherlink/kernel_evm/kernel/src/apply.rs index b91942d1c7a3..9df9996b28ac 100644 --- a/etherlink/kernel_evm/kernel/src/apply.rs +++ b/etherlink/kernel_evm/kernel/src/apply.rs @@ -265,7 +265,7 @@ fn is_valid_ethereum_transaction_common( // EIP 1559 checks // ensure that the user was willing to at least pay the base fee // and that max is greater than both fees - if transaction.max_fee_per_gas < block_constant.base_fee_per_gas + if transaction.max_fee_per_gas < block_constant.base_fee_per_gas() || transaction.max_fee_per_gas < transaction.max_priority_fee_per_gas { log!(host, Debug, "Transaction status: ERROR_MAX_BASE_FEE"); @@ -291,7 +291,7 @@ fn apply_ethereum_transaction_common( allocated_ticks: u64, ) -> Result, anyhow::Error> { let effective_gas_price = - transaction.effective_gas_price(block_constants.base_fee_per_gas)?; + transaction.effective_gas_price(block_constants.base_fee_per_gas())?; let caller = match is_valid_ethereum_transaction_common( host, evm_account_storage, @@ -519,7 +519,7 @@ pub fn apply_transaction( caller, index, gas_used, - block_constants.base_fee_per_gas, + block_constants.base_fee_per_gas(), )?; let receipt_info = make_receipt_info( @@ -548,7 +548,7 @@ mod tests { use evm_execution::account_storage::{account_path, EthereumAccountStorage}; use primitive_types::{H160, U256}; use tezos_ethereum::{ - block::BlockConstants, + block::{BlockConstants, BlockFees}, transaction::{TransactionType, TRANSACTION_HASH_SIZE}, tx_common::EthereumTransactionCommon, }; @@ -562,10 +562,11 @@ mod tests { const CHAIN_ID: u32 = 1337; fn mock_block_constants() -> BlockConstants { + let block_fees = BlockFees::new(U256::from(12345)); BlockConstants::first_block( U256::from(Timestamp::from(0).as_u64()), CHAIN_ID.into(), - U256::from(21000), + block_fees, ) } diff --git a/etherlink/kernel_evm/kernel/src/block.rs b/etherlink/kernel_evm/kernel/src/block.rs index d622e4c44660..5aad5686a9cd 100644 --- a/etherlink/kernel_evm/kernel/src/block.rs +++ b/etherlink/kernel_evm/kernel/src/block.rs @@ -22,6 +22,7 @@ use evm_execution::account_storage::{init_account_storage, EthereumAccountStorag use evm_execution::precompiles; use evm_execution::precompiles::PrecompileBTreeMap; use primitive_types::{H256, U256}; +use tezos_ethereum::block::BlockFees; use tezos_evm_logging::{log, Level::*}; use tezos_smart_rollup_host::runtime::Runtime; use tick_model::estimate_remaining_ticks_for_transaction_execution; @@ -195,10 +196,8 @@ fn compute_bip( .context("Failed to finalize the block in progress")?; *current_block_number = new_block.number + 1; *current_block_parent_hash = new_block.hash; - *current_constants = new_block.constants( - current_constants.chain_id, - current_constants.base_fee_per_gas, - ); + *current_constants = new_block + .constants(current_constants.chain_id, current_constants.block_fees); // Drop the processed blueprint from the storage drop_head_blueprint(host)? } @@ -209,7 +208,7 @@ fn compute_bip( pub fn produce( host: &mut Host, chain_id: U256, - base_fee_per_gas: U256, + block_fees: BlockFees, config: &mut Configuration, ) -> Result { let kernel_upgrade = upgrade::read_kernel_upgrade(host)?; @@ -217,7 +216,7 @@ pub fn produce( let (mut current_constants, mut current_block_number, mut current_block_parent_hash) = match storage::read_current_block(host) { Ok(block) => ( - block.constants(chain_id, base_fee_per_gas), + block.constants(chain_id, block_fees), block.number + 1, block.hash, ), @@ -225,7 +224,7 @@ pub fn produce( let timestamp = current_timestamp(host); let timestamp = U256::from(timestamp.as_u64()); ( - BlockConstants::first_block(timestamp, chain_id, base_fee_per_gas), + BlockConstants::first_block(timestamp, chain_id, block_fees), U256::zero(), H256::from_slice(&hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()), ) @@ -303,7 +302,7 @@ mod tests { use crate::storage::{init_blocks_index, init_transaction_hashes_index}; use crate::storage::{read_transaction_receipt, read_transaction_receipt_status}; use crate::tick_model; - use crate::{retrieve_base_fee_per_gas, retrieve_chain_id}; + use crate::{retrieve_block_fees, retrieve_chain_id}; use evm_execution::account_storage::{ account_path, init_account_storage, EthereumAccountStorage, }; @@ -372,6 +371,10 @@ mod tests { const DUMMY_CHAIN_ID: U256 = U256::one(); const DUMMY_BASE_FEE_PER_GAS: u64 = 21000u64; + fn dummy_block_fees() -> BlockFees { + BlockFees::new(DUMMY_BASE_FEE_PER_GAS.into()) + } + fn dummy_eth_gen_transaction( nonce: U256, v: U256, @@ -506,7 +509,7 @@ mod tests { produce( host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -552,7 +555,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -595,7 +598,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -641,7 +644,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -719,7 +722,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -771,7 +774,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -838,7 +841,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -886,7 +889,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -925,7 +928,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -936,7 +939,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -987,7 +990,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -1026,17 +1029,10 @@ mod tests { let timestamp = current_timestamp(host); let timestamp = U256::from(timestamp.as_u64()); let chain_id = retrieve_chain_id(host); - let base_fee_per_gas = retrieve_base_fee_per_gas(host); + let block_fees = retrieve_block_fees(host); assert!(chain_id.is_ok(), "chain_id should be defined"); - assert!( - base_fee_per_gas.is_ok(), - "base_fee_per_gas should be defined" - ); - BlockConstants::first_block( - timestamp, - chain_id.unwrap(), - base_fee_per_gas.unwrap(), - ) + assert!(block_fees.is_ok(), "block fees should be defined"); + BlockConstants::first_block(timestamp, chain_id.unwrap(), block_fees.unwrap()) } #[test] @@ -1151,7 +1147,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); @@ -1201,7 +1197,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("Empty block should have been produced"); @@ -1213,7 +1209,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("Empty block should have been produced"); @@ -1225,7 +1221,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("Empty block should have been produced"); @@ -1327,7 +1323,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("Should have produced"); @@ -1384,7 +1380,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("Should have produced"); @@ -1473,7 +1469,7 @@ mod tests { produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + dummy_block_fees(), &mut Configuration::Proxy, ) .expect("The block production failed."); diff --git a/etherlink/kernel_evm/kernel/src/block_in_progress.rs b/etherlink/kernel_evm/kernel/src/block_in_progress.rs index 5ad9d7c0c34b..287b82cd7599 100644 --- a/etherlink/kernel_evm/kernel/src/block_in_progress.rs +++ b/etherlink/kernel_evm/kernel/src/block_in_progress.rs @@ -213,7 +213,7 @@ impl BlockInProgress { BlockInProgress::new_with_ticks( current_block_number, parent_hash, - constants.base_fee_per_gas, + constants.base_fee_per_gas(), ring, tick_counter, blueprint.timestamp, diff --git a/etherlink/kernel_evm/kernel/src/lib.rs b/etherlink/kernel_evm/kernel/src/lib.rs index f74eff6ebe90..d799859fbdcd 100644 --- a/etherlink/kernel_evm/kernel/src/lib.rs +++ b/etherlink/kernel_evm/kernel/src/lib.rs @@ -24,6 +24,7 @@ use storage::{ STORAGE_VERSION, STORAGE_VERSION_PATH, }; use tezos_crypto_rs::hash::ContractKt1Hash; +use tezos_ethereum::block::BlockFees; use tezos_evm_logging::{log, Level::*}; use tezos_smart_rollup_encoding::timestamp::Timestamp; use tezos_smart_rollup_entrypoint::kernel_entry; @@ -57,7 +58,9 @@ extern crate alloc; /// production. pub const CHAIN_ID: u32 = 1337; -// Minimal base fee per gas +/// Minimal base fee per gas +/// +/// Distinct from 'intrinsic base fee' of a simple Eth transfer: which costs 21_000 gas. pub const BASE_FEE_PER_GAS: u32 = 21_000; /// The configuration for the EVM execution. @@ -141,15 +144,19 @@ fn retrieve_chain_id(host: &mut Host) -> Result { } } } -fn retrieve_base_fee_per_gas(host: &mut Host) -> Result { - match read_base_fee_per_gas(host) { - Ok(base_fee_per_gas) => Ok(base_fee_per_gas), +fn retrieve_block_fees(host: &mut Host) -> Result { + let base_fee_per_gas = match read_base_fee_per_gas(host) { + Ok(base_fee_per_gas) => base_fee_per_gas, Err(_) => { let base_fee_per_gas = U256::from(BASE_FEE_PER_GAS); store_base_fee_per_gas(host, base_fee_per_gas)?; - Ok(base_fee_per_gas) + base_fee_per_gas } - } + }; + + let block_fees = BlockFees::new(base_fee_per_gas); + + Ok(block_fees) } fn fetch_configuration(host: &mut Host) -> anyhow::Result { @@ -210,7 +217,7 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { let ticketer = read_ticketer(host); let admin = read_admin(host); let mut configuration = fetch_configuration(host)?; - let base_fee_per_gas = retrieve_base_fee_per_gas(host)?; + let block_fees = retrieve_block_fees(host)?; // Run the stage one, this is a no-op if the inbox was already consumed // by another kernel run. This ensures that if the migration does not @@ -226,7 +233,7 @@ pub fn main(host: &mut Host) -> Result<(), anyhow::Error> { .context("Failed during stage 1")?; // Start processing blueprints - block::produce(host, chain_id, base_fee_per_gas, &mut configuration) + block::produce(host, chain_id, block_fees, &mut configuration) .map(|_| ()) .context("Failed during stage 2") } @@ -323,6 +330,7 @@ mod tests { }; use evm_execution::account_storage::{self, EthereumAccountStorage}; use primitive_types::{H160, U256}; + use tezos_ethereum::block::BlockFees; use tezos_ethereum::{ transaction::{TransactionHash, TransactionType}, tx_common::EthereumTransactionCommon, @@ -334,7 +342,7 @@ mod tests { use tezos_smart_rollup_mock::MockHost; const DUMMY_CHAIN_ID: U256 = U256::one(); - const DUMMY_BASE_FEE_PER_GAS: u64 = 21000u64; + const DUMMY_BASE_FEE_PER_GAS: u64 = 12345u64; const TOO_MANY_TRANSACTIONS: u64 = 500; fn set_balance( @@ -473,11 +481,13 @@ mod tests { crate::upgrade::store_kernel_upgrade(&mut host, &broken_kernel_upgrade) .expect("Should be able to store kernel upgrade"); + let block_fees = BlockFees::new(DUMMY_BASE_FEE_PER_GAS.into()); + // If the upgrade is started, it should raise an error crate::block::produce( &mut host, DUMMY_CHAIN_ID, - DUMMY_BASE_FEE_PER_GAS.into(), + block_fees, &mut Configuration::Proxy, ) .expect("Should have produced"); diff --git a/etherlink/kernel_evm/kernel/src/simulation.rs b/etherlink/kernel_evm/kernel/src/simulation.rs index aab55b1502d9..a45024d4c41f 100644 --- a/etherlink/kernel_evm/kernel/src/simulation.rs +++ b/etherlink/kernel_evm/kernel/src/simulation.rs @@ -11,7 +11,7 @@ use crate::tick_model::constants::MAX_TRANSACTION_GAS_LIMIT; use crate::{error::Error, error::StorageError, storage}; use crate::{ - current_timestamp, parsable, parsing, retrieve_base_fee_per_gas, retrieve_chain_id, + current_timestamp, parsable, parsing, retrieve_block_fees, retrieve_chain_id, tick_model, CONFIG, }; @@ -90,14 +90,14 @@ impl Evaluation { host: &mut Host, ) -> Result, Error> { let chain_id = retrieve_chain_id(host)?; - let base_fee_per_gas = retrieve_base_fee_per_gas(host)?; + let block_fees = retrieve_block_fees(host)?; let current_constants = match storage::read_current_block(host) { - Ok(block) => block.constants(chain_id, base_fee_per_gas), + Ok(block) => block.constants(chain_id, block_fees), Err(_) => { let timestamp = current_timestamp(host); let timestamp = U256::from(timestamp.as_u64()); - BlockConstants::first_block(timestamp, chain_id, base_fee_per_gas) + BlockConstants::first_block(timestamp, chain_id, block_fees) } }; @@ -115,7 +115,7 @@ impl Evaluation { let gas_price = if let Some(gas_price) = self.gas_price { U256::from(gas_price) } else { - crate::retrieve_base_fee_per_gas(host)? + block_fees.base_fee_per_gas() }; let outcome = evm_execution::run_transaction( @@ -215,7 +215,7 @@ impl TxValidation { Some(account) => account.nonce(host)?, None => U256::zero(), }; - let base_fee_per_gas = retrieve_base_fee_per_gas(host)?; + let block_fees = retrieve_block_fees(host)?; // Get the chain_id let chain_id = storage::read_chain_id(host)?; // Check if nonce is too low @@ -231,7 +231,7 @@ impl TxValidation { return Ok(TxValidationOutcome::GasLimitTooHigh); } // Check if the gas price is high enough - if tx.max_fee_per_gas < base_fee_per_gas + if tx.max_fee_per_gas < block_fees.base_fee_per_gas() || tx.max_fee_per_gas < tx.max_priority_fee_per_gas { return Ok(TxValidationOutcome::MaxGasFeeTooLow); @@ -438,7 +438,7 @@ mod tests { }; use tezos_smart_rollup_mock::MockHost; - use crate::{current_timestamp, retrieve_base_fee_per_gas, retrieve_chain_id}; + use crate::{current_timestamp, retrieve_block_fees, retrieve_chain_id}; use super::*; @@ -524,16 +524,13 @@ mod tests { let timestamp = U256::from(timestamp.as_u64()); let chain_id = retrieve_chain_id(host); assert!(chain_id.is_ok(), "chain_id should be defined"); - let base_fee_per_gas = retrieve_base_fee_per_gas(host); + let block_fees = retrieve_block_fees(host); assert!(chain_id.is_ok(), "chain_id should be defined"); - assert!( - base_fee_per_gas.is_ok(), - "base_fee_per_gas should be defined" - ); + assert!(block_fees.is_ok(), "block_fees should be defined"); let block = BlockConstants::first_block( timestamp, chain_id.unwrap(), - base_fee_per_gas.unwrap(), + block_fees.unwrap(), ); let precompiles = precompiles::precompile_set::(); let mut evm_account_storage = account_storage::init_account_storage().unwrap(); -- GitLab