Skip to content

fix(staking): revert slashing when validator stake has migrated to a newer rollup #25432

Description

@craftsoldier

Summary

  • trySlash in StakingLib returns false without reverting when a validator's effective balance is zero, which occurs when their stake was in the GSE bonus bucket and a newer rollup has been registered
  • The caller (Slasher.slash via SlashPayload actions) only checks that the call succeeded, not the return value, so the slash round is marked as executed without actually slashing anyone
  • In practice this means a slash voted before a rollup upgrade can silently fail to execute if the upgrade lands first — the validator keeps their full stake and nothing indicates the round was a no-op
  • Instead, revert so the failure surfaces and the round can be investigated or retried

Root cause

When a validator deposits with moveWithLatestRollup = true, their stake goes to the GSE bonus bucket. effectiveBalanceOf gates bonus-bucket access on getLatestRollup() == _instance (GSE.sol). Once a newer rollup is registered via addRollup, the old rollup is no longer "latest" and the lookup returns 0 for all bonus-bucket validators.

If a slash round on the old rollup executes after migration, trySlash hits the !isSlashable path (StakingLib.sol:267) and returns false. Since Slasher.slash only requires that the external call didn't revert (Slasher.sol:87-92), a false return is indistinguishable from success — the round completes silently.

Patch direction

Option A: revert in trySlash when the effective balance is zero, instead of returning false. This makes the failure visible at the round level.

Option B: widen the effectiveBalanceOf gate to let recently-superseded rollups still reach the bonus bucket during a grace window (e.g. 30 days), preserving slashing jurisdiction long enough for pending rounds to complete.


This issue was identified with the assistance of AI tooling during code review.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions