Repository: lambdaclass/ethrex (rust)

Issue:
Add correct deposit contract for public testnets
- Add correct deposit contract for Holesky
- Verify other deposit contracts addresses for testnets
- We probably should also remove `MAINNET_DEPOSIT_CONTRACT_ADDRESS` constant as it is confusing.
- If the genesis file / config doesn't contain a deposit contract, should we crash the node? Will this break tests?

Pull request:
feat(l1): enforce deposit contract address
**Motivation**

To avoid issues mixing the `DepositContractAddress` across different networks.

**Description**

- Enforce setting `deposit_contract_address` from the genesis files.
- Remove the `MAINNET_DEPOSIT_CONTRACT_ADDRESS` constant.
- Update unit tests to use a mock address.
- Update the `network_params` files to include the `deposit_contract_address`.
- Add the correct `deposit_contract_address` for Holesky.

Closes #2082


Patch:
diff --git a/.github/config/assertoor/network_params_blob.yaml b/.github/config/assertoor/network_params_blob.yaml
index 3b6a6dcb1..884e17739 100644
--- a/.github/config/assertoor/network_params_blob.yaml
+++ b/.github/config/assertoor/network_params_blob.yaml
@@ -10,6 +10,10 @@ participants:
     cl_image: sigp/lighthouse:v7.0.0-beta.0
     validator_count: 32
 
+network_params:
+  # The address of the staking contract address on the Eth1 chain
+  deposit_contract_address: "0x4242424242424242424242424242424242424242"
+
 additional_services:
   - assertoor
   - tx_spammer
diff --git a/.github/config/assertoor/network_params_tx.yaml b/.github/config/assertoor/network_params_tx.yaml
index e24a8b6db..d033b8d90 100644
--- a/.github/config/assertoor/network_params_tx.yaml
+++ b/.github/config/assertoor/network_params_tx.yaml
@@ -16,6 +16,9 @@ additional_services:
 network_params:
   electra_fork_epoch: 1
 
+  # The address of the staking contract address on the Eth1 chain
+  deposit_contract_address: "0x4242424242424242424242424242424242424242"
+
 assertoor_params:
   run_stability_check: false
   run_block_proposal_check: false
diff --git a/.github/workflows/ci_levm.yaml b/.github/workflows/ci_levm.yaml
index 5f94cb7da..dcdb50e79 100644
--- a/.github/workflows/ci_levm.yaml
+++ b/.github/workflows/ci_levm.yaml
@@ -113,6 +113,14 @@ jobs:
           name: main-ef-test-data
           path: crates/vm/levm/test_result_main_short.txt
 
+      # This is for ensuring test from merge to Prague are passing.
+      # After adding the Legacy Test suite, not all are passing.
+      # This is a temporary solution until we fix the legacy tests.
+      - name: Check EF-TESTS from London to Prague is 100%
+        run: |
+          cd crates/vm/levm
+          awk '/Prague:/, /London:/ {print $1, $3}' test_result_main.txt | sed 's/[()]//g' | grep -v '100.00%' && echo "All percentage are not 100%." && exit 1 || echo "All percentage are 100%."
+
       - name: Check EF-TESTS status is 100%
         run: |
           cd crates/vm/levm
diff --git a/cmd/ethrex/networks/holesky/genesis.json b/cmd/ethrex/networks/holesky/genesis.json
index 51f93c164..eda73b0a2 100644
--- a/cmd/ethrex/networks/holesky/genesis.json
+++ b/cmd/ethrex/networks/holesky/genesis.json
@@ -16,7 +16,8 @@
     "terminalTotalDifficultyPassed": true,
     "shanghaiTime": 1696000704,
     "pragueTime": 1740434112,
-    "cancunTime": 1707305664
+    "cancunTime": 1707305664,
+    "depositContractAddress": "0x4242424242424242424242424242424242424242"
   },
   "alloc": {
     "0x0000000000000000000000000000000000000000": {
diff --git a/crates/common/constants.rs b/crates/common/constants.rs
index 8df065524..f91794016 100644
--- a/crates/common/constants.rs
+++ b/crates/common/constants.rs
@@ -1,5 +1,3 @@
-use ethereum_types::Address;
-
 // === EIP-4844 constants ===
 
 /// Gas consumption of a single data blob (== blob byte size).
@@ -7,9 +5,3 @@ pub const GAS_PER_BLOB: u64 = 1 << 17;
 
 // Minimum base fee per blob
 pub const MIN_BASE_FEE_PER_BLOB_GAS: u64 = 1;
-
-// === General use constants ===
-
-lazy_static::lazy_static! {
-    pub static ref MAINNET_DEPOSIT_CONTRACT_ADDRESS: Address = Address::from_slice(&hex::decode("00000000219ab540356cbb839cbe05303d7705fa").unwrap());
-}
diff --git a/crates/common/types/genesis.rs b/crates/common/types/genesis.rs
index 7ae2d894e..a4e601544 100644
--- a/crates/common/types/genesis.rs
+++ b/crates/common/types/genesis.rs
@@ -135,7 +135,7 @@ pub struct ChainConfig {
     #[serde(default)]
     pub blob_schedule: BlobSchedule,
     // Deposits system contract address
-    pub deposit_contract_address: Option<Address>,
+    pub deposit_contract_address: Address,
 }
 
 #[repr(u8)]
@@ -378,6 +378,8 @@ mod tests {
     use std::str::FromStr;
     use std::{fs::File, io::BufReader};
 
+    use ethereum_types::H160;
+
     use crate::types::INITIAL_BASE_FEE;
 
     use super::*;
@@ -410,6 +412,8 @@ mod tests {
             prague_time: Some(1718232101),
             terminal_total_difficulty: Some(0),
             terminal_total_difficulty_passed: true,
+            deposit_contract_address: H160::from_str("0x4242424242424242424242424242424242424242")
+                .unwrap(),
             // Note this BlobSchedule config is not the default
             blob_schedule: BlobSchedule {
                 cancun: ForkBlobSchedule {
@@ -577,7 +581,8 @@ mod tests {
                     "max": 4,
                     "baseFeeUpdateFraction": 20000
                   }
-                }
+                },
+                "depositContractAddress": "0x4242424242424242424242424242424242424242"
             }
             "#;
 
@@ -597,6 +602,8 @@ mod tests {
                     base_fee_update_fraction: 20000,
                 },
             },
+            deposit_contract_address: H160::from_str("0x4242424242424242424242424242424242424242")
+                .unwrap(),
             ..Default::default()
         };
         assert_eq!(&config, &expected_chain_config);
@@ -606,7 +613,8 @@ mod tests {
     fn deserialize_chain_config_missing_entire_blob_schedule() {
         let json = r#"
             {
-                "chainId": 123
+                "chainId": 123,
+                "depositContractAddress": "0x4242424242424242424242424242424242424242"
             }
             "#;
 
@@ -626,6 +634,8 @@ mod tests {
                     base_fee_update_fraction: 5007716,
                 },
             },
+            deposit_contract_address: H160::from_str("0x4242424242424242424242424242424242424242")
+                .unwrap(),
             ..Default::default()
         };
         assert_eq!(&config, &expected_chain_config);
@@ -642,7 +652,8 @@ mod tests {
                       "max": 4,
                       "baseFeeUpdateFraction": 20000
                     }
-                }
+                },
+                "depositContractAddress": "0x4242424242424242424242424242424242424242"
             }
             "#;
 
@@ -662,6 +673,8 @@ mod tests {
                     base_fee_update_fraction: 20000,
                 },
             },
+            deposit_contract_address: H160::from_str("0x4242424242424242424242424242424242424242")
+                .unwrap(),
             ..Default::default()
         };
         assert_eq!(&config, &expected_chain_config);
@@ -678,7 +691,8 @@ mod tests {
                     "max": 2,
                     "baseFeeUpdateFraction": 10000
                   }
-                }
+                },
+                "depositContractAddress": "0x4242424242424242424242424242424242424242"
             }
             "#;
 
@@ -698,8 +712,26 @@ mod tests {
                     base_fee_update_fraction: 5007716,
                 },
             },
+            deposit_contract_address: H160::from_str("0x4242424242424242424242424242424242424242")
+                .unwrap(),
             ..Default::default()
         };
         assert_eq!(&config, &expected_chain_config);
     }
+
+    #[test]
+    fn deserialize_chain_config_missing_deposit_contract_address() {
+        let json = r#"
+            {
+                "chainId": 123
+            }
+            "#;
+
+        let result: Result<ChainConfig, _> = serde_json::from_str(json);
+
+        assert!(result.is_err());
+
+        let error_message = result.unwrap_err().to_string();
+        assert!(error_message.contains("missing field `depositContractAddress`"),);
+    }
 }
diff --git a/crates/l2/prover/bench/src/constants.rs b/crates/l2/prover/bench/src/constants.rs
index 1c8f774aa..da6dc4e8f 100644
--- a/crates/l2/prover/bench/src/constants.rs
+++ b/crates/l2/prover/bench/src/constants.rs
@@ -2,10 +2,7 @@
 
 use std::time::Duration;
 
-use ethrex_common::{
-    constants::MAINNET_DEPOSIT_CONTRACT_ADDRESS,
-    types::{BlobSchedule, ChainConfig},
-};
+use ethrex_common::types::{BlobSchedule, ChainConfig};
 use revm_primitives::SpecId;
 
 use lazy_static::lazy_static;
@@ -38,7 +35,8 @@ pub static ref CANCUN_CONFIG: ChainConfig = ChainConfig {
     terminal_total_difficulty_passed: false,
     verkle_time: None,
     blob_schedule: BlobSchedule::default(),
-        deposit_contract_address: Some(*MAINNET_DEPOSIT_CONTRACT_ADDRESS)
+    // Mainnet address
+    deposit_contract_address: H160::from_str("0x00000000219ab540356cbb839cbe05303d7705fa")
 };
 }
 pub const MAINNET_CHAIN_ID: u64 = 0x1;
diff --git a/crates/networking/rpc/rpc.rs b/crates/networking/rpc/rpc.rs
index b55082d44..0e5225eaf 100644
--- a/crates/networking/rpc/rpc.rs
+++ b/crates/networking/rpc/rpc.rs
@@ -460,13 +460,14 @@ mod tests {
     use crate::utils::test_utils::{example_local_node_record, example_p2p_node};
     use ethrex_blockchain::Blockchain;
     use ethrex_common::{
-        constants::MAINNET_DEPOSIT_CONTRACT_ADDRESS,
         types::{ChainConfig, Genesis},
+        H160,
     };
     use ethrex_storage::{EngineType, Store};
     use sha3::{Digest, Keccak256};
     use std::fs::File;
     use std::io::BufReader;
+    use std::str::FromStr;
 
     #[cfg(feature = "based")]
     use crate::{EngineClient, EthClient};
@@ -547,7 +548,7 @@ mod tests {
                         "terminalTotalDifficulty": 0,
                         "terminalTotalDifficultyPassed": true,
                         "blobSchedule": blob_schedule,
-                        "depositContractAddress": *MAINNET_DEPOSIT_CONTRACT_ADDRESS
+                        "depositContractAddress": H160::from_str("0x00000000219ab540356cbb839cbe05303d7705fa").unwrap(),
                     }
                 },
             }
@@ -665,7 +666,8 @@ mod tests {
             prague_time: Some(1718232101),
             terminal_total_difficulty: Some(0),
             terminal_total_difficulty_passed: true,
-            deposit_contract_address: Some(*MAINNET_DEPOSIT_CONTRACT_ADDRESS),
+            deposit_contract_address: H160::from_str("0x00000000219ab540356cbb839cbe05303d7705fa")
+                .unwrap(),
             ..Default::default()
         }
     }
diff --git a/crates/storage/store.rs b/crates/storage/store.rs
index 3b241fd33..c282efc1e 100644
--- a/crates/storage/store.rs
+++ b/crates/storage/store.rs
@@ -8,10 +8,10 @@ use crate::store_db::redb::RedBStore;
 use bytes::Bytes;
 
 use ethereum_types::{Address, H256, U256};
-use ethrex_common::types::payload::PayloadBundle;
 use ethrex_common::types::{
-    code_hash, AccountInfo, AccountState, Block, BlockBody, BlockHash, BlockHeader, BlockNumber,
-    ChainConfig, Genesis, GenesisAccount, Index, Receipt, Transaction, EMPTY_TRIE_HASH,
+    code_hash, payload::PayloadBundle, AccountInfo, AccountState, Block, BlockBody, BlockHash,
+    BlockHeader, BlockNumber, ChainConfig, Genesis, GenesisAccount, Index, Receipt, Transaction,
+    EMPTY_TRIE_HASH,
 };
 use ethrex_rlp::decode::RLPDecode;
 use ethrex_rlp::encode::RLPEncode;
@@ -1040,7 +1040,7 @@ mod tests {
     use ethereum_types::{H256, U256};
     use ethrex_common::{
         types::{Transaction, TxType, EMPTY_KECCACK_HASH},
-        Bloom,
+        Bloom, H160,
     };
     use ethrex_rlp::decode::RLPDecode;
     use std::{fs, panic, str::FromStr};
@@ -1333,6 +1333,8 @@ mod tests {
             prague_time: Some(1718232101),
             terminal_total_difficulty: Some(58750000000000000000000),
             terminal_total_difficulty_passed: true,
+            deposit_contract_address: H160::from_str("0x4242424242424242424242424242424242424242")
+                .unwrap(),
             ..Default::default()
         }
     }
diff --git a/crates/vm/backends/levm/mod.rs b/crates/vm/backends/levm/mod.rs
index ba403e821..8553ddffc 100644
--- a/crates/vm/backends/levm/mod.rs
+++ b/crates/vm/backends/levm/mod.rs
@@ -506,10 +506,6 @@ pub fn extract_all_requests_levm(
         }
     }
 
-    let deposit_contract_address = config.deposit_contract_address.ok_or(EvmError::Custom(
-        "deposit_contract_address config is missing".to_string(),
-    ))?;
-
     let withdrawals_data: Vec<u8> = match LEVM::read_withdrawal_requests(header, store, cache) {
         Some(report) => {
             // the cache is updated inside the generic_system_call
@@ -527,7 +523,7 @@ pub fn extract_all_requests_levm(
             None => Default::default(),
         };
 
-    let deposits = Requests::from_deposit_receipts(deposit_contract_address, receipts);
+    let deposits = Requests::from_deposit_receipts(config.deposit_contract_address, receipts);
     let withdrawals = Requests::from_withdrawals_data(withdrawals_data);
     let consolidation = Requests::from_consolidation_data(consolidation_data);
 
diff --git a/crates/vm/backends/revm/mod.rs b/crates/vm/backends/revm/mod.rs
index b3219c223..f94ecddc2 100644
--- a/crates/vm/backends/revm/mod.rs
+++ b/crates/vm/backends/revm/mod.rs
@@ -758,11 +758,7 @@ pub fn extract_all_requests(
         }
     }
 
-    let deposit_contract_address = config.deposit_contract_address.ok_or(EvmError::Custom(
-        "deposit_contract_address config is missing".to_string(),
-    ))?;
-
-    let deposits = Requests::from_deposit_receipts(deposit_contract_address, receipts);
+    let deposits = Requests::from_deposit_receipts(config.deposit_contract_address, receipts);
     let withdrawals_data = REVM::read_withdrawal_requests(header, state);
     let consolidation_data = REVM::dequeue_consolidation_requests(header, state);
 
diff --git a/crates/vm/levm/Makefile b/crates/vm/levm/Makefile
index 5a8645220..ec9e80de6 100644
--- a/crates/vm/levm/Makefile
+++ b/crates/vm/levm/Makefile
@@ -24,8 +24,8 @@ ETH_TEST_URL := https://github.com/ethereum/tests.git
 ETH_TEST_TAG := v14.1
 COMMIT_LEGACY_TESTS_FOR_TAG := b2e6c9e
 
-STATETEST_VERSION := pectra-devnet-5%40v1.1.0
-STATETEST_NET := pectra-devnet-5
+STATETEST_VERSION := pectra-devnet-6%40v1.0.0
+STATETEST_NET := pectra-devnet-6
 STATETEST_ARTIFACT := fixtures_$(STATETEST_NET).tar.gz
 STATETEST_URL := https://github.com/ethereum/execution-spec-tests/releases/download/$(STATETEST_VERSION)/fixtures_$(STATETEST_NET).tar.gz
 
diff --git a/crates/vm/levm/src/hooks/default_hook.rs b/crates/vm/levm/src/hooks/default_hook.rs
index 2669192cc..ffeb1d491 100644
--- a/crates/vm/levm/src/hooks/default_hook.rs
+++ b/crates/vm/levm/src/hooks/default_hook.rs
@@ -363,14 +363,14 @@ impl Hook for DefaultHook {
 
         // 2. Return unused gas + gas refunds to the sender.
         let max_gas = vm.env.gas_limit;
-        let consumed_gas = report.gas_used;
+        let mut consumed_gas = report.gas_used;
         // [EIP-3529](https://eips.ethereum.org/EIPS/eip-3529)
         let quotient = if vm.env.config.fork < Fork::London {
             MAX_REFUND_QUOTIENT_PRE_LONDON
         } else {
             MAX_REFUND_QUOTIENT
         };
-        let refunded_gas = report.gas_refunded.min(
+        let mut refunded_gas = report.gas_refunded.min(
             consumed_gas
                 .checked_div(quotient)
                 .ok_or(VMError::Internal(InternalError::UndefinedState(-1)))?,
@@ -378,6 +378,15 @@ impl Hook for DefaultHook {
         // "The max refundable proportion of gas was reduced from one half to one fifth by EIP-3529 by Buterin and Swende [2021] in the London release"
         report.gas_refunded = refunded_gas;
 
+        if vm.env.config.fork >= Fork::Prague {
+            let floor_gas_price = vm.get_floor_gas_price(initial_call_frame)?;
+            let execution_gas_used = consumed_gas.saturating_sub(refunded_gas);
+            if floor_gas_price > execution_gas_used {
+                consumed_gas = floor_gas_price;
+                refunded_gas = 0;
+            }
+        }
+
         let gas_to_return = max_gas
             .checked_sub(consumed_gas)
             .and_then(|gas| gas.checked_add(refunded_gas))
diff --git a/crates/vm/levm/src/opcode_handlers/environment.rs b/crates/vm/levm/src/opcode_handlers/environment.rs
index 5f296f98e..7d1b710c6 100644
--- a/crates/vm/levm/src/opcode_handlers/environment.rs
+++ b/crates/vm/levm/src/opcode_handlers/environment.rs
@@ -1,10 +1,9 @@
 use crate::{
     call_frame::CallFrame,
-    constants::SET_CODE_DELEGATION_BYTES,
     errors::{InternalError, OpcodeResult, VMError},
     gas_cost::{self},
     memory::{self, calculate_memory_size},
-    utils::{access_account, has_delegation, word_to_address},
+    utils::{access_account, word_to_address},
     vm::VM,
 };
 use ethrex_common::{types::Fork, U256};
@@ -294,19 +293,14 @@ impl VM {
             address,
         );
 
-        // https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
-        let is_delegation = has_delegation(&account_info)?;
-
         current_call_frame.increase_consumed_gas(gas_cost::extcodesize(
             address_was_cold,
             self.env.config.fork,
         )?)?;
 
-        current_call_frame.stack.push(if is_delegation {
-            SET_CODE_DELEGATION_BYTES[..2].len().into()
-        } else {
-            account_info.bytecode.len().into()
-        })?;
+        current_call_frame
+            .stack
+            .push(account_info.bytecode.len().into())?;
 
         Ok(OpcodeResult::Continue { pc_increment: 1 })
     }
@@ -334,9 +328,6 @@ impl VM {
 
         let new_memory_size = calculate_memory_size(dest_offset, size)?;
 
-        // https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
-        let is_delegation = has_delegation(&account_info)?;
-
         current_call_frame.increase_consumed_gas(gas_cost::extcodecopy(
             size,
             new_memory_size,
@@ -349,11 +340,9 @@ impl VM {
             return Ok(OpcodeResult::Continue { pc_increment: 1 });
         }
 
-        let bytecode = if is_delegation {
-            SET_CODE_DELEGATION_BYTES[..2].into()
-        } else {
-            account_info.bytecode
-        };
+        // If the bytecode is a delegation designation, it will copy the marker (0xef0100) || address.
+        // https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
+        let bytecode = account_info.bytecode;
 
         let mut data = vec![0u8; size];
         if offset < bytecode.len().into() {
@@ -467,29 +456,20 @@ impl VM {
             address,
         );
 
-        // https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
-        let is_delegation = has_delegation(&account_info)?;
-
         current_call_frame.increase_consumed_gas(gas_cost::extcodehash(
             address_was_cold,
             self.env.config.fork,
         )?)?;
 
-        if is_delegation {
-            let hash =
-                U256::from_big_endian(keccak(&SET_CODE_DELEGATION_BYTES[..2]).as_fixed_bytes());
-            current_call_frame.stack.push(hash)?;
-        } else {
-            // An account is considered empty when it has no code and zero nonce and zero balance. [EIP-161]
-            if account_info.is_empty() {
-                current_call_frame.stack.push(U256::zero())?;
-                return Ok(OpcodeResult::Continue { pc_increment: 1 });
-            }
-
-            let hash = U256::from_big_endian(keccak(account_info.bytecode).as_fixed_bytes());
-            current_call_frame.stack.push(hash)?;
+        // An account is considered empty when it has no code and zero nonce and zero balance. [EIP-161]
+        if account_info.is_empty() {
+            current_call_frame.stack.push(U256::zero())?;
+            return Ok(OpcodeResult::Continue { pc_increment: 1 });
         }
 
+        let hash = U256::from_big_endian(keccak(account_info.bytecode).as_fixed_bytes());
+        current_call_frame.stack.push(hash)?;
+
         Ok(OpcodeResult::Continue { pc_increment: 1 })
     }
 }
diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs
index 178125ee7..b75b0a08f 100644
--- a/crates/vm/levm/src/vm.rs
+++ b/crates/vm/levm/src/vm.rs
@@ -26,7 +26,6 @@ use ethrex_common::{
     Address, H256, U256,
 };
 use std::{
-    cmp::max,
     collections::{HashMap, HashSet},
     fmt::Debug,
     sync::Arc,
@@ -360,42 +359,33 @@ impl VM {
         matches!(self.tx_kind, TxKind::Create)
     }
 
-    fn gas_used(
-        &self,
-        initial_call_frame: &CallFrame,
-        report: &ExecutionReport,
-    ) -> Result<u64, VMError> {
-        if self.env.config.fork >= Fork::Prague {
-            // If the transaction is a CREATE transaction, the calldata is emptied and the bytecode is assigned.
-            let calldata = if self.is_create() {
-                &initial_call_frame.bytecode
-            } else {
-                &initial_call_frame.calldata
-            };
-
-            // tokens_in_calldata = nonzero_bytes_in_calldata * 4 + zero_bytes_in_calldata
-            // tx_calldata = nonzero_bytes_in_calldata * 16 + zero_bytes_in_calldata * 4
-            // this is actually tokens_in_calldata * STANDARD_TOKEN_COST
-            // see it in https://eips.ethereum.org/EIPS/eip-7623
-            let tokens_in_calldata: u64 = gas_cost::tx_calldata(calldata, self.env.config.fork)
-                .map_err(VMError::OutOfGas)?
-                .checked_div(STANDARD_TOKEN_COST)
-                .ok_or(VMError::Internal(InternalError::DivisionError))?;
-
-            // floor_gas_price = TX_BASE_COST + TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
-            let mut floor_gas_price: u64 = tokens_in_calldata
-                .checked_mul(TOTAL_COST_FLOOR_PER_TOKEN)
-                .ok_or(VMError::Internal(InternalError::GasOverflow))?;
-
-            floor_gas_price = floor_gas_price
-                .checked_add(TX_BASE_COST)
-                .ok_or(VMError::Internal(InternalError::GasOverflow))?;
-
-            let gas_used = max(floor_gas_price, report.gas_used);
-            Ok(gas_used)
+    pub fn get_floor_gas_price(&self, initial_call_frame: &CallFrame) -> Result<u64, VMError> {
+        // If the transaction is a CREATE transaction, the calldata is emptied and the bytecode is assigned.
+        let calldata = if self.is_create() {
+            &initial_call_frame.bytecode
         } else {
-            Ok(report.gas_used)
-        }
+            &initial_call_frame.calldata
+        };
+
+        // tokens_in_calldata = nonzero_bytes_in_calldata * 4 + zero_bytes_in_calldata
+        // tx_calldata = nonzero_bytes_in_calldata * 16 + zero_bytes_in_calldata * 4
+        // this is actually tokens_in_calldata * STANDARD_TOKEN_COST
+        // see it in https://eips.ethereum.org/EIPS/eip-7623
+        let tokens_in_calldata: u64 = gas_cost::tx_calldata(calldata, self.env.config.fork)
+            .map_err(VMError::OutOfGas)?
+            .checked_div(STANDARD_TOKEN_COST)
+            .ok_or(VMError::Internal(InternalError::DivisionError))?;
+
+        // floor_gas_price = TX_BASE_COST + TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
+        let mut floor_gas_price: u64 = tokens_in_calldata
+            .checked_mul(TOTAL_COST_FLOOR_PER_TOKEN)
+            .ok_or(VMError::Internal(InternalError::GasOverflow))?;
+
+        floor_gas_price = floor_gas_price
+            .checked_add(TX_BASE_COST)
+            .ok_or(VMError::Internal(InternalError::GasOverflow))?;
+
+        Ok(floor_gas_price)
     }
 
     pub fn execute(&mut self) -> Result<ExecutionReport, VMError> {
@@ -434,8 +424,6 @@ impl VM {
 
         let mut report = self.run_execution(&mut initial_call_frame)?;
 
-        report.gas_used = self.gas_used(&initial_call_frame, &report)?;
-
         self.finalize_execution(&initial_call_frame, &mut report)?;
 
         report.new_state.clone_from(&self.cache);


Test patch:
diff --git a/cmd/ef_tests/blockchain/network.rs b/cmd/ef_tests/blockchain/network.rs
index 02f3cfc5a..26fbe5c90 100644
--- a/cmd/ef_tests/blockchain/network.rs
+++ b/cmd/ef_tests/blockchain/network.rs
@@ -1,6 +1,7 @@
-use ethrex_common::{constants::MAINNET_DEPOSIT_CONTRACT_ADDRESS, types::ChainConfig};
+use ethrex_common::{types::ChainConfig, H160};
 use lazy_static::lazy_static;
 use serde::Deserialize;
+use std::str::FromStr;
 
 // Chain config for different forks as defined on https://ethereum.github.io/execution-spec-tests/v3.0.0/consuming_tests/common_types/#fork
 lazy_static! {
@@ -43,7 +44,9 @@ lazy_static! {
     };
     pub static ref CANCUN_TO_PRAGUE_AT_15K_CONFIG: ChainConfig = ChainConfig {
         prague_time: Some(0x3a98),
-        deposit_contract_address: Some(*MAINNET_DEPOSIT_CONTRACT_ADDRESS),
+        // Mainnet address
+        deposit_contract_address: H160::from_str("0x00000000219ab540356cbb839cbe05303d7705fa")
+            .unwrap(),
         ..*CANCUN_CONFIG
     };
     pub static ref PRAGUE_CONFIG: ChainConfig = ChainConfig {
diff --git a/test_data/genesis-execution-api.json b/test_data/genesis-execution-api.json
index 22379f4df..af128f4e6 100644
--- a/test_data/genesis-execution-api.json
+++ b/test_data/genesis-execution-api.json
@@ -19,7 +19,8 @@
     "cancunTime": 0,
     "terminalTotalDifficulty": 131072,
     "terminalTotalDifficultyPassed": true,
-    "ethash": {}
+    "ethash": {},
+    "depositContractAddress": "0x4242424242424242424242424242424242424242"
   },
   "nonce": "0x0",
   "timestamp": "0x0",
diff --git a/test_data/genesis-hive.json b/test_data/genesis-hive.json
index 8340e0b75..00c73fab4 100644
--- a/test_data/genesis-hive.json
+++ b/test_data/genesis-hive.json
@@ -18,7 +18,8 @@
     "mergeNetsplitBlock": 0,
     "terminalTotalDifficulty": 131072,
     "shanghaiTime": 0,
-    "cancunTime": 0
+    "cancunTime": 0,
+    "depositContractAddress": "0x4242424242424242424242424242424242424242"
   },
   "alloc": {
     "0000000000000000000000000000000000000100": {
diff --git a/test_data/genesis-kurtosis.json b/test_data/genesis-kurtosis.json
index ce30c61b0..518aad80f 100644
--- a/test_data/genesis-kurtosis.json
+++ b/test_data/genesis-kurtosis.json
@@ -17,6 +17,7 @@
     "shanghaiTime": 0,
     "cancunTime": 0,
     "pragueTime": 1718232101,
+    "depositContractAddress": "0x4242424242424242424242424242424242424242",
     "blobSchedule": {
       "cancun": {
         "target": 2,
diff --git a/test_data/network_params.yaml b/test_data/network_params.yaml
index 6f21b2948..f28d023ab 100644
--- a/test_data/network_params.yaml
+++ b/test_data/network_params.yaml
@@ -29,6 +29,9 @@ participants:
 network_params:
   electra_fork_epoch: 1
 
+  # The address of the staking contract address on the Eth1 chain
+  deposit_contract_address: "0x4242424242424242424242424242424242424242"
+
 additional_services:
   - dora
   - el_forkmon