Skip to content

BOLDUpgradeAction.cleanupOldRollup() staker refund loop capped at 50 — risk for Orbit chains with >50 stakers #430

Description

@brodmart

Summary

BOLDUpgradeAction.cleanupOldRollup() iterates stakers to refund bonds, but the loop is capped at 50 iterations:

function cleanupOldRollup() external {
    // ...
    uint256 stakerCount = oldRollup.stakerCount();
    if (stakerCount > 50) {
        stakerCount = 50;
    }
    for (uint256 i = 0; i < stakerCount; i++) {
        // refund stakers[i]
    }
}

If an Orbit chain has more than 50 active stakers at migration time, stakers beyond index 50 do not receive bond refunds. Their ETH stake is not returned by this migration path.

Current Status (Arbitrum One)

The Arbitrum One BOLD migration ran on February 12, 2025. Based on on-chain state at that time, the chain had approximately 5-10 active stakers, so the cap was never triggered. The existing code comment // we dont expect any instances to have close to this number of stakers reflects this expectation.

Forward Risk

As the Orbit chain ecosystem grows, other rollups using BOLDUpgradeAction may have more validators. An Orbit chain that:

  • Runs a permissionless validation set
  • Has >50 registered stakers at migration time

...would silently lose the remaining staker bonds to cleanupOldRollup(), with no on-chain revert or warning.

Recommended Fix

Option A: Remove the cap and iterate all stakers (may hit gas limit on large sets — use with caution):

uint256 stakerCount = oldRollup.stakerCount();
// removed cap

Option B: Add a continuation mechanism — allow cleanupOldRollup() to be called multiple times with a start index:

function cleanupOldRollup(uint256 startIdx, uint256 count) external { ... }

Option C: Emit a warning event when the cap is hit:

if (oldRollup.stakerCount() > 50) {
    emit StakerRefundCapReached(oldRollup.stakerCount());
}

Severity

Low-to-Medium for current deployments (cap never triggered on mainnet). Medium for future Orbit deployments with permissionless validation. No immediate exploit path on Arbitrum One.

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