//! ETH Transfer Validation Failure Example //! //! This example shows how EVM handles transactions that fail during the validation phase, //! specifically when attempting to transfer ETH with insufficient balance. //! //! Key points demonstrated: //! - Transaction validation occurs before execution //! - No gas is consumed when validation fails //! - No execution trace is generated //! - How to handle and verify expected failures //! //! This example demonstrates: //! - How EVM handles pre-execution validation failures //! - Transfer attempt with insufficient balance //! - Error handling in transaction simulation //! //! Note: This transaction fails during validation phase (before execution), //! so there will be no execution trace or inspector output. use revm_trace::{ types::TxKind, TransactionProcessor, create_evm_with_inspector, SimulationBatch, SimulationTx, TxInspector }; use anyhow::Result; use alloy::primitives::{address, U256}; use colored::*; mod common; use common::get_block_env; const ETH_RPC_URL: &str = "https://eth.llamarpc.com"; #[tokio::main] async fn main() -> Result<()> { println!("Starting transfer ETH failed test..."); // Initialize EVM with transaction inspector // Note: Inspector won't produce output as transaction fails in validation let inspector = TxInspector::new(); let mut evm = create_evm_with_inspector(ETH_RPC_URL, inspector).await.unwrap(); // Get latest block environment for simulation let block_env = get_block_env(ETH_RPC_URL, None).await.unwrap(); println!("{}", "✅ EVM instance created successfully\n".green()); // Configure transfer parameters let safe = address!("Ab778bF14C7F879D33FAA7aeD44dA68AaA02513a"); // Sender with insufficient balance let to = address!("E8ccbb36816e5f2fB69fBe6fbd46d7e370435d84"); // Recipient // Amount to transfer: 0.01 ETH let amount = U256::from(10000000000000000u128); // 0.01 ETH in wei // Create transfer transaction // Empty data field as this is a simple ETH transfer let tx = SimulationTx { caller: safe, transact_to: TxKind::Call(to), value: amount, data: vec![].into(), }; // Create transaction batch // Note: is_stateful doesn't matter here as transaction will fail validation let txs = SimulationBatch { block_env, transactions: vec![tx], is_stateful: true, }; // Process transaction // Expected to fail due to insufficient balance let result = evm.process_transactions(txs); // Verify failure assert!( result[0].is_err(), "⌠Expected transfer to fail due to insufficient balance" ); // Display error details println!( "{}", format!("Result:⌠{:#?}", result[0].as_ref().unwrap_err()).red() ); Ok(()) }