-
Notifications
You must be signed in to change notification settings - Fork 476
fix: DSF increase on checkpointed nonzero shares #1176
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
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
ca509dc
fix: add proper parsing of balanceDeltaWei; passing regression test
ypatil12 855dcd8
test: add integration tests; update docs
ypatil12 308d597
test: one last sanity test
ypatil12 0c545f9
test: add regression tests
ypatil12 8838be6
chore: fmt
ypatil12 9511db3
chore: bindings
ypatil12 5d1d1bd
fix: flaky test
ypatil12 aff1ce1
fix: add DM fix
ypatil12 0e60c46
docs: clarify zero case
ypatil12 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
| pragma solidity ^0.8.27; | ||
|
|
||
| import "src/test/integration/IntegrationChecks.t.sol"; | ||
|
|
||
| contract Integration_SlashedEigenpod_AVS_Base is IntegrationCheckUtils { | ||
| using ArrayLib for *; | ||
| using SlashingLib for *; | ||
| using Math for uint256; | ||
|
|
||
| AVS avs; | ||
| OperatorSet operatorSet; | ||
|
|
||
| User operator; | ||
| AllocateParams allocateParams; | ||
| SlashingParams slashParams; | ||
|
|
||
| User staker; | ||
| IStrategy[] strategies; | ||
| uint[] initTokenBalances; | ||
| uint[] initDepositShares; | ||
|
|
||
| function _init() internal virtual override { | ||
| _configAssetTypes(HOLDS_ETH); | ||
| (staker, strategies, initTokenBalances) = _newRandomStaker(); | ||
| (operator,,) = _newRandomOperator(); | ||
| (avs,) = _newRandomAVS(); | ||
|
|
||
| cheats.assume(initTokenBalances[0] >= 64 ether); | ||
|
|
||
| // 1. Deposit Into Strategies | ||
| staker.depositIntoEigenlayer(strategies, initTokenBalances); | ||
| initDepositShares = _calculateExpectedShares(strategies, initTokenBalances); | ||
| check_Deposit_State(staker, strategies, initDepositShares); | ||
|
|
||
| // 2. Delegate to an operator | ||
| staker.delegateTo(operator); | ||
| check_Delegation_State(staker, operator, strategies, initDepositShares); | ||
|
|
||
| // 3. Create an operator set and register an operator. | ||
| operatorSet = avs.createOperatorSet(strategies); | ||
|
|
||
| // 4. Register for operator set | ||
| operator.registerForOperatorSet(operatorSet); | ||
| check_Registration_State_NoAllocation(operator, operatorSet, allStrats); | ||
|
|
||
| // 5. Allocate to operator set | ||
| allocateParams = _genAllocation_AllAvailable(operator, operatorSet); | ||
| operator.modifyAllocations(allocateParams); | ||
| check_IncrAlloc_State_Slashable(operator, allocateParams); | ||
| _rollBlocksForCompleteAllocation(operator, operatorSet, strategies); | ||
| } | ||
| } | ||
|
|
||
| contract Integration_SlashedEigenpod_AVS_Checkpoint is Integration_SlashedEigenpod_AVS_Base { | ||
|
|
||
| function _init() internal override { | ||
| super._init(); | ||
|
|
||
| // 6. Slash | ||
| slashParams = _genSlashing_Rand(operator, operatorSet); | ||
| avs.slashOperator(slashParams); | ||
| check_Base_Slashing_State(operator, allocateParams, slashParams); | ||
|
|
||
| beaconChain.advanceEpoch_NoRewards(); | ||
| } | ||
|
|
||
| /// @dev Asserts that the DSF isn't updated after a slash & checkpoint with 0 balance | ||
| function testFuzz_deposit_delegate_allocate_slash_checkpointZeroBalance(uint24 _rand) public rand(_rand) { | ||
| // 7. Start & complete checkpoint | ||
| staker.startCheckpoint(); | ||
| check_StartCheckpoint_State(staker); | ||
| staker.completeCheckpoint(); | ||
| check_CompleteCheckpoint_ZeroBalanceDelta_State(staker); | ||
| } | ||
| } | ||
|
|
||
| contract Integration_SlashedEigenpod_AVS_Withdraw is Integration_SlashedEigenpod_AVS_Base { | ||
|
|
||
| function _init() internal override { | ||
| super._init(); | ||
|
|
||
| // Slash or queue a withdrawal in a random order | ||
| if (_randBool()) { // Slash -> Queue Withdrawal | ||
| // 7. Slash | ||
| slashParams = _genSlashing_Half(operator, operatorSet); | ||
| avs.slashOperator(slashParams); | ||
| check_Base_Slashing_State(operator, allocateParams, slashParams); | ||
|
|
||
| // 8. Queue Withdrawal for all shares. TODO: add proper assertion | ||
| staker.queueWithdrawals(strategies, initDepositShares); | ||
| } else { // Queue Withdrawal -> Slash | ||
| // 7. Queue Withdrawal for all shares | ||
| Withdrawal[] memory withdrawals = staker.queueWithdrawals(strategies, initDepositShares); | ||
| bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals); | ||
| check_QueuedWithdrawal_State(staker, operator, strategies, initDepositShares, withdrawals, withdrawalRoots); | ||
|
|
||
| // 8. Slash | ||
| slashParams = _genSlashing_Half(operator, operatorSet); | ||
| avs.slashOperator(slashParams); | ||
| check_Base_Slashing_State(operator, allocateParams, slashParams); | ||
| } | ||
|
|
||
| beaconChain.advanceEpoch_NoRewards(); | ||
| } | ||
|
|
||
| /// @dev Asserts that the DSF isn't updated after a slash/queue and a checkpoint with 0 balance. | ||
| /// @dev The staker should subsequently not be able to inflate their withdrawable shares | ||
| function testFuzz_deposit_delegate_allocate_slashAndQueue_checkpoint_redeposit(uint24 _rand) public rand(_rand) { | ||
| // 9. Start & complete checkpoint. | ||
| staker.startCheckpoint(); | ||
| check_StartCheckpoint_State(staker); | ||
| staker.completeCheckpoint(); | ||
| check_CompleteCheckpoint_ZeroBalanceDelta_State(staker); | ||
|
|
||
| // 10. Redeposit | ||
| cheats.deal(address(staker), 32 ether); | ||
| (uint40[] memory newValidators, uint64 addedBeaconBalanceGwei) = staker.startValidators(); | ||
| beaconChain.advanceEpoch_NoRewards(); | ||
| staker.verifyWithdrawalCredentials(newValidators); | ||
| check_VerifyWC_State(staker, newValidators, addedBeaconBalanceGwei); | ||
| } | ||
|
|
||
| /// @dev Asserts that the staker cannot inflate withdrawable shares after redepositing | ||
| function testFuzz_deposit_delegate_allocate_slashAndQueue_completeAsTokens_redeposit(uint24 _rand) public rand(_rand) { | ||
| Withdrawal[] memory withdrawals = _getQueuedWithdrawals(staker); | ||
| _rollBlocksForCompleteWithdrawals(withdrawals); | ||
|
|
||
| // 9. Complete withdrawal as tokens | ||
| for (uint256 i = 0; i < withdrawals.length; ++i) { | ||
| uint256[] memory expectedTokens = | ||
| _calculateExpectedTokens(withdrawals[i].strategies, withdrawals[i].scaledShares); | ||
| staker.completeWithdrawalAsTokens(withdrawals[i]); | ||
| check_Withdrawal_AsTokens_State_AfterSlash(staker, operator, withdrawals[i], allocateParams, slashParams, expectedTokens); | ||
| } | ||
|
|
||
| // 10. Redeposit | ||
| cheats.deal(address(staker), 32 ether); | ||
| (uint40[] memory newValidators, uint64 addedBeaconBalanceGwei) = staker.startValidators(); | ||
| beaconChain.advanceEpoch_NoRewards(); | ||
| staker.verifyWithdrawalCredentials(newValidators); | ||
| check_VerifyWC_State(staker, newValidators, addedBeaconBalanceGwei); | ||
| } | ||
|
|
||
| /// @dev Asserts that the staker cannot inflate withdrawable shares after checkpointing & completing as shares | ||
0xClandestine marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| function testFuzz_deposit_delegate_allocate_slashAndQueue_checkPoint_completeAsShares(uint24 _rand) public rand(_rand) { | ||
| Withdrawal[] memory withdrawals = _getQueuedWithdrawals(staker); | ||
| _rollBlocksForCompleteWithdrawals(withdrawals); | ||
| uint slashingFactor = _getSlashingFactor(staker, BEACONCHAIN_ETH_STRAT); | ||
| uint depositScalingFactor = _getDepositScalingFactor(staker, BEACONCHAIN_ETH_STRAT); | ||
|
|
||
| // 9. Start & complete checkpoint, since the next step does not. | ||
| staker.startCheckpoint(); | ||
| check_StartCheckpoint_State(staker); | ||
| staker.completeCheckpoint(); | ||
| check_CompleteCheckpoint_ZeroBalanceDelta_State(staker); | ||
|
|
||
| // 10. Complete withdrawal as shares. Deposit scaling factor is doubled because operator was slashed by half. | ||
| staker.completeWithdrawalAsShares(withdrawals[0]); | ||
| check_Withdrawal_AsShares_State_AfterSlash(staker, operator, withdrawals[0], allocateParams, slashParams); | ||
| assertEq( | ||
| _getStakerWithdrawableShares(staker, strategies)[0], | ||
| _getExpectedWithdrawableSharesAfterCompletion(staker, withdrawals[0].scaledShares[0], depositScalingFactor * 2, slashingFactor), | ||
| "withdrawable shares not incremented correctly" | ||
| ); | ||
| } | ||
| } | ||
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just want to note that I have separate code dealing with this scenario in our testing branch so we'll have to remove one or the other down the line