diff --git a/consensus/state_processing/src/per_block_processing.rs b/consensus/state_processing/src/per_block_processing.rs index ef4799c245..6339f9003d 100644 --- a/consensus/state_processing/src/per_block_processing.rs +++ b/consensus/state_processing/src/per_block_processing.rs @@ -517,7 +517,7 @@ pub fn get_expected_withdrawals( let epoch = state.current_epoch(); let mut withdrawal_index = state.next_withdrawal_index()?; let mut validator_index = state.next_withdrawal_validator_index()?; - let mut withdrawals = vec![]; + let mut withdrawals = Vec::::with_capacity(E::max_withdrawals_per_payload()); let fork_name = state.fork_name_unchecked(); // [New in Electra:EIP7251] @@ -532,19 +532,27 @@ pub fn get_expected_withdrawals( break; } - let withdrawal_balance = state.get_balance(withdrawal.validator_index as usize)?; let validator = state.get_validator(withdrawal.validator_index as usize)?; let has_sufficient_effective_balance = validator.effective_balance >= spec.min_activation_balance; - let has_excess_balance = withdrawal_balance > spec.min_activation_balance; + let total_withdrawn = withdrawals + .iter() + .filter_map(|w| { + (w.validator_index == withdrawal.validator_index).then_some(w.amount) + }) + .safe_sum()?; + let balance = state + .get_balance(withdrawal.validator_index as usize)? + .safe_sub(total_withdrawn)?; + let has_excess_balance = balance > spec.min_activation_balance; if validator.exit_epoch == spec.far_future_epoch && has_sufficient_effective_balance && has_excess_balance { let withdrawable_balance = std::cmp::min( - withdrawal_balance.safe_sub(spec.min_activation_balance)?, + balance.safe_sub(spec.min_activation_balance)?, withdrawal.amount, ); withdrawals.push(Withdrawal {