Skip to content

Commit

Permalink
test: burning indices
Browse files Browse the repository at this point in the history
  • Loading branch information
ypatil12 committed Dec 18, 2024
1 parent 6ffb6c3 commit 8d380fa
Showing 1 changed file with 208 additions and 0 deletions.
208 changes: 208 additions & 0 deletions src/test/unit/DelegationUnit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6000,6 +6000,48 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage
delegationManager.completeQueuedWithdrawal(withdrawal, tokens, receiveAsTokens);
}

/// @notice Verifies that when we complete a withdrawal as shares after a full slash, we revert
function test_revert_fullySlashed() public {
// Register operator
_registerOperatorWithBaseDetails(defaultOperator);
_setOperatorMagnitude(defaultOperator, strategyMock, WAD);

// Set the staker deposits in the strategies
uint256 depositAmount = 100e18;
strategyManagerMock.addDeposit(defaultStaker, strategyMock, depositAmount);
_delegateToOperatorWhoAcceptsAllStakers(defaultStaker, defaultOperator);

// Queue withdrawal
uint256 withdrawalAmount = depositAmount;
(
QueuedWithdrawalParams[] memory queuedWithdrawalParams,
Withdrawal memory withdrawal,
bytes32 withdrawalRoot
) = _setUpQueueWithdrawalsSingleStrat({
staker: defaultStaker,
withdrawer: defaultStaker,
strategy: strategyMock,
depositSharesToWithdraw: withdrawalAmount
});
cheats.prank(defaultStaker);
delegationManager.queueWithdrawals(queuedWithdrawalParams);

// Warp to just before the MIN_WITHDRAWAL_DELAY_BLOCKS
cheats.roll(withdrawal.startBlock + delegationManager.minWithdrawalDelayBlocks());

// Slash all of operator's shares
_setOperatorMagnitude(defaultOperator, strategyMock, 0);
cheats.prank(address(allocationManagerMock));
delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0);

// Complete withdrawal as shares and assert that operator has no shares increased
cheats.roll(block.number + 1);
IERC20[] memory tokens = strategyMock.underlyingToken().toArray();
cheats.expectRevert(FullySlashed.selector);
cheats.prank(defaultStaker);
delegationManager.completeQueuedWithdrawal(withdrawal, tokens, false);
}

/**
* Test completing multiple queued withdrawals for a single strategy by passing in the withdrawals
*/
Expand Down Expand Up @@ -6539,6 +6581,172 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests
assertEq(delegationManager.operatorShares(defaultOperator, strategyMock), 0, "shares should not have changed");
}

/// @notice Verifies that shares are burnable for a withdrawal slashed just before the MIN_WITHDRAWAL_DELAY_BLOCKS is hit
function test_sharesBurnableAtMinDelayBlocks() public {
// Register operator
_registerOperatorWithBaseDetails(defaultOperator);
_setOperatorMagnitude(defaultOperator, strategyMock, WAD);

// Set the staker deposits in the strategies
uint256 depositAmount = 100e18;
strategyManagerMock.addDeposit(defaultStaker, strategyMock, depositAmount);
_delegateToOperatorWhoAcceptsAllStakers(defaultStaker, defaultOperator);

// Queue withdrawal
uint256 withdrawalAmount = depositAmount;
(
QueuedWithdrawalParams[] memory queuedWithdrawalParams,
Withdrawal memory withdrawal,
bytes32 withdrawalRoot
) = _setUpQueueWithdrawalsSingleStrat({
staker: defaultStaker,
withdrawer: defaultStaker,
strategy: strategyMock,
depositSharesToWithdraw: withdrawalAmount
});
cheats.prank(defaultStaker);
delegationManager.queueWithdrawals(queuedWithdrawalParams);

// Warp to just before the MIN_WITHDRAWAL_DELAY_BLOCKS
cheats.roll(withdrawal.startBlock + delegationManager.minWithdrawalDelayBlocks());

// Slash all of operator's shares
_setOperatorMagnitude(defaultOperator, strategyMock, 0);
cheats.prank(address(allocationManagerMock));
delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0);

// Complete withdrawal as tokens and assert that nothing is returned
cheats.roll(block.number + 1);
IERC20[] memory tokens = strategyMock.underlyingToken().toArray();
cheats.expectCall(
address(strategyManagerMock),
abi.encodeWithSelector(
IShareManager.withdrawSharesAsTokens.selector,
defaultStaker,
strategyMock,
strategyMock.underlyingToken(),
0
)
);
cheats.prank(defaultStaker);
delegationManager.completeQueuedWithdrawal(withdrawal, tokens, true);
}

/// @notice Verifies that shares are NOT burnable for a withdrawal queued just before the MIN_WITHDRAWAL_DELAY_BLOCKS
function test_sharesNotBurnableWhenWithdrawalCompletable() public {
// Register operator
_registerOperatorWithBaseDetails(defaultOperator);
_setOperatorMagnitude(defaultOperator, strategyMock, WAD);

// Set the staker deposits in the strategies
uint256 depositAmount = 100e18;
strategyManagerMock.addDeposit(defaultStaker, strategyMock, depositAmount);
_delegateToOperatorWhoAcceptsAllStakers(defaultStaker, defaultOperator);

// Queue withdrawal
uint256 withdrawalAmount = depositAmount;
(
QueuedWithdrawalParams[] memory queuedWithdrawalParams,
Withdrawal memory withdrawal,
bytes32 withdrawalRoot
) = _setUpQueueWithdrawalsSingleStrat({
staker: defaultStaker,
withdrawer: defaultStaker,
strategy: strategyMock,
depositSharesToWithdraw: withdrawalAmount
});
cheats.prank(defaultStaker);
delegationManager.queueWithdrawals(queuedWithdrawalParams);

// Warp to completion time
cheats.roll(withdrawal.startBlock + delegationManager.minWithdrawalDelayBlocks() + 1);
uint256 slashableShares = delegationManager.getSlashableSharesInQueue(defaultOperator, strategyMock);
assertEq(slashableShares, 0, "shares should not be slashable");

// Slash all of operator's shares
_setOperatorMagnitude(defaultOperator, strategyMock, 0);
cheats.prank(address(allocationManagerMock));
delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0);

// Complete withdrawal as tokens and assert that we call back into teh SM with 100 tokens
IERC20[] memory tokens = strategyMock.underlyingToken().toArray();
cheats.expectCall(
address(strategyManagerMock),
abi.encodeWithSelector(
IShareManager.withdrawSharesAsTokens.selector,
defaultStaker,
strategyMock,
strategyMock.underlyingToken(),
100e18
)
);
cheats.prank(defaultStaker);
delegationManager.completeQueuedWithdrawal(withdrawal, tokens, true);
}

/**
* @notice Queues 5 withdrawals at different blocks. Then, warps such that the first 2 are completable. Validates the slashable shares
*/
function test_slashableSharesInQueue() public {
// Register operator
_registerOperatorWithBaseDetails(defaultOperator);
_setOperatorMagnitude(defaultOperator, strategyMock, WAD);

// Set the staker deposits in the strategies
uint256 depositAmount = 120e18;
strategyManagerMock.addDeposit(defaultStaker, strategyMock, depositAmount);
_delegateToOperatorWhoAcceptsAllStakers(defaultStaker, defaultOperator);

// Queue 5 withdrawals
uint256 startBlock = block.number;
uint256 withdrawalAmount = depositAmount / 6;
for(uint256 i = 0; i < 5; i++) {
(
QueuedWithdrawalParams[] memory queuedWithdrawalParams,
Withdrawal memory withdrawal,
bytes32 withdrawalRoot
) = _setUpQueueWithdrawalsSingleStrat({
staker: defaultStaker,
withdrawer: defaultStaker,
strategy: strategyMock,
depositSharesToWithdraw: withdrawalAmount
});
cheats.prank(defaultStaker);
delegationManager.queueWithdrawals(queuedWithdrawalParams);
cheats.roll(startBlock + i + 1);
}

// Warp to completion time for the first 2 withdrawals
// First withdrawal queued at startBlock. Second queued at startBlock + 1
cheats.roll(startBlock + 1 + delegationManager.minWithdrawalDelayBlocks() + 1);

// Get slashable shares
uint256 slashableSharesInQueue = delegationManager.getSlashableSharesInQueue(defaultOperator, strategyMock);
assertEq(slashableSharesInQueue, depositAmount/6 * 3, "slashable shares in queue should be 3/6 of the deposit amount");

// Slash all of operator's shares
_setOperatorMagnitude(defaultOperator, strategyMock, 0);
cheats.prank(address(allocationManagerMock));
cheats.expectEmit(true, true, true, true, address(delegationManager));
emit OperatorSharesDecreased(
defaultOperator,
address(0),
strategyMock,
depositAmount / 6 // 1 withdrawal not queued so decreased
);
cheats.expectEmit(true, true, true, true, address(delegationManager));
emit OperatorSharesBurned(
defaultOperator,
strategyMock,
depositAmount / 6 * 4 // 4 parts are burned
);
delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0);

// Assert slashable shares
slashableSharesInQueue = delegationManager.getSlashableSharesInQueue(defaultOperator, strategyMock);
assertEq(slashableSharesInQueue, 0);
}

/**
* @notice Verifies that `DelegationManager.burnOperatorShares` properly decreases the delegated `shares` that the operator
* who the `defaultStaker` is delegated to has in the strategies
Expand Down

0 comments on commit 8d380fa

Please sign in to comment.