@@ -68,7 +68,6 @@ contract DelegationManagerUnitTests is EigenLayerUnitTestSetup, IDelegationManag
6868 // Helper to use in storage
6969 DepositScalingFactor dsf;
7070 uint256 stakerDSF;
71- uint256 slashingFactor;
7271
7372 /// @notice mappings used to handle duplicate entries in fuzzed address array input
7473 mapping (address => uint256 ) public totalSharesForStrategyInArray;
@@ -6514,6 +6513,69 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage
65146513 assertEq (operatorSharesAfter, operatorSharesBefore + withdrawalAmount, "operator shares not increased correctly " );
65156514 assertFalse (delegationManager.pendingWithdrawals (withdrawalRoot), "withdrawalRoot should be completed and marked false now " );
65166515 }
6516+
6517+ function testFuzz_completeQueuedWithdrawals_OutOfOrderBlocking (Randomness r ) public {
6518+ uint256 totalDepositShares = r.Uint256 (4 , 100 ether);
6519+ uint256 depositSharesPerWithdrawal = totalDepositShares / 4 ;
6520+
6521+ _registerOperatorWithBaseDetails (defaultOperator);
6522+ strategyManagerMock.addDeposit (defaultStaker, strategyMock, totalDepositShares);
6523+ _delegateToOperatorWhoAcceptsAllStakers (defaultStaker, defaultOperator);
6524+
6525+ QueuedWithdrawalParams[] memory queuedParams = new QueuedWithdrawalParams [](4 );
6526+ Withdrawal[] memory withdrawals = new Withdrawal [](4 );
6527+
6528+ uint256 startBlock = block .number ;
6529+
6530+ for (uint256 i; i < 4 ; ++ i) {
6531+ cheats.roll (startBlock + i);
6532+ (
6533+ QueuedWithdrawalParams[] memory params ,
6534+ Withdrawal memory withdrawal ,
6535+ ) = _setUpQueueWithdrawalsSingleStrat (
6536+ defaultStaker,
6537+ defaultStaker,
6538+ strategyMock,
6539+ depositSharesPerWithdrawal
6540+ );
6541+
6542+ (queuedParams[i], withdrawals[i]) = (params[0 ], withdrawal);
6543+ }
6544+
6545+ uint256 delay = delegationManager.minWithdrawalDelayBlocks ();
6546+
6547+ cheats.startPrank (defaultStaker);
6548+ cheats.roll (startBlock);
6549+
6550+ // assertEq(queuedParams[0].effectBlock, block.timestamp);
6551+ delegationManager.queueWithdrawals (queuedParams[0 ].toArray ());
6552+ cheats.roll (startBlock + 1 );
6553+ delegationManager.queueWithdrawals (queuedParams[1 ].toArray ());
6554+
6555+ (
6556+ Withdrawal[] memory firstWithdrawals ,
6557+ uint256 [][] memory firstShares
6558+ ) = delegationManager.getQueuedWithdrawals (defaultStaker);
6559+
6560+ cheats.roll (startBlock + 2 );
6561+ delegationManager.queueWithdrawals (queuedParams[2 ].toArray ());
6562+ cheats.roll (startBlock + 3 );
6563+ delegationManager.queueWithdrawals (queuedParams[3 ].toArray ());
6564+
6565+ IERC20 [][] memory tokens = new IERC20 [][](2 );
6566+ bool [] memory receiveAsTokens = new bool [](2 );
6567+ for (uint256 i; i < 2 ; ++ i) {
6568+ tokens[i] = strategyMock.underlyingToken ().toArray ();
6569+ }
6570+
6571+ cheats.roll (startBlock + delay + 1 );
6572+ delegationManager.completeQueuedWithdrawals (firstWithdrawals, tokens, true .toArray (2 ));
6573+
6574+ // Throws `WithdrawalNotQueued`.
6575+ cheats.roll (startBlock + delay + 2 );
6576+ delegationManager.completeQueuedWithdrawals (withdrawals[2 ].toArray (), tokens, true .toArray ());
6577+ cheats.stopPrank ();
6578+ }
65176579}
65186580
65196581contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests {
@@ -8192,3 +8254,121 @@ contract DelegationManagerUnitTests_Lifecycle is DelegationManagerUnitTests {
81928254 assertEq (delegationManager.operatorShares (newOperator, strategy), 0 , "new operator shares should be unchanged " );
81938255 }
81948256}
8257+
8258+ contract DelegationManagerUnitTests_getQueuedWithdrawals is DelegationManagerUnitTests {
8259+ using ArrayLib for * ;
8260+ using SlashingLib for * ;
8261+
8262+ function _withdrawalRoot (Withdrawal memory withdrawal ) internal pure returns (bytes32 ) {
8263+ return keccak256 (abi.encode (withdrawal));
8264+ }
8265+
8266+ function test_getQueuedWithdrawals_Correctness (Randomness r ) public {
8267+ uint256 numStrategies = r.Uint256 (2 , 8 );
8268+ uint256 [] memory depositShares = r.Uint256Array ({
8269+ len: numStrategies,
8270+ min: 2 ,
8271+ max: 100 ether
8272+ });
8273+
8274+ IStrategy[] memory strategies = _deployAndDepositIntoStrategies (defaultStaker, depositShares, false );
8275+ _registerOperatorWithBaseDetails (defaultOperator);
8276+ _delegateToOperatorWhoAcceptsAllStakers (defaultStaker, defaultOperator);
8277+
8278+ for (uint256 i; i < numStrategies; ++ i) {
8279+ uint256 newStakerShares = depositShares[i] / 2 ;
8280+ _setOperatorMagnitude (defaultOperator, strategies[i], 0.5 ether);
8281+ cheats.prank (address (allocationManagerMock));
8282+ delegationManager.burnOperatorShares (defaultOperator, strategies[i], WAD, 0.5 ether);
8283+ uint256 afterSlash = delegationManager.operatorShares (defaultOperator, strategies[i]);
8284+ assertApproxEqAbs (afterSlash, newStakerShares, 1 , "bad operator shares after slash " );
8285+ }
8286+
8287+ // Queue withdrawals.
8288+ (
8289+ QueuedWithdrawalParams[] memory queuedWithdrawalParams ,
8290+ Withdrawal memory withdrawal ,
8291+ bytes32 withdrawalRoot
8292+ ) = _setUpQueueWithdrawals ({
8293+ staker: defaultStaker,
8294+ withdrawer: defaultStaker,
8295+ strategies: strategies,
8296+ depositWithdrawalAmounts: depositShares
8297+ });
8298+
8299+ cheats.prank (defaultStaker);
8300+ delegationManager.queueWithdrawals (queuedWithdrawalParams);
8301+
8302+ // Get queued withdrawals.
8303+ (Withdrawal[] memory withdrawals , uint256 [][] memory shares ) = delegationManager.getQueuedWithdrawals (defaultStaker);
8304+
8305+ // Checks
8306+ for (uint256 i; i < numStrategies; ++ i) {
8307+ uint256 newStakerShares = depositShares[i] / 2 ;
8308+ assertApproxEqAbs (shares[0 ][i], newStakerShares, 1 , "staker shares should be decreased by half +- 1 " );
8309+ }
8310+
8311+ assertEq (_withdrawalRoot (withdrawal), _withdrawalRoot (withdrawals[0 ]), "_withdrawalRoot(withdrawal) != _withdrawalRoot(withdrawals[0]) " );
8312+ assertEq (_withdrawalRoot (withdrawal), withdrawalRoot, "_withdrawalRoot(withdrawal) != withdrawalRoot " );
8313+ }
8314+
8315+ function test_getQueuedWithdrawals_TotalQueuedGreaterThanTotalStrategies (Randomness r ) public {
8316+ uint256 totalDepositShares = r.Uint256 (2 , 100 ether);
8317+
8318+ _registerOperatorWithBaseDetails (defaultOperator);
8319+ strategyManagerMock.addDeposit (defaultStaker, strategyMock, totalDepositShares);
8320+ _delegateToOperatorWhoAcceptsAllStakers (defaultStaker, defaultOperator);
8321+
8322+ uint256 newStakerShares = totalDepositShares / 2 ;
8323+ _setOperatorMagnitude (defaultOperator, strategyMock, 0.5 ether);
8324+ cheats.prank (address (allocationManagerMock));
8325+ delegationManager.burnOperatorShares (defaultOperator, strategyMock, WAD, 0.5 ether);
8326+ uint256 afterSlash = delegationManager.operatorShares (defaultOperator, strategyMock);
8327+ assertApproxEqAbs (afterSlash, newStakerShares, 1 , "bad operator shares after slash " );
8328+
8329+ // Queue withdrawals.
8330+ (
8331+ QueuedWithdrawalParams[] memory queuedWithdrawalParams0 ,
8332+ Withdrawal memory withdrawal0 ,
8333+ bytes32 withdrawalRoot0
8334+ ) = _setUpQueueWithdrawalsSingleStrat ({
8335+ staker: defaultStaker,
8336+ withdrawer: defaultStaker,
8337+ strategy: strategyMock,
8338+ depositSharesToWithdraw: totalDepositShares / 2
8339+ });
8340+
8341+ cheats.prank (defaultStaker);
8342+ delegationManager.queueWithdrawals (queuedWithdrawalParams0);
8343+
8344+ (
8345+ QueuedWithdrawalParams[] memory queuedWithdrawalParams1 ,
8346+ Withdrawal memory withdrawal1 ,
8347+ bytes32 withdrawalRoot1
8348+ ) = _setUpQueueWithdrawalsSingleStrat ({
8349+ staker: defaultStaker,
8350+ withdrawer: defaultStaker,
8351+ strategy: strategyMock,
8352+ depositSharesToWithdraw: totalDepositShares / 2
8353+ });
8354+
8355+ cheats.prank (defaultStaker);
8356+ delegationManager.queueWithdrawals (queuedWithdrawalParams1);
8357+
8358+ // Get queued withdrawals.
8359+ (Withdrawal[] memory withdrawals , uint256 [][] memory shares ) = delegationManager.getQueuedWithdrawals (defaultStaker);
8360+
8361+ // Sanity
8362+ assertEq (withdrawals.length , 2 , "withdrawal.length != 2 " );
8363+ assertEq (withdrawals[0 ].strategies.length , 1 , "withdrawals[0].strategies.length != 1 " );
8364+ assertEq (withdrawals[1 ].strategies.length , 1 , "withdrawals[1].strategies.length != 1 " );
8365+
8366+ // Checks
8367+ assertApproxEqAbs (shares[0 ][0 ], newStakerShares / 2 , 1 , "shares[0][0] != newStakerShares " );
8368+ assertApproxEqAbs (shares[1 ][0 ], newStakerShares / 2 , 1 , "shares[1][0] != newStakerShares " );
8369+ assertEq (_withdrawalRoot (withdrawal0), _withdrawalRoot (withdrawals[0 ]), "withdrawal0 != withdrawals[0] " );
8370+ assertEq (_withdrawalRoot (withdrawal1), _withdrawalRoot (withdrawals[1 ]), "withdrawal1 != withdrawals[1] " );
8371+ assertEq (_withdrawalRoot (withdrawal0), withdrawalRoot0, "_withdrawalRoot(withdrawal0) != withdrawalRoot0 " );
8372+ assertEq (_withdrawalRoot (withdrawal1), withdrawalRoot1, "_withdrawalRoot(withdrawal1) != withdrawalRoot1 " );
8373+ }
8374+ }
0 commit comments