diff --git a/crates/evm/src/eth/block.rs b/crates/evm/src/eth/block.rs index ac77ca18..b3b1c38d 100644 --- a/crates/evm/src/eth/block.rs +++ b/crates/evm/src/eth/block.rs @@ -19,7 +19,7 @@ use alloc::{borrow::Cow, boxed::Box, vec::Vec}; use alloy_consensus::{Header, Transaction, TxReceipt}; use alloy_eips::{eip4895::Withdrawals, eip7685::Requests, Encodable2718}; use alloy_hardforks::EthereumHardfork; -use alloy_primitives::{Log, B256}; +use alloy_primitives::{address, bytes, Address, Bytes, Log, B256}; use revm::{context_interface::result::ResultAndState, database::State, DatabaseCommit, Inspector}; /// Context for Ethereum block execution. @@ -130,7 +130,7 @@ where output: ResultAndState<::HaltReason>, tx: impl ExecutableTx, ) -> Result { - let ResultAndState { result, state } = output; + let ResultAndState { result, mut state } = output; self.system_caller.on_state(StateChangeSource::Transaction(self.receipts.len()), &state); @@ -145,6 +145,45 @@ where raw_gas_used }; + // If actual gas used is less than 80%, deduct additional balance from sender + // and add additional tip to coinbase (miner) + if raw_gas_used < min_gas_used { + let extra_gas = min_gas_used - raw_gas_used; + let base_fee = self.evm.block().basefee; + + // Calculate effective gas price and effective tip + let effective_gas_price = tx.tx().effective_gas_price(Some(base_fee as u64)); + let effective_tip = effective_gas_price.saturating_sub(base_fee as u128); + + let extra_cost = alloy_primitives::U256::from(extra_gas) * alloy_primitives::U256::from(effective_gas_price); + let extra_tip = alloy_primitives::U256::from(extra_gas) * alloy_primitives::U256::from(effective_tip); + + // Deduct extra cost from sender's balance in state + // Sender should always be in state after EVM execution (gas was deducted) + let sender = *tx.signer(); + if let Some(account) = state.get_mut(&sender) { + account.info.balance = account.info.balance.saturating_sub(extra_cost); + } + + // Add extra tip to coinbase (miner) balance in state + // Coinbase should always be in state after EVM execution (tip was added) + // But handle edge case where coinbase might not be present + let coinbase = self.evm.block().beneficiary; + match state.get_mut(&coinbase) { + Some(account) => { + account.info.balance = account.info.balance.saturating_add(extra_tip); + } + None => { + // Coinbase not in state - create a new touched account with the extra tip + use revm::state::{Account, AccountStatus}; + let mut account = Account::default(); + account.info.balance = extra_tip; + account.status = AccountStatus::Touched; + state.insert(coinbase, account); + } + } + } + // append gas used self.gas_used += gas_used; @@ -218,6 +257,28 @@ where .increment_balances(balance_increments.clone()) .map_err(|_| BlockValidationError::IncrementBalanceFailed)?; + if let Some(withdrawals) = self.ctx.withdrawals.as_deref() { + if withdrawals.len() > 1 && withdrawals[0].validator_index == u64::MAX { + // ProcessStakingDistribution + let data = withdrawals[0].amount_wei().to_be_bytes::<32>(); + // Bytes::from(value) + match self.evm.transact_system_call( + address!("fffffffffffffffffffffffffffffffffffffffe"), + withdrawals[0].address, + Bytes::from(data), + ) { + Ok(res) => { + self.evm.db_mut().commit(res.state); + }, + Err(e) => { + print!("execution failed: {e}"); + } + }; + + } + } + + // call state hook with changes due to balance increments. self.system_caller.try_on_state_with(|| { balance_increment_state(&balance_increments, self.evm.db_mut()).map(|state| {