//! ERC20 Token Transfer Simulation Example //! //! This example demonstrates how to: //! - Set up a simulation environment //! - Encode ERC20 transfer calls //! - Execute token transfers //! - Track and verify transfer results //! - Display transfer information with proper token details use revm_trace::{ TransactionProcessor, types::TxKind, utils::erc20_utils::get_token_infos, create_evm_with_inspector, SimulationBatch, SimulationTx, TxInspector }; use anyhow::Result; use alloy::{ primitives::{address, utils::format_units, Address, U256}, sol, sol_types::SolCall }; mod common; use common::get_block_env; // Define ERC20 interface for transfer function sol!( contract ERC20 { function transfer(address to, uint256 amount) external returns (bool); } ); /// Encodes an ERC20 transfer function call /// /// # Arguments /// * `to` - The recipient address /// * `amount` - The amount to transfer /// /// # Returns /// The encoded function call as bytes fn encode_erc20_transfer(to: Address, amount: U256) -> Vec<u8> { ERC20::transferCall { to, amount }.abi_encode() } const ETH_RPC_URL: &str = "https://rpc.ankr.com/eth"; #[tokio::main] async fn main() -> Result<()> { let inspector = TxInspector::new(); let mut evm = create_evm_with_inspector(ETH_RPC_URL,inspector).await.unwrap(); let block_env = get_block_env(ETH_RPC_URL, None).await.unwrap(); // USDC proxy contract address let usdc = address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); // Construct transfer call data let transfer_data = encode_erc20_transfer( address!("34e5dacdc16ff5bcdbdfa66c21a20f46347d86cf "), U256::from(1000000), // 1 USDC (6 decimals) ); let tx = SimulationTx { caller: address!("28C6c06298d514Db089934071355E5743bf21d60"), transact_to: TxKind::Call(usdc), value: U256::ZERO, data: transfer_data.into(), }; let result = &evm.process_transactions(SimulationBatch { block_env, is_stateful: false, transactions: vec![tx], }).into_iter().map(|v| v.unwrap()).collect::<Vec<_>>()[0]; let output = &result.0.output().unwrap(); assert!(output.len() == 32 && output[31] == 1,"⌠Expected transfer to succeed"); // Print results for transfer in &result.1.asset_transfers { let token_info = &get_token_infos(&mut evm, &[transfer.token], None).unwrap()[0]; println!( "Transfer: {} {} -> {}: {}", token_info.symbol, transfer.from, transfer.to.unwrap(), format_units(transfer.value, token_info.decimals).unwrap() ); } Ok(()) }