Skip to content

Commit 0dd35f6

Browse files
0xClandestineypatil12
authored andcommitted
refactor: small cleanup (#959)
refactor small cleanup chore: `forge fmt` fix: `getQueuedWithdrawals` + test fix: add constructor back test: `totalQueued` > `withdrawal.strategies.length` test(wip): `completeQueuedWithdrawals` currently failing fix: effectBlock test(wip): @8sunyuan patch fix: one flaky test fix: second flaky test
1 parent 6ea0584 commit 0dd35f6

File tree

7 files changed

+329
-4
lines changed

7 files changed

+329
-4
lines changed

src/contracts/core/AllocationManager.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ contract AllocationManager is
6363
// Check that the operator set exists and the operator is registered to it
6464
OperatorSet memory operatorSet = OperatorSet(avs, params.operatorSetId);
6565
bool isOperatorSlashable = _isOperatorSlashable(params.operator, operatorSet);
66+
require(params.strategies.length == params.wadsToSlash.length, InputArrayLengthMismatch());
6667
require(_operatorSets[operatorSet.avs].contains(operatorSet.id), InvalidOperatorSet());
6768
require(isOperatorSlashable, OperatorNotSlashable());
6869

src/contracts/core/DelegationManager.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ contract DelegationManager is
964964
for (uint256 j; j < withdrawals[i].strategies.length; ++j) {
965965
shares[i][j] = SlashingLib.scaleForCompleteWithdrawal({
966966
scaledShares: withdrawals[i].scaledShares[j],
967-
slashingFactor: slashingFactors[i]
967+
slashingFactor: slashingFactors[j]
968968
});
969969
}
970970
}

src/contracts/interfaces/IAllocationManager.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ pragma solidity >=0.5.0;
44
import {OperatorSet} from "../libraries/OperatorSetLib.sol";
55
import "./IPauserRegistry.sol";
66
import "./IStrategy.sol";
7-
import "./ISignatureUtils.sol";
87
import "./IAVSRegistrar.sol";
98

109
interface IAllocationManagerErrors {
@@ -213,7 +212,7 @@ interface IAllocationManagerEvents is IAllocationManagerTypes {
213212
event StrategyRemovedFromOperatorSet(OperatorSet operatorSet, IStrategy strategy);
214213
}
215214

216-
interface IAllocationManager is ISignatureUtils, IAllocationManagerErrors, IAllocationManagerEvents {
215+
interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEvents {
217216
/**
218217
* @dev Initializes the initial owner and paused status.
219218
*/

src/test/unit/AllocationManagerUnit.t.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,15 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests
613613
allocationManager.slashOperator(defaultAVS, _randSlashingParams(random().Address(), 0));
614614
}
615615

616+
function test_revert_InputArrayLengthMismatch() public {
617+
SlashingParams memory slashingParams = _randSlashingParams(defaultOperator, 0);
618+
slashingParams.strategies = slashingParams.strategies.setLength(2);
619+
620+
cheats.prank(defaultAVS);
621+
cheats.expectRevert(InputArrayLengthMismatch.selector);
622+
allocationManager.slashOperator(defaultAVS, slashingParams);
623+
}
624+
616625
function test_revert_StrategiesMustBeInAscendingOrder() public {
617626
IStrategy[] memory strategies = new IStrategy[](3);
618627
strategies[0] = IStrategy(address(3));

src/test/unit/DelegationUnit.t.sol

Lines changed: 196 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

65616641
contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests {
@@ -8549,6 +8629,121 @@ contract DelegationManagerUnitTests_ConvertToDepositShares is DelegationManagerU
85498629

85508630
contract 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

src/test/utils/ArrayLib.sol

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ library ArrayLib {
152152
array[0] = withdrawal;
153153
}
154154

155+
function toArray(
156+
IDelegationManagerTypes.QueuedWithdrawalParams memory queuedWithdrawalParams
157+
) internal pure returns (IDelegationManagerTypes.QueuedWithdrawalParams[] memory array) {
158+
array = new IDelegationManagerTypes.QueuedWithdrawalParams[](1);
159+
array[0] = queuedWithdrawalParams;
160+
}
161+
155162
/// -----------------------------------------------------------------------
156163
/// Length Updates
157164
/// -----------------------------------------------------------------------
@@ -236,6 +243,16 @@ library ArrayLib {
236243
return array;
237244
}
238245

246+
function setLength(
247+
IDelegationManagerTypes.Withdrawal[] memory array,
248+
uint256 len
249+
) internal pure returns (IDelegationManagerTypes.Withdrawal[] memory) {
250+
assembly {
251+
mstore(array, len)
252+
}
253+
return array;
254+
}
255+
239256
/// -----------------------------------------------------------------------
240257
/// Contains
241258
/// -----------------------------------------------------------------------
@@ -310,6 +327,26 @@ library ArrayLib {
310327
return false;
311328
}
312329

330+
function contains(
331+
OperatorSet[] memory array,
332+
OperatorSet memory x
333+
) internal pure returns (bool) {
334+
for (uint256 i; i < array.length; ++i) {
335+
if (keccak256(abi.encode(array[i])) == keccak256(abi.encode(x))) return true;
336+
}
337+
return false;
338+
}
339+
340+
function contains(
341+
IDelegationManagerTypes.Withdrawal[] memory array,
342+
IDelegationManagerTypes.Withdrawal memory x
343+
) internal pure returns (bool) {
344+
for (uint256 i; i < array.length; ++i) {
345+
if (keccak256(abi.encode(array[i])) == keccak256(abi.encode(x))) return true;
346+
}
347+
return false;
348+
}
349+
313350
/// -----------------------------------------------------------------------
314351
/// indexOf
315352
/// -----------------------------------------------------------------------
@@ -384,6 +421,26 @@ library ArrayLib {
384421
return type(uint256).max;
385422
}
386423

424+
function indexOf(
425+
OperatorSet[] memory array,
426+
OperatorSet memory x
427+
) internal pure returns (uint256) {
428+
for (uint256 i; i < array.length; ++i) {
429+
if (keccak256(abi.encode(array[i])) == keccak256(abi.encode(x))) return i;
430+
}
431+
return type(uint256).max;
432+
}
433+
434+
function indexOf(
435+
IDelegationManagerTypes.Withdrawal[] memory array,
436+
IDelegationManagerTypes.Withdrawal memory x
437+
) internal pure returns (uint256) {
438+
for (uint256 i; i < array.length; ++i) {
439+
if (keccak256(abi.encode(array[i])) == keccak256(abi.encode(x))) return i;
440+
}
441+
return type(uint256).max;
442+
}
443+
387444
/// -----------------------------------------------------------------------
388445
/// Sorting
389446
/// -----------------------------------------------------------------------

0 commit comments

Comments
 (0)