@@ -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;
@@ -6556,6 +6555,87 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage
65566555 assertEq (operatorSharesAfter, operatorSharesBefore + withdrawalAmount, "operator shares not increased correctly " );
65576556 assertFalse (delegationManager.pendingWithdrawals (withdrawalRoot), "withdrawalRoot should be completed and marked false now " );
65586557 }
6558+
6559+ function testFuzz_completeQueuedWithdrawals_OutOfOrderBlocking (Randomness r ) public {
6560+ uint256 totalDepositShares = r.Uint256 (4 , 100 ether);
6561+ uint256 depositSharesPerWithdrawal = totalDepositShares / 4 ;
6562+
6563+ _registerOperatorWithBaseDetails (defaultOperator);
6564+ strategyManagerMock.addDeposit (defaultStaker, strategyMock, totalDepositShares);
6565+ _delegateToOperatorWhoAcceptsAllStakers (defaultStaker, defaultOperator);
6566+
6567+ QueuedWithdrawalParams[] memory queuedParams = new QueuedWithdrawalParams [](4 );
6568+ Withdrawal[] memory withdrawals = new Withdrawal [](4 );
6569+
6570+ uint256 startBlock = block .number ;
6571+
6572+ uint256 nonce = delegationManager.cumulativeWithdrawalsQueued (defaultStaker);
6573+ for (uint256 i; i < 4 ; ++ i) {
6574+ cheats.roll (startBlock + i);
6575+ (
6576+ QueuedWithdrawalParams[] memory params ,
6577+ Withdrawal memory withdrawal ,
6578+ ) = _setUpQueueWithdrawalsSingleStrat (
6579+ defaultStaker,
6580+ defaultStaker,
6581+ strategyMock,
6582+ depositSharesPerWithdrawal
6583+ );
6584+ withdrawal.nonce = nonce;
6585+ nonce += 1 ;
6586+
6587+ (queuedParams[i], withdrawals[i]) = (params[0 ], withdrawal);
6588+ }
6589+
6590+ uint256 delay = delegationManager.minWithdrawalDelayBlocks ();
6591+
6592+ cheats.startPrank (defaultStaker);
6593+ cheats.roll (startBlock);
6594+
6595+ delegationManager.queueWithdrawals (queuedParams[0 ].toArray ());
6596+ cheats.roll (startBlock + 1 );
6597+ delegationManager.queueWithdrawals (queuedParams[1 ].toArray ());
6598+
6599+ (
6600+ Withdrawal[] memory firstWithdrawals ,
6601+ uint256 [][] memory firstShares
6602+ ) = delegationManager.getQueuedWithdrawals (defaultStaker);
6603+
6604+ cheats.roll (startBlock + 2 );
6605+ delegationManager.queueWithdrawals (queuedParams[2 ].toArray ());
6606+ cheats.roll (startBlock + 3 );
6607+ delegationManager.queueWithdrawals (queuedParams[3 ].toArray ());
6608+
6609+ IERC20 [][] memory tokens = new IERC20 [][](2 );
6610+ bool [] memory receiveAsTokens = new bool [](2 );
6611+ for (uint256 i; i < 2 ; ++ i) {
6612+ tokens[i] = strategyMock.underlyingToken ().toArray ();
6613+ }
6614+
6615+ bytes32 root1 = delegationManager.calculateWithdrawalRoot (withdrawals[0 ]);
6616+ bytes32 root2 = delegationManager.calculateWithdrawalRoot (withdrawals[1 ]);
6617+
6618+ bytes32 root1_view = delegationManager.calculateWithdrawalRoot (firstWithdrawals[0 ]);
6619+ bytes32 root2_view = delegationManager.calculateWithdrawalRoot (firstWithdrawals[1 ]);
6620+
6621+ assertEq (
6622+ root1, root1_view,
6623+ "withdrawal root should be the same "
6624+ );
6625+
6626+ assertEq (
6627+ root2, root2_view,
6628+ "withdrawal root should be the same "
6629+ );
6630+
6631+ cheats.roll (startBlock + delay + 2 );
6632+ delegationManager.completeQueuedWithdrawals (firstWithdrawals, tokens, true .toArray (2 ));
6633+
6634+ // Throws `WithdrawalNotQueued`.
6635+ cheats.roll (startBlock + delay + 3 );
6636+ delegationManager.completeQueuedWithdrawals (withdrawals[2 ].toArray (), tokens, true .toArray ());
6637+ cheats.stopPrank ();
6638+ }
65596639}
65606640
65616641contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests {
@@ -8549,6 +8629,121 @@ contract DelegationManagerUnitTests_ConvertToDepositShares is DelegationManagerU
85498629
85508630contract DelegationManagerUnitTests_getQueuedWithdrawals is DelegationManagerUnitTests {
85518631 using ArrayLib for * ;
8632+ using SlashingLib for * ;
8633+
8634+ function _withdrawalRoot (Withdrawal memory withdrawal ) internal pure returns (bytes32 ) {
8635+ return keccak256 (abi.encode (withdrawal));
8636+ }
8637+
8638+ function test_getQueuedWithdrawals_Correctness (Randomness r ) public rand (r) {
8639+ uint256 numStrategies = r.Uint256 (2 , 8 );
8640+ uint256 [] memory depositShares = r.Uint256Array ({
8641+ len: numStrategies,
8642+ min: 2 ,
8643+ max: 100 ether
8644+ });
8645+
8646+ IStrategy[] memory strategies = _deployAndDepositIntoStrategies (defaultStaker, depositShares, false );
8647+ _registerOperatorWithBaseDetails (defaultOperator);
8648+ _delegateToOperatorWhoAcceptsAllStakers (defaultStaker, defaultOperator);
8649+
8650+ for (uint256 i; i < numStrategies; ++ i) {
8651+ uint256 newStakerShares = depositShares[i] / 2 ;
8652+ _setOperatorMagnitude (defaultOperator, strategies[i], 0.5 ether);
8653+ cheats.prank (address (allocationManagerMock));
8654+ delegationManager.burnOperatorShares (defaultOperator, strategies[i], WAD, 0.5 ether);
8655+ uint256 afterSlash = delegationManager.operatorShares (defaultOperator, strategies[i]);
8656+ assertApproxEqAbs (afterSlash, newStakerShares, 1 , "bad operator shares after slash " );
8657+ }
8658+
8659+ // Queue withdrawals.
8660+ (
8661+ QueuedWithdrawalParams[] memory queuedWithdrawalParams ,
8662+ Withdrawal memory withdrawal ,
8663+ bytes32 withdrawalRoot
8664+ ) = _setUpQueueWithdrawals ({
8665+ staker: defaultStaker,
8666+ withdrawer: defaultStaker,
8667+ strategies: strategies,
8668+ depositWithdrawalAmounts: depositShares
8669+ });
8670+
8671+ cheats.prank (defaultStaker);
8672+ delegationManager.queueWithdrawals (queuedWithdrawalParams);
8673+
8674+ // Get queued withdrawals.
8675+ (Withdrawal[] memory withdrawals , uint256 [][] memory shares ) = delegationManager.getQueuedWithdrawals (defaultStaker);
8676+ // Checks
8677+ for (uint256 i; i < strategies.length ; ++ i) {
8678+ uint256 newStakerShares = depositShares[i] / 2 ;
8679+ assertApproxEqAbs (shares[0 ][i], newStakerShares, 1 , "staker shares should be decreased by half +- 1 " );
8680+ }
8681+
8682+ assertEq (_withdrawalRoot (withdrawal), _withdrawalRoot (withdrawals[0 ]), "_withdrawalRoot(withdrawal) != _withdrawalRoot(withdrawals[0]) " );
8683+ assertEq (_withdrawalRoot (withdrawal), withdrawalRoot, "_withdrawalRoot(withdrawal) != withdrawalRoot " );
8684+ }
8685+
8686+ function test_getQueuedWithdrawals_TotalQueuedGreaterThanTotalStrategies (
8687+ Randomness r
8688+ ) public rand (r) {
8689+ uint256 totalDepositShares = r.Uint256 (2 , 100 ether);
8690+
8691+ _registerOperatorWithBaseDetails (defaultOperator);
8692+ strategyManagerMock.addDeposit (defaultStaker, strategyMock, totalDepositShares);
8693+ _delegateToOperatorWhoAcceptsAllStakers (defaultStaker, defaultOperator);
8694+
8695+ uint256 newStakerShares = totalDepositShares / 2 ;
8696+ _setOperatorMagnitude (defaultOperator, strategyMock, 0.5 ether);
8697+ cheats.prank (address (allocationManagerMock));
8698+ delegationManager.burnOperatorShares (defaultOperator, strategyMock, WAD, 0.5 ether);
8699+ uint256 afterSlash = delegationManager.operatorShares (defaultOperator, strategyMock);
8700+ assertApproxEqAbs (afterSlash, newStakerShares, 1 , "bad operator shares after slash " );
8701+
8702+ // Queue withdrawals.
8703+ (
8704+ QueuedWithdrawalParams[] memory queuedWithdrawalParams0 ,
8705+ Withdrawal memory withdrawal0 ,
8706+ bytes32 withdrawalRoot0
8707+ ) = _setUpQueueWithdrawalsSingleStrat ({
8708+ staker: defaultStaker,
8709+ withdrawer: defaultStaker,
8710+ strategy: strategyMock,
8711+ depositSharesToWithdraw: totalDepositShares / 2
8712+ });
8713+
8714+ cheats.prank (defaultStaker);
8715+ delegationManager.queueWithdrawals (queuedWithdrawalParams0);
8716+
8717+ (
8718+ QueuedWithdrawalParams[] memory queuedWithdrawalParams1 ,
8719+ Withdrawal memory withdrawal1 ,
8720+ bytes32 withdrawalRoot1
8721+ ) = _setUpQueueWithdrawalsSingleStrat ({
8722+ staker: defaultStaker,
8723+ withdrawer: defaultStaker,
8724+ strategy: strategyMock,
8725+ depositSharesToWithdraw: totalDepositShares / 2
8726+ });
8727+
8728+ cheats.prank (defaultStaker);
8729+ delegationManager.queueWithdrawals (queuedWithdrawalParams1);
8730+
8731+ // Get queued withdrawals.
8732+ (Withdrawal[] memory withdrawals , uint256 [][] memory shares ) = delegationManager.getQueuedWithdrawals (defaultStaker);
8733+
8734+ // Sanity
8735+ assertEq (withdrawals.length , 2 , "withdrawal.length != 2 " );
8736+ assertEq (withdrawals[0 ].strategies.length , 1 , "withdrawals[0].strategies.length != 1 " );
8737+ assertEq (withdrawals[1 ].strategies.length , 1 , "withdrawals[1].strategies.length != 1 " );
8738+
8739+ // Checks
8740+ assertApproxEqAbs (shares[0 ][0 ], newStakerShares / 2 , 1 , "shares[0][0] != newStakerShares " );
8741+ assertApproxEqAbs (shares[1 ][0 ], newStakerShares / 2 , 1 , "shares[1][0] != newStakerShares " );
8742+ assertEq (_withdrawalRoot (withdrawal0), _withdrawalRoot (withdrawals[0 ]), "withdrawal0 != withdrawals[0] " );
8743+ assertEq (_withdrawalRoot (withdrawal1), _withdrawalRoot (withdrawals[1 ]), "withdrawal1 != withdrawals[1] " );
8744+ assertEq (_withdrawalRoot (withdrawal0), withdrawalRoot0, "_withdrawalRoot(withdrawal0) != withdrawalRoot0 " );
8745+ assertEq (_withdrawalRoot (withdrawal1), withdrawalRoot1, "_withdrawalRoot(withdrawal1) != withdrawalRoot1 " );
8746+ }
85528747
85538748 /**
85548749 * @notice Assert that the shares returned in the view function `getQueuedWithdrawals` are unaffected from a
0 commit comments