Skip to main content

ethrex_levm/
environment.rs

1use ethrex_common::{
2    Address, H256, U256,
3    types::{BlockHeader, ChainConfig, Fork, ForkBlobSchedule},
4};
5
6use crate::constants::{
7    BLOB_BASE_FEE_UPDATE_FRACTION, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE, MAX_BLOB_COUNT,
8    MAX_BLOB_COUNT_ELECTRA, TARGET_BLOB_GAS_PER_BLOCK, TARGET_BLOB_GAS_PER_BLOCK_PECTRA,
9};
10
11use rustc_hash::FxHashMap;
12/// [EIP-1153]: https://eips.ethereum.org/EIPS/eip-1153#reference-implementation
13pub type TransientStorage = FxHashMap<(Address, U256), U256>;
14
15#[derive(Debug, Default, Clone)]
16/// Environmental information that the execution agent must provide.
17pub struct Environment {
18    /// The sender address of the external transaction.
19    pub origin: Address,
20    /// Gas limit of the Transaction
21    pub gas_limit: u64,
22    pub config: EVMConfig,
23    pub block_number: u64,
24    /// Coinbase is the block's beneficiary - the address that receives the block rewards and fees.
25    pub coinbase: Address,
26    pub timestamp: u64,
27    pub prev_randao: Option<H256>,
28    pub difficulty: U256,
29    pub slot_number: U256,
30    pub chain_id: U256,
31    pub base_fee_per_gas: U256,
32    pub base_blob_fee_per_gas: U256,
33    pub gas_price: U256, // Effective gas price
34    pub block_excess_blob_gas: Option<u64>,
35    pub block_blob_gas_used: Option<u64>,
36    pub tx_blob_hashes: Vec<H256>,
37    pub tx_max_priority_fee_per_gas: Option<U256>,
38    pub tx_max_fee_per_gas: Option<U256>,
39    pub tx_max_fee_per_blob_gas: Option<U256>,
40    pub tx_nonce: u64,
41    pub block_gas_limit: u64,
42    pub is_privileged: bool,
43    pub fee_token: Option<Address>,
44    /// When true, skip balance deduction in `deduct_caller`. Used by the prewarmer
45    /// to avoid early reverts on insufficient balance so that warming touches more storage.
46    pub disable_balance_check: bool,
47    /// When true, skip the sender nonce-mismatch validation. Used by the simulation
48    /// RPCs (eth_call, eth_estimateGas, eth_createAccessList): call objects may omit
49    /// the nonce, and no client enforces it there. The account nonce still increments
50    /// during execution. `debug_traceCall` relies on it too (geth's
51    /// `ToMessage(_, skipNonceCheck=true)`): the synthetic call may run on top of a
52    /// mid-block state (`txIndex`) whose nonce differs from the value the caller
53    /// supplied, so enforcing the check would spuriously reject the trace.
54    pub disable_nonce_check: bool,
55    /// When true, skip the gas limits that gate a transaction's *admission* rather than
56    /// its execution: the block-level gas allowance and the EIP-7825 per-transaction cap.
57    /// Used by the simulation RPCs (eth_call, eth_estimateGas, debug_traceCall), whose
58    /// callers routinely pass a `gas` above either bound — tools commonly pass the block
59    /// gas limit — and still expect an answer, since nothing is being submitted.
60    /// This exists so `block_gas_limit` can keep the block's real value: that field is
61    /// observable through the GASLIMIT opcode and feeds the EIP-8037 cost-per-state-byte
62    /// formula, so raising it to bypass the allowance corrupts both.
63    pub disable_gas_allowance_check: bool,
64    /// When true, the tx is a pre-execution system contract call (EIP-2935, EIP-4788,
65    /// EIP-7002, EIP-7251 etc.). Skips the block-level gas-allowance check since system
66    /// calls are allowed to exceed `block_gas_limit` (their 30M cap is a separate rule).
67    pub is_system_call: bool,
68}
69
70/// This struct holds special configuration variables specific to the
71/// EVM. In most cases, at least at the time of writing (February
72/// 2025), you want to use the default blob_schedule values for the
73/// specified Fork. The "intended" way to do this is by using the `EVMConfig::canonical_values(fork: Fork)` function.
74///
75/// However, that function should NOT be used IF you want to use a
76/// custom `ForkBlobSchedule`, like it's described in [EIP-7840](https://eips.ethereum.org/EIPS/eip-7840)
77/// Values are determined by [EIP-7691](https://eips.ethereum.org/EIPS/eip-7691#specification)
78#[derive(Debug, Clone, Copy)]
79pub struct EVMConfig {
80    pub fork: Fork,
81    pub blob_schedule: ForkBlobSchedule,
82}
83
84impl EVMConfig {
85    pub fn new(fork: Fork, blob_schedule: ForkBlobSchedule) -> EVMConfig {
86        EVMConfig {
87            fork,
88            blob_schedule,
89        }
90    }
91
92    pub fn new_from_chain_config(chain_config: &ChainConfig, block_header: &BlockHeader) -> Self {
93        let fork = chain_config.fork(block_header.timestamp);
94
95        let blob_schedule = chain_config
96            .get_fork_blob_schedule(block_header.timestamp)
97            .unwrap_or_else(|| EVMConfig::canonical_values(fork));
98
99        EVMConfig::new(fork, blob_schedule)
100    }
101
102    /// This function is used for running the EF tests. If you don't
103    /// have acces to a EVMConfig (mainly in the form of a
104    /// genesis.json file) you can use this function to get the
105    /// "Default" ForkBlobSchedule for that specific Fork.
106    /// NOTE: This function could potentially be expanded to include
107    /// other types of "default"s.
108    pub fn canonical_values(fork: Fork) -> ForkBlobSchedule {
109        let max_blobs_per_block = Self::max_blobs_per_block(fork);
110        let target = Self::get_target_blob_gas_per_block_(fork);
111        let base_fee_update_fraction: u64 = Self::get_blob_base_fee_update_fraction_value(fork);
112
113        ForkBlobSchedule {
114            target,
115            max: max_blobs_per_block,
116            base_fee_update_fraction,
117        }
118    }
119
120    fn max_blobs_per_block(fork: Fork) -> u32 {
121        if fork >= Fork::Prague {
122            MAX_BLOB_COUNT_ELECTRA
123        } else {
124            MAX_BLOB_COUNT
125        }
126    }
127
128    fn get_blob_base_fee_update_fraction_value(fork: Fork) -> u64 {
129        if fork >= Fork::Prague {
130            BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
131        } else {
132            BLOB_BASE_FEE_UPDATE_FRACTION
133        }
134    }
135
136    fn get_target_blob_gas_per_block_(fork: Fork) -> u32 {
137        if fork >= Fork::Prague {
138            TARGET_BLOB_GAS_PER_BLOCK_PECTRA
139        } else {
140            TARGET_BLOB_GAS_PER_BLOCK
141        }
142    }
143}
144
145impl Default for EVMConfig {
146    /// The default EVMConfig depends on the default Fork.
147    fn default() -> Self {
148        let fork = core::default::Default::default();
149        EVMConfig {
150            fork,
151            blob_schedule: Self::canonical_values(fork),
152        }
153    }
154}