Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions specs/electra/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -1114,10 +1114,12 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal],

validator = state.validators[withdrawal.validator_index]
has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
has_excess_balance = state.balances[withdrawal.validator_index] > MIN_ACTIVATION_BALANCE
total_withdrawn = sum(w.amount for w in withdrawals if w.validator_index == withdrawal.validator_index)
balance = state.balances[withdrawal.validator_index] - total_withdrawn
has_excess_balance = balance > MIN_ACTIVATION_BALANCE
if validator.exit_epoch == FAR_FUTURE_EPOCH and has_sufficient_effective_balance and has_excess_balance:
withdrawable_balance = min(
state.balances[withdrawal.validator_index] - MIN_ACTIVATION_BALANCE,
balance - MIN_ACTIVATION_BALANCE,
withdrawal.amount)
withdrawals.append(Withdrawal(
index=withdrawal_index,
Expand All @@ -1134,9 +1136,8 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal],
for _ in range(bound):
validator = state.validators[validator_index]
# [Modified in Electra:EIP7251]
partially_withdrawn_balance = sum(
withdrawal.amount for withdrawal in withdrawals if withdrawal.validator_index == validator_index)
balance = state.balances[validator_index] - partially_withdrawn_balance
total_withdrawn = sum(w.amount for w in withdrawals if w.validator_index == validator_index)
balance = state.balances[validator_index] - total_withdrawn
if is_fully_withdrawable_validator(validator, balance, epoch):
withdrawals.append(Withdrawal(
index=withdrawal_index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -748,3 +748,79 @@ def test_partially_withdrawable_validator_compounding_min_minus_one(spec, state)
partial_withdrawals_indices=[],
)
assert state.pending_partial_withdrawals == []


@with_electra_and_later
@spec_state_test
def test_pending_withdrawals_two_partial_withdrawals_same_validator_1(spec, state):
validator_index = 0

# Initialize a compounding validator
set_compounding_withdrawal_credential_with_balance(
spec,
state,
validator_index,
effective_balance=spec.Gwei(32_000_000_000),
balance=spec.Gwei(33_000_000_000),
)

# Add two pending withdrawals of 1 ETH each to the queue
withdrawal = spec.PendingPartialWithdrawal(
validator_index=validator_index,
amount=spec.Gwei(1_000_000_000),
withdrawable_epoch=spec.get_current_epoch(state),
)
state.pending_partial_withdrawals = [withdrawal, withdrawal]

# Ensure our two pending withdrawals are there
assert len(state.pending_partial_withdrawals) == 2

yield from run_withdrawals_processing(
spec,
state,
build_empty_execution_payload(spec, state),
num_expected_withdrawals=1,
)

# Ensure our two pending withdrawals were processed
assert state.pending_partial_withdrawals == []
# Ensure the validator's balance is the minimum
assert state.balances[validator_index] == spec.MIN_ACTIVATION_BALANCE


@with_electra_and_later
@spec_state_test
def test_pending_withdrawals_two_partial_withdrawals_same_validator_2(spec, state):
validator_index = 0

# Initialize a compounding validator
set_compounding_withdrawal_credential_with_balance(
spec,
state,
validator_index,
effective_balance=spec.Gwei(2015_000_000_000),
balance=spec.Gwei(2015_000_000_000),
)

# Add two pending withdrawals of 1008 ETH each to the queue
withdrawal = spec.PendingPartialWithdrawal(
validator_index=validator_index,
amount=spec.Gwei(1008_000_000_000),
withdrawable_epoch=spec.get_current_epoch(state),
)
state.pending_partial_withdrawals = [withdrawal, withdrawal]

# Ensure our two pending withdrawals are there
assert len(state.pending_partial_withdrawals) == 2

yield from run_withdrawals_processing(
spec,
state,
build_empty_execution_payload(spec, state),
num_expected_withdrawals=2,
)

# Ensure our two pending withdrawals were processed
assert state.pending_partial_withdrawals == []
# Ensure the validator's balance is the minimum
assert state.balances[validator_index] == spec.MIN_ACTIVATION_BALANCE