Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: slashable window boundaries #965

Merged
merged 8 commits into from
Dec 18, 2024
Merged

Conversation

8sunyuan
Copy link
Collaborator

Fixing slashable windows here by ensuring that from
[block.number, block.number + MIN_WITHDRAWAL_DELAY_BLOCKS] and
[block.number, block.number + DEALLOCATION_DELAY] are both the same window.
Since we want these two values MIN_WITHDRAWAL_DELAY_BLOCKS and DEALLOCATION_DELAY to be configured to be the same in deployments, we make the following changes:

  1. Upon withdrawal completion, we now have a slashableUntil block which is withdrawal.startBlock + MIN_WITHDRAWAL_DELAY_BLOCKS which is the last block the staker's withdrawal is slashable for. That means the first block they can complete withdraw is the block following hence the strict inequality
uint32 slashableUntil = withdrawal.startBlock + MIN_WITHDRAWAL_DELAY_BLOCKS;
require(slashableUntil < uint32(block.number), WithdrawalDelayNotElapsed());
  1. For deallocations, we have effectBlock set as block.number + DEALLOCATION_DELAY currently but that is the block that the deallocation is no longer slashable and can be completed. We fix this to ensure the slashable window of [block.number, block.number + DEALLOCATION_DELAY] by making the effectBlock = block.number + DEALLOCATION_DELAY + 1.

  2. For DelegationManager._getSlashedSharesInQueue we want also ensure a slashable window of [block.number - MIN_WITHDRAWAL_DELAY_BLOCKS, block.number] including blocknumber block.number - MIN_WITHDRAWAL_DELAY_BLOCKS. So since a subtraction is done of curCumulativeScaledShares - prevCumulativeScaledShares, we make the snapshot.lookup of prevCumulativeScaledShares to be -1 to include that block itself.

@ypatil12 ypatil12 closed this Dec 18, 2024
@ypatil12 ypatil12 reopened this Dec 18, 2024
@8sunyuan 8sunyuan force-pushed the fix-slashable-windows branch from 4a8ea67 to ca92a20 Compare December 18, 2024 01:26
// if the slashableUntil block is in the future, simply read current slashing factors
// still possible however for the slashing factors to change before the withdrawal is completable
// and the shares withdrawn to be less
if (slashableUntil > uint32(block.number)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be >=

alternatively, making it uint32(block.number) > slashableUntil and switching the inners of the conditionals is cleaner

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_getSlashingFactors gets the current slashing factor, so the logic here is that if slashableUntil is at some future block, then we simply read the current slashing factors. Else we read it at the exact slashableUntil block

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its clearer if we go >=, but the underlying logic is still the same

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get now what you guys are saying now and agreed.
Updated now e6c66cd

allocation.effectBlock = uint32(block.number) + DEALLOCATION_DELAY;
// deallocations are slashable in the window [block.number, block.number + deallocationDelay]
// therefore, the effectBlock is set to the block right after the slashable window
allocation.effectBlock = uint32(block.number) + DEALLOCATION_DELAY + 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: every comparison to effectBlock is < effectBlock. There is some minor difference in naming (and resulting comparisons) because we do:

  • < effectBlock
  • <= slashableUntil

Nomenclature does make sense here though

src/contracts/core/AllocationManager.sol Show resolved Hide resolved
// slashableUntil is block inclusive so we need to check if the current block is strictly greater than the slashableUntil block
// meaning the withdrawal can be completed.
uint32 slashableUntil = withdrawal.startBlock + MIN_WITHDRAWAL_DELAY_BLOCKS;
require(slashableUntil < uint32(block.number), WithdrawalDelayNotElapsed());
Copy link
Collaborator

@ypatil12 ypatil12 Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_Revert_WhenWithdrawalDelayNotPassed validates this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint256 curCumulativeScaledShares = _cumulativeScaledSharesHistory[operator][strategy].latest();
uint256 prevCumulativeScaledShares = _cumulativeScaledSharesHistory[operator][strategy].upperLookup({
key: uint32(block.number) - MIN_WITHDRAWAL_DELAY_BLOCKS
key: uint32(block.number) - MIN_WITHDRAWAL_DELAY_BLOCKS - 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Burning test: 8d380fa

@8sunyuan 8sunyuan force-pushed the fix-slashable-windows branch from ab8550d to e6c66cd Compare December 18, 2024 15:09
@8sunyuan 8sunyuan merged commit 1d6adf9 into slashing-magnitudes Dec 18, 2024
11 checks passed
@8sunyuan 8sunyuan deleted the fix-slashable-windows branch December 18, 2024 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants