Open
Conversation
Implement the SWIP-40 and SWIP-41 staking flow with delayed queue-based stake updates, withdrawals, and exits while keeping redistribution aligned with effective active stake.
Prevent queued stake withdrawals and exits from executing while a node is frozen or actively participating in the current redistribution round, and wire staking to the redistribution contract for the runtime check.
Prevent claims from finalizing when postage payout fails, and initialize staking with the expected redistribution contract so deployment catches linkage mismatches early.
Add direct effective stake coverage and make the two-reveal winner assertion resilient to deterministic state changes, while cleaning related test typing and lint issues.
Reconcile queued withdrawals after slashing and preview stake state at a specific round so upcoming-round eligibility uses the same round context as the anchor.
Prevent new stake updates from being enqueued after an exit is scheduled, and align withdrawal waits on real networks with the intended 28-day round window while keeping local settings fast.
Use overlay presence as the stake initialization check and remove the dead lastUpdatedBlockNumber field and related test assertions.
…king Allow effective withdrawals and exits to execute without current-round participation blocking them, and remove the admin-controlled redistribution hook from staking and deployment wiring.
Clarify that queued stake preview getters are forward-looking rather than historical by switching the staking and redistribution APIs from target-round naming to explicit round lookahead semantics.
- Revert FrozenWithdrawal on frozen withdrawal/exit in applyUpdates instead of silently skipping - Check _queueClosed before _previewStake so terminating queues revert QueueClosed instead of NotStaked - Enforce WAIT_OVERLAY_CHANGE >= WAIT_BASE and WAIT_WITHDRAWAL >= WAIT_BASE in constructor - Make UPDATE_QUEUE_MAX_LENGTH public
- Remove dead `Frozen` error (unused after FrozenWithdrawal was added) - Merge identical `StakeState` into `Stake`, remove `_toStakeView` - Add `_revertOnFrozen` param to `_applyReadyUpdates` so privileged callers (freezeDeposit, slashDeposit, migrateStake) break instead of reverting when a frozen withdrawal is encountered - Move `_queueClosed` check from `_enqueueUpdate` to all six public callers including `createDeposit` which previously lacked it - Update tests to expect FrozenWithdrawal revert on applyUpdates while frozen
e2e56e7 to
8bba0ee
Compare
Move FrozenWithdrawal revert into applyUpdates as a post-call check instead of threading a bool through _applyReadyUpdates. The internal function now always breaks on frozen entries.
Swap freeze and apply order in freezeDeposit so mature withdrawals settle while the node is still unfrozen, then the freeze takes effect for future rounds.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
balance, and a frozen node's effective stake is0lookaheadsemantics instead ofAtRoundnamingapplyUpdatesreverts on frozen withdrawals/exits, post-exit operations revertQueueClosedinstead ofNotStaked, constructor validates wait-parameter orderingUPDATE_QUEUE_MAX_LENGTHas a public constantFrozenerror, duplicateStakeStatestruct (merged intoStake), redundant_toStakeViewconversion_applyReadyUpdatesso privileged callers (freezeDeposit,slashDeposit,migrateStake) can never be blocked by a frozen withdrawal — they skip frozen entries instead of revertingBee Node Changes
createDeposit,addTokens,increaseHeight,changeOverlay,withdraw, andexitnow enqueue updates that only become effective after the relevant wait period and afterapplyUpdates(owner)materializes them on-chain.WAIT_BASEfor deposit, top-up, and height increaseWAIT_OVERLAY_CHANGEfor overlay changesWAIT_WITHDRAWALfor withdraw and exitWAIT_WITHDRAWALis intended to represent roughly a 28-day delay in rounds. Local development configs may still use short values.applyUpdates(owner)to materialize ready updates on-chain. This is especially important for withdrawals and exits, because the BZZ transfer is only executed duringapplyUpdates(owner).applyUpdates(owner)reverts withFrozenWithdrawal(). Bee should catch this revert and retry after the freeze expires. The frozen update stays in the queue and will execute on a subsequentapplyUpdatescall once the node is unfrozen.Redistribution.isParticipatingInUpcomingRound(owner, depth)as the source of truth for eligibility. Bee should not try to reconstruct that decision from plainStakeRegistrygetters alone, because redistribution combines staking state with round/anchor logic.nodeEffectiveStake(owner),overlayOfAddress(owner),heightOfAddress(owner), andstakes(owner)as the currently effective staking state only. Queued future state is not implicitly exposed through those getters.nodeEffectiveStakeLookahead(owner, lookahead)overlayOfAddressLookahead(owner, lookahead)heightOfAddressLookahead(owner, lookahead)lookahead = 0means "effective state for the current round context", andlookahead = 1means "effective state one round ahead". This replaces the previous absolute-round preview naming.applyUpdates(owner)has succeeded.nodeEffectiveStake(owner)as the live effective stake value. The previous committed/potential split is gone.exit()is queued, the owner's staking queue is closed. Any subsequent call tocreateDeposit,addTokens,changeOverlay,increaseHeight,withdraw, orexitreverts withQueueClosed(). No further staking updates can be enqueued for that owner until the exit is applied and the queue is cleared. Bee should treat a queued exit as a terminal pending action for that stake position.UPDATE_QUEUE_MAX_LENGTHon-chain to check queue capacity before enqueuing. The queue reverts withUpdateQueueFull()when the limit is reached.applyUpdates(owner)Deployment Notes
WAIT_OVERLAY_CHANGE >= WAIT_BASEandWAIT_WITHDRAWAL >= WAIT_BASE. Deployment scripts that pass wait parameters violating this invariant will fail withInvalidWaitConfiguration().Contract Cleanup
Frozenerror declaration.StakeStatestruct intoStake— the duplicate struct and_toStakeViewconversion function were dead weight since the fields were identical._queueClosedguard from_enqueueUpdateinto all six public caller functions. This ensuresQueueClosedis the first revert a user sees when the queue is terminating, before any gas is spent on_previewStake. ThecreateDepositfunction previously lacked this guard entirely._applyReadyUpdatesnow takes a_revertOnFrozenparameter. PublicapplyUpdatespassestrue(reverts withFrozenWithdrawal). Privileged callers (freezeDeposit,slashDeposit,migrateStake) passfalse(breaks out of the loop) so the redistributor can always freeze and slash, and migration always succeeds.Redistribution Notes
claim()now keeps payout and round finalization atomic. If the postage payout fails, the whole claim reverts and can be retried later once the underlying issue is resolved.Reference