From 70f46293d9f4887790f7d901ae1896fd3a611640 Mon Sep 17 00:00:00 2001 From: hangleang Date: Sat, 21 Dec 2024 15:50:14 +0700 Subject: [PATCH] EIP7251: Fix partial withdrawal balance update --- .../src/electra/block_processing.rs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/transition_functions/src/electra/block_processing.rs b/transition_functions/src/electra/block_processing.rs index c808bd4c..6b1e07a4 100644 --- a/transition_functions/src/electra/block_processing.rs +++ b/transition_functions/src/electra/block_processing.rs @@ -235,7 +235,7 @@ fn process_withdrawals( where P::MaxWithdrawalsPerPayload: NonZero, { - let (expected_withdrawals, partial_withdrawals_count) = get_expected_withdrawals(state)?; + let (expected_withdrawals, processed_partial_withdrawals_count) = get_expected_withdrawals(state)?; let computed = expected_withdrawals.len(); let in_block = execution_payload.withdrawals().len(); @@ -268,7 +268,7 @@ where .pending_partial_withdrawals() .into_iter() .copied() - .skip(partial_withdrawals_count), + .skip(processed_partial_withdrawals_count), )?; // > Update the next withdrawal index if this block contained withdrawals @@ -316,7 +316,7 @@ pub fn get_expected_withdrawals( let mut withdrawal_index = state.next_withdrawal_index(); let mut validator_index = state.next_withdrawal_validator_index(); let mut withdrawals = vec![]; - let mut partial_withdrawals_count = 0; + let mut processed_partial_withdrawals_count = 0; // > [New in Electra:EIP7251] Consume pending partial withdrawals for withdrawal in &state.pending_partial_withdrawals().clone() { @@ -354,14 +354,25 @@ pub fn get_expected_withdrawals( withdrawal_index += 1; } - partial_withdrawals_count += 1; + processed_partial_withdrawals_count += 1; } // > Sweep for remaining for _ in 0..bound { - let balance = state.balances().get(validator_index).copied()?; let validator = state.validators().get(validator_index)?; + // > [Modified in Electra:EIP7251] + let partially_withdrawn_balance = withdrawals + .iter() + .filter(|withdrawal| withdrawal.validator_index == validator_index) + .map(|withdrawal| withdrawal.amount) + .sum::(); + + let validator_balance = state.balances().get(validator_index).copied()?; + let balance = validator_balance + .checked_sub(partially_withdrawn_balance) + .expect("withdrawal amounts must not excess balance"); + let address = validator .withdrawal_credentials .as_bytes() @@ -408,7 +419,7 @@ pub fn get_expected_withdrawals( .expect("total_validators being 0 should prevent the loop from being executed"); } - Ok((withdrawals, partial_withdrawals_count)) + Ok((withdrawals, processed_partial_withdrawals_count)) } fn process_execution_payload(