diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index acf098663..2e6c64be5 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -1402,8 +1402,11 @@ def process_final_updates(state: BeaconState) -> None: # Update effective balances with hysteresis for index, validator in enumerate(state.validators): balance = state.balances[index] - HALF_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // 2 - if balance < validator.effective_balance or validator.effective_balance + 3 * HALF_INCREMENT < balance: + QUARTER_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // 4 + if ( + balance + QUARTER_INCREMENT < validator.effective_balance + or validator.effective_balance + 7 * QUARTER_INCREMENT < balance + ): validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) # Reset slashings state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0) diff --git a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py b/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py index 58882a44f..b0d05427a 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_final_updates.py @@ -51,19 +51,22 @@ def test_effective_balance_hysteresis(spec, state): max = spec.MAX_EFFECTIVE_BALANCE min = spec.EJECTION_BALANCE inc = spec.EFFECTIVE_BALANCE_INCREMENT - half_inc = inc // 2 + quar_inc = inc // 4 cases = [ (max, max, max, "as-is"), - (max, max - 1, max - inc, "round down, step lower"), + (max, max - 1, max, "round up"), (max, max + 1, max, "round down"), + (max, max - quar_inc, max, "lower balance, but not low enough"), + (max, max - quar_inc, max, "lower balance, step down"), + (max, max + (3 * quar_inc) + 1, max, "already at max, as is"), (max, max - inc, max - inc, "exactly 1 step lower"), - (max, max - inc - 1, max - (2 * inc), "just 1 over 1 step lower"), + (max, max - inc - 1, max - (2 * inc), "past 1 step lower, double step"), (max, max - inc + 1, max - inc, "close to 1 step lower"), - (min, min + (half_inc * 3), min, "bigger balance, but not high enough"), - (min, min + (half_inc * 3) + 1, min + inc, "bigger balance, high enough, but small step"), - (min, min + (half_inc * 4) - 1, min + inc, "bigger balance, high enough, close to double step"), - (min, min + (half_inc * 4), min + (2 * inc), "exact two step balance increment"), - (min, min + (half_inc * 4) + 1, min + (2 * inc), "over two steps, round down"), + (min, min + (quar_inc * 7), min, "bigger balance, but not high enough"), + (min, min + (quar_inc * 7) + 1, min + inc, "bigger balance, high enough, but small step"), + (min, min + (quar_inc * 8) - 1, min + inc, "bigger balance, high enough, close to double step"), + (min, min + (quar_inc * 8), min + (2 * inc), "exact two step balance increment"), + (min, min + (quar_inc * 8) + 1, min + (2 * inc), "over two steps, round down"), ] current_epoch = spec.get_current_epoch(state) for i, (pre_eff, bal, _, _) in enumerate(cases):