//! EVM config for vanilla optimism. #![doc( html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" )] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] // The `optimism` feature must be enabled to use this crate. #![cfg(feature = "optimism")] use reth_chainspec::ChainSpec; use reth_evm::{ConfigureEvm, ConfigureEvmEnv}; use reth_primitives::{ revm_primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv}, transaction::FillTxEnv, Address, Head, Header, TransactionSigned, U256, }; use reth_revm::{inspector_handle_register, Database, Evm, EvmBuilder, GetInspector}; mod config; pub use config::{revm_spec, revm_spec_by_timestamp_after_bedrock}; mod execute; pub use execute::*; pub mod l1; pub use l1::*; mod error; pub use error::OptimismBlockExecutionError; use revm_primitives::{Bytes, Env, OptimismFields, TxKind}; /// Optimism-related EVM configuration. #[derive(Debug, Default, Clone, Copy)] #[non_exhaustive] pub struct OptimismEvmConfig; impl ConfigureEvmEnv for OptimismEvmConfig { fn fill_tx_env(&self, tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address) { transaction.fill_tx_env(tx_env, sender); } fn fill_tx_env_system_contract_call( &self, env: &mut Env, caller: Address, contract: Address, data: Bytes, ) { env.tx = TxEnv { caller, transact_to: TxKind::Call(contract), // Explicitly set nonce to None so revm does not do any nonce checks nonce: None, gas_limit: 30_000_000, value: U256::ZERO, data, // Setting the gas price to zero enforces that no value is transferred as part of the // call, and that the call will not count against the block's gas limit gas_price: U256::ZERO, // The chain ID check is not relevant here and is disabled if set to None chain_id: None, // Setting the gas priority fee to None ensures the effective gas price is derived from // the `gas_price` field, which we need to be zero gas_priority_fee: None, access_list: Vec::new(), // blob fields can be None for this tx blob_hashes: Vec::new(), max_fee_per_blob_gas: None, authorization_list: None, optimism: OptimismFields { source_hash: None, mint: None, is_system_transaction: Some(false), // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the // enveloped tx size. enveloped_tx: Some(Bytes::default()), }, }; // ensure the block gas limit is >= the tx env.block.gas_limit = U256::from(env.tx.gas_limit); // disable the base fee check for this call by setting the base fee to zero env.block.basefee = U256::ZERO; } fn fill_cfg_env( &self, cfg_env: &mut CfgEnvWithHandlerCfg, chain_spec: &ChainSpec, header: &Header, total_difficulty: U256, ) { let spec_id = revm_spec( chain_spec, &Head { number: header.number, timestamp: header.timestamp, difficulty: header.difficulty, total_difficulty, hash: Default::default(), }, ); cfg_env.chain_id = chain_spec.chain().id(); cfg_env.perf_analyse_created_bytecodes = AnalysisKind::Analyse; cfg_env.handler_cfg.spec_id = spec_id; cfg_env.handler_cfg.is_optimism = chain_spec.is_optimism(); } } impl ConfigureEvm for OptimismEvmConfig { type DefaultExternalContext<'a> = (); fn evm(&self, db: DB) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> { EvmBuilder::default().with_db(db).optimism().build() } fn evm_with_inspector(&self, db: DB, inspector: I) -> Evm<'_, I, DB> where DB: Database, I: GetInspector, { EvmBuilder::default() .with_db(db) .with_external_context(inspector) .optimism() .append_handler_register(inspector_handle_register) .build() } fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a> {} } #[cfg(test)] mod tests { use super::*; use reth_primitives::revm_primitives::{BlockEnv, CfgEnv}; use revm_primitives::SpecId; #[test] #[ignore] fn test_fill_cfg_and_block_env() { let mut cfg_env = CfgEnvWithHandlerCfg::new_with_spec_id(CfgEnv::default(), SpecId::LATEST); let mut block_env = BlockEnv::default(); let header = Header::default(); let chain_spec = ChainSpec::default(); let total_difficulty = U256::ZERO; OptimismEvmConfig::default().fill_cfg_and_block_env( &mut cfg_env, &mut block_env, &chain_spec, &header, total_difficulty, ); assert_eq!(cfg_env.chain_id, chain_spec.chain().id()); } }