diff --git a/crates/evm/src/eth/block.rs b/crates/evm/src/eth/block.rs index ac77ca18..2be18d2b 100644 --- a/crates/evm/src/eth/block.rs +++ b/crates/evm/src/eth/block.rs @@ -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;