diff --git a/src/contracts/core/AllocationManager.sol b/src/contracts/core/AllocationManager.sol index 8e8fb2ac8..30c362175 100644 --- a/src/contracts/core/AllocationManager.sol +++ b/src/contracts/core/AllocationManager.sol @@ -123,6 +123,12 @@ contract AllocationManager is // 5. Update state _updateAllocationInfo(params.operator, operatorSet.key(), params.strategies[i], info, allocation); + + // Emit an event for the updated allocation + emit AllocationUpdated( + params.operator, operatorSet, params.strategies[i], allocation.currentMagnitude, uint32(block.number) + ); + _updateMaxMagnitude(params.operator, params.strategies[i], info.maxMagnitude); // 6. Decrease and burn operators shares in the DelegationManager @@ -201,6 +207,7 @@ contract AllocationManager is allocation.currentMagnitude = params[i].newMagnitudes[j]; allocation.pendingDiff = 0; + allocation.effectBlock = uint32(block.number); } } else if (allocation.pendingDiff > 0) { // Allocation immediately consumes available magnitude, but the additional @@ -213,6 +220,15 @@ contract AllocationManager is // 5. Update state _updateAllocationInfo(operator, operatorSet.key(), strategy, info, allocation); + + // 6. Emit an event for the updated allocation + emit AllocationUpdated( + operator, + OperatorSetLib.decode(operatorSet.key()), + strategy, + _addInt128(allocation.currentMagnitude, allocation.pendingDiff), + allocation.effectBlock + ); } } } @@ -292,7 +308,7 @@ contract AllocationManager is function setAllocationDelay(address operator, uint32 delay) external { if (msg.sender != address(delegation)) { require(_checkCanCall(operator), InvalidCaller()); - require(delegation.isOperator(operator), OperatorNotRegistered()); + require(delegation.isOperator(operator), InvalidOperator()); } _setAllocationDelay(operator, delay); } @@ -321,7 +337,6 @@ contract AllocationManager is // Add strategies to the operator set bytes32 operatorSetKey = operatorSet.key(); - for (uint256 j = 0; j < params[i].strategies.length; j++) { _operatorSetStrategies[operatorSetKey].add(address(params[i].strategies[j])); emit StrategyAddedToOperatorSet(operatorSet, params[i].strategies[j]); @@ -497,15 +512,18 @@ contract AllocationManager is StrategyInfo memory info, Allocation memory allocation ) internal { - // Update encumbered magnitude - encumberedMagnitude[operator][strategy] = info.encumberedMagnitude; - emit EncumberedMagnitudeUpdated(operator, strategy, info.encumberedMagnitude); + // Update encumbered magnitude if it has changed + // The mapping should NOT be updated when there is a deallocation on a delay + if (encumberedMagnitude[operator][strategy] != info.encumberedMagnitude) { + encumberedMagnitude[operator][strategy] = info.encumberedMagnitude; + emit EncumberedMagnitudeUpdated(operator, strategy, info.encumberedMagnitude); + } // Update allocation for this operator set from the strategy + // We emit an `AllocationUpdated` from the `modifyAllocations` and `slashOperator` functions. + // `clearDeallocationQueue` does not emit an `AllocationUpdated` event since it was + // emitted when the deallocation was queued allocations[operator][operatorSetKey][strategy] = allocation; - emit AllocationUpdated( - operator, OperatorSetLib.decode(operatorSetKey), strategy, allocation.currentMagnitude, uint32(block.number) - ); // Note: these no-op if the sets already contain the added values (or do not contain removed ones) if (allocation.pendingDiff != 0) { @@ -639,7 +657,7 @@ contract AllocationManager is Allocation memory allocation = allocations[operator][operatorSetKey][strategy]; // If we've reached a pending deallocation that isn't completable yet, - // we can stop. Any subsequent modificaitons will also be uncompletable. + // we can stop. Any subsequent modifications will also be uncompletable. if (block.number < allocation.effectBlock) { break; } diff --git a/src/contracts/core/AllocationManagerStorage.sol b/src/contracts/core/AllocationManagerStorage.sol index f86d975cd..c5d397ec8 100644 --- a/src/contracts/core/AllocationManagerStorage.sol +++ b/src/contracts/core/AllocationManagerStorage.sol @@ -87,6 +87,8 @@ abstract contract AllocationManagerStorage is IAllocationManager { _maxMagnitudeHistory; /// @dev For a strategy, contains the amount of magnitude an operator has allocated to operator sets + /// @dev This value should be read with caution, as deallocations that are completable but not + /// popped off the queue are still included in the encumbered magnitude mapping(address operator => mapping(IStrategy strategy => uint64)) public encumberedMagnitude; /// @dev For a strategy, keeps an ordered queue of operator sets that have pending deallocations diff --git a/src/contracts/interfaces/IAllocationManager.sol b/src/contracts/interfaces/IAllocationManager.sol index 4b41edfb1..8fb29a3dd 100644 --- a/src/contracts/interfaces/IAllocationManager.sol +++ b/src/contracts/interfaces/IAllocationManager.sol @@ -26,8 +26,6 @@ interface IAllocationManagerErrors { /// @dev Thrown when an invalid operator is provided. error InvalidOperator(); - /// @dev Thrown when `operator` is not a registered operator. - error OperatorNotRegistered(); /// @dev Thrown when an operator's allocation delay has yet to be set. error UninitializedAllocationDelay(); /// @dev Thrown when attempting to slash an operator when they are not slashable. diff --git a/src/test/integration/IntegrationDeployer.t.sol b/src/test/integration/IntegrationDeployer.t.sol index 0f6a36909..46685e0ed 100644 --- a/src/test/integration/IntegrationDeployer.t.sol +++ b/src/test/integration/IntegrationDeployer.t.sol @@ -46,8 +46,6 @@ uint8 constant PAUSED_NON_PROOF_WITHDRAWALS = 5; abstract contract IntegrationDeployer is ExistingDeploymentParser, Logger { using StdStyle for *; - using ArrayLib for *; - using ArrayLib for IStrategy[]; // Fork ids for specific fork tests bool isUpgraded; diff --git a/src/test/unit/AllocationManagerUnit.t.sol b/src/test/unit/AllocationManagerUnit.t.sol index edf7f8c43..d5a90bc7e 100644 --- a/src/test/unit/AllocationManagerUnit.t.sol +++ b/src/test/unit/AllocationManagerUnit.t.sol @@ -19,7 +19,6 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag uint256 internal constant FUZZ_MAX_OP_SETS = 8; uint8 internal constant MAX_OPERATOR_SET_STRATEGY_LIST_LENGTH = 33; - uint8 internal constant PAUSED_MODIFY_ALLOCATIONS = 0; uint8 internal constant PAUSED_OPERATOR_SLASHING = 1; uint8 internal constant PAUSED_OPERATOR_SET_REGISTRATION_AND_DEREGISTRATION = 2; @@ -48,6 +47,11 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag address defaultOperator = address(this); address defaultAVS = address(new MockAVSRegistrar()); + /// ----------------------------------------------------------------------- + /// Internal Storage Helpers + /// ----------------------------------------------------------------------- + mapping(IStrategy => uint64) _encumberedMagnitudes; + /// ----------------------------------------------------------------------- /// Setup /// ----------------------------------------------------------------------- @@ -65,7 +69,6 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag ) ) ); - defaultStrategies = strategyMock.toArray(); defaultOperatorSet = OperatorSet(defaultAVS, 0); @@ -122,7 +125,8 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag ) internal returns (OperatorSet memory) { cheats.prank(operatorSet.avs); allocationManager.createOperatorSets( - operatorSet.avs, CreateSetParams({operatorSetId: operatorSet.id, strategies: strategies}).toArray() + operatorSet.avs, + CreateSetParams({operatorSetId: operatorSet.id, strategies: strategies}).toArray() ); return operatorSet; } @@ -141,7 +145,8 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag function _registerForOperatorSet(address operator, OperatorSet memory operatorSet) internal { cheats.prank(operator); allocationManager.registerForOperatorSets( - operator, RegisterParams({avs: operatorSet.avs, operatorSetIds: operatorSet.id.toArrayU32(), data: ""}) + operator, + RegisterParams({avs: operatorSet.avs, operatorSetIds: operatorSet.id.toArrayU32(), data: ""}) ); } @@ -161,53 +166,114 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag cheats.stopPrank(); } - function _checkAllocationStorage( - Allocation memory allocation, - uint256 expectedCurrentMagnitude, - int256 expectedPendingDiff, - uint256 expectedEffectBlock - ) internal view { - console.log("Check Allocation Storage:".yellow()); - console.log(" currentMagnitude = %d", allocation.currentMagnitude); - console.log(" pendingDiff = %d", allocation.pendingDiff); - console.log(" effectBlock = %d", allocation.effectBlock); - console.log(" currentBlock = %d", block.number); - console.log("\n"); + struct Magnitudes { + uint256 encumbered; + uint256 max; + uint256 allocatable; + } - assertApproxEqAbs(expectedCurrentMagnitude, allocation.currentMagnitude, 1, "currentMagnitude != expected"); - assertEq(expectedPendingDiff, allocation.pendingDiff, "pendingDiff != expected"); - assertEq(expectedEffectBlock, allocation.effectBlock, "effectBlock != expected"); + /** + * Get expected post slash storage values + * Assumes that: + * 1. WAD is max before slash + * 2. encumbered is equal to magnitude before slash + */ + function _getExpectedSlashVals( + uint256 wadToSlash, + uint64 magBeforeSlash + ) internal pure returns (uint256 wadSlashed, uint64 newCurrentMag, uint64 newMaxMag, uint64 newEncumberedMag) { + return _getExpectedSlashVals(wadToSlash, magBeforeSlash, magBeforeSlash); + } + /** + * Get expected post slash storage values + * Assumes that: + * 1. WAD is max before slash + */ + function _getExpectedSlashVals( + uint256 wadToSlash, + uint64 magBeforeSlash, + uint64 encumberedMagBeforeSlash + ) internal pure returns (uint256 wadSlashed, uint64 newCurrentMag, uint64 newMaxMag, uint64 newEncumberedMag) { + // Get slippage to apply to returned values - we basically recreate mulWadRoundUp here + uint64 slippage = _calculateSlippage(magBeforeSlash, wadToSlash); + // Get the magnitude to slash - this value is rounded UP in the implementation + uint64 slashedMag = uint64((uint256(magBeforeSlash) * wadToSlash / WAD + slippage)); + wadSlashed = slashedMag; + newCurrentMag = magBeforeSlash - slashedMag; + newMaxMag = WAD - slashedMag; + newEncumberedMag = encumberedMagBeforeSlash - slashedMag; + } + + /// @dev Returns 0 or 1, depending on the remainder of the division + function _calculateSlippage(uint64 magnitude, uint256 wadToSlash) internal pure returns (uint64) { + return mulmod(magnitude, wadToSlash, WAD) > 0 ? 1 : 0; } function _checkAllocationStorage( address operator, OperatorSet memory operatorSet, IStrategy strategy, - uint256 expectedCurrentMagnitude, - int256 expectedPendingDiff, - uint256 expectedEffectBlock + Allocation memory expectedAllocation, + Magnitudes memory expectedMagnitudes ) internal view { - Allocation memory getAllocation = allocationManager.getAllocation(operator, operatorSet, strategy); + Allocation memory allocation = allocationManager.getAllocation(operator, operatorSet, strategy); + + console.log("\nChecking Allocation Storage:".yellow()); + console.log(" currentMagnitude: %d", allocation.currentMagnitude); + console.log(" pendingDiff: %d", allocation.pendingDiff); + console.log(" effectBlock: %d", allocation.effectBlock); + + assertEq( + expectedAllocation.currentMagnitude, allocation.currentMagnitude, "currentMagnitude != expected" + ); + assertEq(expectedAllocation.pendingDiff, allocation.pendingDiff, "pendingDiff != expected"); + assertEq(expectedAllocation.effectBlock, allocation.effectBlock, "effectBlock != expected"); + + uint256 encumberedMagnitude = allocationManager.encumberedMagnitude(operator, strategy); + uint256 maxMagnitude = allocationManager.getMaxMagnitudes(operator, strategy.toArray())[0]; + uint256 allocatableMagnitude = allocationManager.getAllocatableMagnitude(operator, strategy); + + console.log(" encumberedMagnitude: %d", encumberedMagnitude); + console.log(" maxMagnitude: %d", maxMagnitude); + console.log(" allocatableMagnitude: %d", allocatableMagnitude); + + assertEq(expectedMagnitudes.encumbered, encumberedMagnitude, "encumberedMagnitude != expected"); + assertEq(expectedMagnitudes.max, maxMagnitude, "maxMagnitude != expected"); + assertEq(expectedMagnitudes.allocatable, allocatableMagnitude, "allocatableMagnitude != expected"); + + // Check `getMaxMagnitudes` alias for coverage. + assertEq( + expectedMagnitudes.max, + allocationManager.getMaxMagnitudes(operator.toArray(), strategy)[0], + "maxMagnitude != expected" + ); + + // Check `getAllocations` alias for coverage. Allocation memory getAllocations = allocationManager.getAllocations(operator.toArray(), operatorSet, strategy)[0]; - _checkAllocationStorage(getAllocation, expectedCurrentMagnitude, expectedPendingDiff, expectedEffectBlock); - _checkAllocationStorage(getAllocations, expectedCurrentMagnitude, expectedPendingDiff, expectedEffectBlock); + assertEq( + expectedAllocation.currentMagnitude, getAllocations.currentMagnitude, "currentMagnitude != expected" + ); + assertEq(expectedAllocation.pendingDiff, getAllocations.pendingDiff, "pendingDiff != expected"); + assertEq(expectedAllocation.effectBlock, getAllocations.effectBlock, "effectBlock != expected"); + + console.log("Success!".green().bold()); } function _checkSlashableStake( OperatorSet memory operatorSet, address operator, IStrategy[] memory strategies, - uint256 expectedStake + uint256 expectedSlashableStake ) internal view { - _checkSlashableStake(operatorSet, operator, strategies, expectedStake, block.number); + _checkSlashableStake(operatorSet, operator, strategies, expectedSlashableStake, block.number); } function _checkSlashableStake( OperatorSet memory operatorSet, address operator, IStrategy[] memory strategies, - uint256 expectedStake, + uint256 expectedSlashableStake, uint256 futureBlock ) internal view { uint256[] memory slashableStake = allocationManager.getMinimumSlashableStake({ @@ -218,36 +284,94 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag })[0]; for (uint256 i = 0; i < strategies.length; i++) { - console.log(StdStyle.yellow("Check Slashable Stake:")); + console.log("\nChecking Slashable Stake:".yellow()); console.log(" slashableStake[%d] = %d", i, slashableStake[i]); - console.log("\n"); - assertApproxEqAbs(slashableStake[i], expectedStake, 1, "slashableStake != expected"); + assertEq(slashableStake[i], expectedSlashableStake, "slashableStake != expected"); } + + console.log("Success!".green().bold()); } function _checkAllocationEvents( address operator, OperatorSet memory operatorSet, IStrategy strategy, - uint64 currentMagnitude, + uint64 magnitude, uint64 encumberedMagnitude, uint32 effectBlock ) internal { - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit EncumberedMagnitudeUpdated(operator, strategy, encumberedMagnitude); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit AllocationUpdated(operator, operatorSet, strategy, magnitude, effectBlock); + } + + function _checkDeallocationEvent( + address operator, + OperatorSet memory operatorSet, + IStrategy strategy, + uint64 magnitude, + uint32 effectBlock + ) internal { + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit AllocationUpdated(operator, operatorSet, strategy, magnitude, effectBlock); + } + + function _checkClearDeallocationQueueEvents( + address operator, + IStrategy strategy, + uint64 encumberedMagnitude + ) internal { + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit EncumberedMagnitudeUpdated(operator, strategy, encumberedMagnitude); - cheats.expectEmit(true, false, false, false, address(allocationManager)); - emit AllocationUpdated(operator, operatorSet, strategy, currentMagnitude, effectBlock); + } + + function _checkSlashEvents( + address operator, + OperatorSet memory operatorSet, + IStrategy strategy, + uint256 wadToSlash, + string memory description, + uint64 currentMag, + uint64 maxMag, + uint64 encumberedMag + ) internal { + return _checkSlashEvents( + operator, + operatorSet, + strategy.toArray(), + wadToSlash.toArrayU256(), + description, + currentMag.toArrayU64(), + maxMag.toArrayU64(), + encumberedMag.toArrayU64() + ); } function _checkSlashEvents( address operator, OperatorSet memory operatorSet, IStrategy[] memory strategies, - uint256[] memory wadsToSlash, - string memory description + uint256[] memory wadToSlash, + string memory description, + uint64[] memory currentMags, + uint64[] memory maxMags, + uint64[] memory encumberedMags ) internal { - cheats.expectEmit(true, false, false, false, address(allocationManager)); - emit OperatorSlashed(operator, operatorSet, strategies, wadsToSlash, description); + for(uint256 i = 0; i < strategies.length; i++) { + // If there is nothing slashed, we don't emit events for encumbered magnitude + if (wadToSlash[i] == 0) { + continue; + } + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit EncumberedMagnitudeUpdated(operator, strategies[i], encumberedMags[i]); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit AllocationUpdated(operator, operatorSet, strategies[i], currentMags[i], uint32(block.number)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit MaxMagnitudeUpdated(operator, strategies[i], maxMags[i]); + } + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit OperatorSlashed(operator, operatorSet, strategies, wadToSlash, description); } /// ----------------------------------------------------------------------- @@ -394,6 +518,10 @@ contract AllocationManagerUnitTests is EigenLayerUnitTestSetup, IAllocationManag numToClear[0] = type(uint16).max; return numToClear; } + + function _defaultAllocEffectBlock() internal view returns (uint32) { + return uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + } } contract AllocationManagerUnitTests_Initialization_Setters is AllocationManagerUnitTests { @@ -473,6 +601,12 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.slashOperator(defaultAVS, slashingParams); } + function test_revert_NotRegisteredToSet() public { + cheats.prank(defaultAVS); + cheats.expectRevert(OperatorNotSlashable.selector); + allocationManager.slashOperator(defaultAVS, _randSlashingParams(random().Address(), 0)); + } + function test_revert_NotMemberOfSet() public { cheats.prank(defaultAVS); cheats.expectRevert(OperatorNotSlashable.selector); @@ -528,15 +662,30 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests ); } - function test_revert_operatorAllocated_notActive() public { + /** + * Attempts to slash an operator before the allocation is active + * Validates: + * 1. The events of the slash indicate nothing was slashed + * 2. Storage is not mutated post slash + * 3. The operator's allocation takes effect as normal post slash + */ + function test_operatorAllocated_notActive() public { AllocateParams[] memory allocateParams = _newAllocateParams(defaultOperatorSet, WAD); cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, allocateParams); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + + uint64 encumberedMagnitudeBefore = allocationManager.encumberedMagnitude(defaultOperator, strategyMock); + uint64 maxMagnitudeBefore = allocationManager.getMaxMagnitudes(defaultOperator, strategyMock.toArray())[0]; + + // The only slash event we expect is the OperatorSlashed. Validate the number + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit OperatorSlashed(defaultOperator, defaultOperatorSet, defaultStrategies, uint256(0).toArrayU256(), "test"); + uint256 numLogsBefore = cheats.getRecordedLogs().length; cheats.prank(defaultAVS); allocationManager.slashOperator( - defaultAVS, + defaultAVS, SlashingParams({ operator: defaultOperator, operatorSetId: allocateParams[0].operatorSet.id, @@ -545,37 +694,44 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests description: "test" }) ); + uint256 numLogsAfter = cheats.getRecordedLogs().length; - uint256 effectBlock = block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY; + // Assert only 1 log was emitted + assertEq(numLogsAfter, numLogsBefore + 1, "Incorrect number of logs emitted"); - _checkAllocationStorage({ - operator: defaultOperator, - operatorSet: defaultOperatorSet, - strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: int64(allocateParams[0].newMagnitudes[0]), - expectedEffectBlock: effectBlock - }); + // Assert encumberedMagnitude and maxMagnitude are unchanged + assertEq( + encumberedMagnitudeBefore, + allocationManager.encumberedMagnitude(defaultOperator, strategyMock), + "encumberedMagnitude mutated" + ); + + assertEq( + maxMagnitudeBefore, + allocationManager.getMaxMagnitudes(defaultOperator, strategyMock.toArray())[0], + "maxMagnitude mutated" + ); + // Roll to effect block and validate allocation + uint32 effectBlock = uint32(block.number) + DEFAULT_OPERATOR_ALLOCATION_DELAY; + uint64 pendingIncrease = allocateParams[0].newMagnitudes[0]; cheats.roll(effectBlock); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: allocateParams[0].newMagnitudes[0], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: pendingIncrease, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: pendingIncrease, max: WAD, allocatable: WAD - pendingIncrease}) }); } /** * Allocates all magnitude to for a single strategy to an operatorSet. Slashes 25% - * Asserts that: + * Validates: * 1. Events are emitted - * 2. Encumbered mag is updated - * 3. Max mag is updated - * 4. Calculations for `getAllocatableMagnitude` and `getAllocation` are correct + * 2. Allocation & info introspection + * 3. Slashable stake introspection */ function test_slashPostAllocation() public { // Generate allocation for this operator set, we allocate max @@ -585,7 +741,16 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.modifyAllocations(defaultOperator, allocateParams); cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - _checkSlashEvents(defaultOperator, defaultOperatorSet, defaultStrategies, uint256(25e16).toArrayU256(), "test"); + _checkSlashEvents({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + wadToSlash: uint256(25e16), + description: "test", + currentMag: uint64(75e16), + maxMag: uint64(75e16), + encumberedMag: uint64(75e16) + }); // Slash operator for 25% cheats.prank(defaultAVS); @@ -601,32 +766,19 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests ); // Check storage - assertEq( - 75e16, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - 75e16, allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], "maxMagnitude not updated" - ); - assertEq( - 0, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude shoudl be 0" - ); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: 75e16, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: 75e16, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: 75e16, max: 75e16, allocatable: 0}) }); + _checkSlashableStake({ operatorSet: defaultOperatorSet, operator: defaultOperator, strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES.mulWad(75e16) + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(75e16) }); } @@ -643,50 +795,44 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests SlashingParams memory slashingParams = _randSlashingParams(defaultOperator, defaultOperatorSet.id); - uint64 allocatedMagnitude = allocateParams[0].newMagnitudes[0]; - uint64 expectedSlashedMagnitude = - uint64(SlashingLib.mulWadRoundUp(allocatedMagnitude, slashingParams.wadsToSlash[0])); - uint64 expectedEncumberedMagnitude = allocatedMagnitude - expectedSlashedMagnitude; - uint64 maxMagnitudeAfterSlash = WAD - expectedSlashedMagnitude; - uint256 slashedStake = DEFAULT_OPERATOR_SHARES.mulWad(expectedSlashedMagnitude); - uint256 newSlashableMagnitude = uint256(expectedEncumberedMagnitude).divWad(maxMagnitudeAfterSlash); + (uint256 expectedWadSlashed, uint64 expectedCurrentMag, uint64 expectedMaxMag, uint64 expectedEncumberedMag) = _getExpectedSlashVals({ + magBeforeSlash: allocateParams[0].newMagnitudes[0], + wadToSlash: slashingParams.wadsToSlash[0] + }); _checkSlashEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: uint256(expectedSlashedMagnitude).toArrayU256(), - description: "test" + strategy: strategyMock, + wadToSlash: expectedWadSlashed, + description: "test", + currentMag: expectedCurrentMag, + maxMag: expectedMaxMag, + encumberedMag: expectedEncumberedMag }); // Slash Operator cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); - // Check storage - assertEq( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - maxMagnitudeAfterSlash, - allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], - "maxMagnitude not updated" - ); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: expectedEncumberedMagnitude, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: expectedCurrentMag, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMag, + max: expectedMaxMag, + allocatable: expectedMaxMag - expectedEncumberedMag + }) }); + + uint256 slashedStake = DEFAULT_OPERATOR_SHARES.mulWad(expectedWadSlashed); // Wad is same as slashed mag since we start with max mag _checkSlashableStake({ operatorSet: defaultOperatorSet, operator: defaultOperator, strategies: defaultStrategies, - expectedStake: (DEFAULT_OPERATOR_SHARES - slashedStake).mulWad(newSlashableMagnitude) + expectedSlashableStake: (DEFAULT_OPERATOR_SHARES - slashedStake).mulWad(expectedCurrentMag.divWad(expectedMaxMag)) }); } @@ -697,49 +843,26 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests * 2. Encumbered mag is updated * 3. Max mag is updated * 4. Calculations for `getAllocatableMagnitude` and `getAllocation` are correct - * 5. The second magnitude allocation is not slashed from + * 5. The second allocation is not slashed from */ function testFuzz_slash_oneCompletedAlloc_onePendingAlloc( Randomness r ) public rand(r) { - uint64 wadToSlash = r.Uint64(0.01 ether, WAD); + uint256 wadToSlash = r.Uint256(0.01 ether, WAD); // Generate allocation for `strategyMock`, we allocate half - AllocateParams[] memory allocateParams = _newAllocateParams(defaultOperatorSet, 5e17); - cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, allocateParams); - cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - - // Check slashable stake after the first allocation - _checkSlashableStake({ - operatorSet: defaultOperatorSet, - operator: defaultOperator, - strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES.mulWad(5e17) - }); + { + AllocateParams[] memory allocateParams = _newAllocateParams(defaultOperatorSet, 5e17); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + } // Allocate the other half AllocateParams[] memory allocateParams2 = _newAllocateParams(defaultOperatorSet, WAD); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams2); - uint32 secondAllocEffectBlock = uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - - // Check slashable stake hasn't changed after the second allocation - _checkSlashableStake({ - operatorSet: defaultOperatorSet, - operator: defaultOperator, - strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES.mulWad(5e17) - }); - - // Check minimum slashable stake would not change even after the second allocation becomes effective - _checkSlashableStake({ - operatorSet: defaultOperatorSet, - operator: defaultOperator, - strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES.mulWad(5e17), - futureBlock: secondAllocEffectBlock - }); + uint32 secondAllocEffectBlock = _defaultAllocEffectBlock(); // Slash operator for 50% SlashingParams memory slashingParams = SlashingParams({ @@ -750,50 +873,44 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests description: "test" }); - uint64 totalAllocated = 0.5 ether; - uint64 expectedEncumberedMagnitude = (WAD - uint64(uint256(totalAllocated) * uint256(wadToSlash) / WAD)); - uint64 magnitudeAfterSlash = totalAllocated - uint64(uint256(totalAllocated) * uint256(wadToSlash) / WAD); - uint64 maxMagnitudeAfterSlash = expectedEncumberedMagnitude; + (uint256 expectedWadSlashed, uint64 expectedCurrentMag, uint64 expectedMaxMag, uint64 expectedEncumberedMag) = _getExpectedSlashVals({ + magBeforeSlash: 5e17, + encumberedMagBeforeSlash: WAD, + wadToSlash: wadToSlash + }); - uint64 expectedSlashedMagnitude = uint64(totalAllocated.mulWadRoundUp(slashingParams.wadsToSlash[0])); - uint256 newSlashableMagnitude = uint256(magnitudeAfterSlash).divWad(maxMagnitudeAfterSlash); - uint256 slashedStake = DEFAULT_OPERATOR_SHARES.mulWad(expectedSlashedMagnitude); + uint256 slashedStake = DEFAULT_OPERATOR_SHARES.mulWad(expectedWadSlashed); // Wad is same as slashed mag since we start with max mag uint256 newTotalStake = DEFAULT_OPERATOR_SHARES - slashedStake; - // // STACK TOO DEEP - // // _checkSlashEvents({ - // // operator: defaultOperator, - // // operatorSet: defaultOperatorSet, - // // strategies: defaultStrategies, - // // wadsToSlash: uint256(wadToSlash).toArrayU256(), - // // description: "test" - // // }); + _checkSlashEvents({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + wadToSlash: expectedWadSlashed, + description: "test", + currentMag: expectedCurrentMag, + maxMag: expectedMaxMag, + encumberedMag: expectedEncumberedMag + }); // Slash Operator cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); - // Check storage - assertApproxEqAbs( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - 1, - "encumberedMagnitude not updated" - ); - assertApproxEqAbs( - maxMagnitudeAfterSlash, - allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], - 1, - "maxMagnitude not updated" - ); - _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: magnitudeAfterSlash, - expectedPendingDiff: 5e17, - expectedEffectBlock: secondAllocEffectBlock + expectedAllocation: Allocation({ + currentMagnitude: expectedCurrentMag, + pendingDiff: 5e17, + effectBlock: secondAllocEffectBlock + }), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMag, + max: expectedMaxMag, + allocatable: 0 + }) }); // Slashable stake should include first allocation and slashed magnitude @@ -801,32 +918,29 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests operatorSet: defaultOperatorSet, operator: defaultOperator, strategies: defaultStrategies, - expectedStake: newTotalStake.mulWad(newSlashableMagnitude) + expectedSlashableStake: newTotalStake.mulWad(expectedCurrentMag.divWad(expectedMaxMag)) }); cheats.roll(secondAllocEffectBlock); - assertEq( - 0, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude should be 0" - ); - + uint64 newSlashableMagnitude = expectedCurrentMag + 5e17; _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: magnitudeAfterSlash + 0.5 ether, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: newSlashableMagnitude, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMag, + max: expectedMaxMag, + allocatable: 0 + }) }); - newSlashableMagnitude = allocateParams2[0].newMagnitudes[0]; _checkSlashableStake({ operatorSet: defaultOperatorSet, operator: defaultOperator, strategies: defaultStrategies, - expectedStake: newTotalStake.mulWad(newSlashableMagnitude) + expectedSlashableStake: newTotalStake.mulWad(newSlashableMagnitude.divWad(expectedMaxMag)) }); } @@ -838,10 +952,8 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests * * Asserts that: * 1. Events are emitted - * 2. Encumbered mag is updated - * 3. Max mag is updated - * 4. Calculations for `getAllocatableMagnitude` and `getAllocation` are correct - * 5. Slashed amounts are rounded up to ensure magnitude is always slashed + * 2. Storage properly updated after each slash + * 3. Slashed amounts are rounded up to ensure magnitude is always slashed */ function test_repeatUntilFullSlash() public { // Generate allocation for `strategyMock`, we allocate 100% to opSet 0 @@ -851,14 +963,6 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.modifyAllocations(defaultOperator, allocateParams); cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - // Check slashable amount after initial allocation - _checkSlashableStake({ - operatorSet: defaultOperatorSet, - operator: defaultOperator, - strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES - }); - // 1. Slash operator for 99% in opSet 0 bringing their magnitude to 1e16 SlashingParams memory slashingParams = SlashingParams({ operator: defaultOperator, @@ -875,9 +979,12 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests _checkSlashEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: uint256(99e16).toArrayU256(), - description: "test" + strategy: strategyMock, + wadToSlash: uint256(99e16), + description: "test", + currentMag: magnitudeAfterSlash, + maxMag: maxMagnitudeAfterSlash, + encumberedMag: expectedEncumberedMagnitude }); // Slash Operator @@ -885,28 +992,19 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.slashOperator(defaultAVS, slashingParams); // Check storage - assertEq( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - maxMagnitudeAfterSlash, - allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], - "maxMagnitude not updated" - ); - Allocation memory allocation = - allocationManager.getAllocation(defaultOperator, defaultOperatorSet, strategyMock); - assertEq(magnitudeAfterSlash, allocation.currentMagnitude, "currentMagnitude not updated"); - - // Check slashable amount after first slash - _checkSlashableStake({ - operatorSet: defaultOperatorSet, + _checkAllocationStorage({ operator: defaultOperator, - strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES.mulWad(1e16) + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: magnitudeAfterSlash, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMagnitude, + max: maxMagnitudeAfterSlash, + allocatable: maxMagnitudeAfterSlash - expectedEncumberedMagnitude + }) }); + // 2. Slash operator again for 99.99% in opSet 0 bringing their magnitude to 1e14 slashingParams = SlashingParams({ operator: defaultOperator, @@ -915,6 +1013,7 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests wadsToSlash: 9999e14.toArrayU256(), description: "test" }); + expectedEncumberedMagnitude = 1e12; // After slashing 99.99%, only 0.01% expected encumberedMagnitude magnitudeAfterSlash = 1e12; maxMagnitudeAfterSlash = 1e12; @@ -922,34 +1021,28 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests _checkSlashEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: uint256(9999e14).toArrayU256(), - description: "test" + strategy: strategyMock, + wadToSlash: uint256(9999e14), + description: "test", + currentMag: magnitudeAfterSlash, + maxMag: maxMagnitudeAfterSlash, + encumberedMag: expectedEncumberedMagnitude }); cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); // Check storage - assertEq( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - maxMagnitudeAfterSlash, - allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], - "maxMagnitude not updated" - ); - allocation = allocationManager.getAllocation(defaultOperator, defaultOperatorSet, strategyMock); - assertEq(magnitudeAfterSlash, allocation.currentMagnitude, "currentMagnitude not updated"); - - // Check slashable amount after second slash - _checkSlashableStake({ - operatorSet: defaultOperatorSet, + _checkAllocationStorage({ operator: defaultOperator, - strategies: defaultStrategies, - expectedStake: DEFAULT_OPERATOR_SHARES.mulWad(1e12) + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: magnitudeAfterSlash, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMagnitude, + max: maxMagnitudeAfterSlash, + allocatable: maxMagnitudeAfterSlash - expectedEncumberedMagnitude + }) }); // 3. Slash operator again for 99.9999999999999% in opSet 0 @@ -957,7 +1050,7 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests operator: defaultOperator, operatorSetId: defaultOperatorSet.id, strategies: defaultStrategies, - wadsToSlash: (WAD - 1e3).toArrayU256(), + wadsToSlash: uint256(WAD - 1e3).toArrayU256(), description: "test" }); // Should technically be 1e3 remaining but with rounding error and rounding up slashed amounts @@ -969,9 +1062,12 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests _checkSlashEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: uint256(WAD - 1e3).toArrayU256(), - description: "test" + strategy: strategyMock, + wadToSlash: WAD, + description: "test", + currentMag: magnitudeAfterSlash, + maxMag: maxMagnitudeAfterSlash, + encumberedMag: expectedEncumberedMagnitude }); // Slash Operator @@ -979,25 +1075,24 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.slashOperator(defaultAVS, slashingParams); // Check storage - assertEq( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - maxMagnitudeAfterSlash, - allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], - "maxMagnitude not updated" - ); - allocation = allocationManager.getAllocation(defaultOperator, defaultOperatorSet, strategyMock); - assertEq(magnitudeAfterSlash, allocation.currentMagnitude, "currentMagnitude not updated"); + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: 0, + max: 0, + allocatable: 0 + }) + }); // Check slashable amount after final slash _checkSlashableStake({ operatorSet: defaultOperatorSet, operator: defaultOperator, strategies: defaultStrategies, - expectedStake: 0 + expectedSlashableStake: 0 }); } @@ -1014,14 +1109,13 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests function testFuzz_SlashWhileDeallocationPending( Randomness r ) public rand(r) { + // Initialize state AllocateParams[] memory allocateParams = r.AllocateParams(defaultAVS, 1, 1); AllocateParams[] memory deallocateParams = r.DeallocateParams(allocateParams); CreateSetParams[] memory createSetParams = r.CreateSetParams(allocateParams); RegisterParams memory registerParams = r.RegisterParams(allocateParams); SlashingParams memory slashingParams = r.SlashingParams(defaultOperator, allocateParams[0]); - console.log("wadsToSlash: %d", slashingParams.wadsToSlash[0]); - delegationManagerMock.setOperatorShares( defaultOperator, allocateParams[0].strategies[0], DEFAULT_OPERATOR_SHARES ); @@ -1030,43 +1124,35 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.createOperatorSets(defaultAVS, createSetParams); cheats.startPrank(defaultOperator); allocationManager.registerForOperatorSets(defaultOperator, registerParams); + + // Allocate allocationManager.modifyAllocations(defaultOperator, allocateParams); cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // Deallocate allocationManager.modifyAllocations(defaultOperator, deallocateParams); uint32 deallocationEffectBlock = uint32(block.number + DEALLOCATION_DELAY); cheats.stopPrank(); - // Check slashable stake after deallocation (still pending; no change) - _checkSlashableStake({ - operatorSet: allocateParams[0].operatorSet, - operator: defaultOperator, - strategies: allocateParams[0].strategies, - expectedStake: allocateParams[0].newMagnitudes[0] - }); - - // Check slashable stake after deallocation takes effect, before slashing - _checkSlashableStake({ - operatorSet: allocateParams[0].operatorSet, - operator: defaultOperator, - strategies: allocateParams[0].strategies, - expectedStake: deallocateParams[0].newMagnitudes[0], - futureBlock: deallocationEffectBlock - }); - uint256 magnitudeAllocated = allocateParams[0].newMagnitudes[0]; uint256 magnitudeDeallocated = magnitudeAllocated - deallocateParams[0].newMagnitudes[0]; - uint256 magnitudeSlashed = magnitudeAllocated.mulWad(slashingParams.wadsToSlash[0]); + uint256 magnitudeSlashed = (magnitudeAllocated * slashingParams.wadsToSlash[0] / WAD) + _calculateSlippage(uint64(magnitudeAllocated), slashingParams.wadsToSlash[0]); uint256 expectedCurrentMagnitude = magnitudeAllocated - magnitudeSlashed; int128 expectedPendingDiff = -int128(uint128(magnitudeDeallocated - magnitudeDeallocated.mulWadRoundUp(slashingParams.wadsToSlash[0]))); - _checkSlashEvents({ - operator: defaultOperator, - operatorSet: allocateParams[0].operatorSet, - strategies: allocateParams[0].strategies, - wadsToSlash: slashingParams.wadsToSlash, - description: "test" - }); + // Manually check slash events since we have a deallocation pending + // Deallocation update is emitted first + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit AllocationUpdated(defaultOperator, allocateParams[0].operatorSet, allocateParams[0].strategies[0], uint64(uint128(int128(uint128(expectedCurrentMagnitude)) + expectedPendingDiff)), deallocationEffectBlock); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit EncumberedMagnitudeUpdated(defaultOperator, allocateParams[0].strategies[0], uint64(magnitudeAllocated - magnitudeSlashed)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit AllocationUpdated(defaultOperator, allocateParams[0].operatorSet, allocateParams[0].strategies[0], uint64(expectedCurrentMagnitude), uint32(block.number)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit MaxMagnitudeUpdated(defaultOperator, allocateParams[0].strategies[0], uint64(WAD - magnitudeSlashed)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit OperatorSlashed(defaultOperator, allocateParams[0].operatorSet, allocateParams[0].strategies, magnitudeSlashed.toArrayU256(), ""); cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); @@ -1075,65 +1161,41 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests operator: defaultOperator, operatorSet: allocateParams[0].operatorSet, strategy: allocateParams[0].strategies[0], - expectedCurrentMagnitude: expectedCurrentMagnitude, - expectedPendingDiff: expectedPendingDiff, - expectedEffectBlock: deallocationEffectBlock - }); - - // Check slashable stake after slash - _checkSlashableStake({ - operatorSet: allocateParams[0].operatorSet, - operator: defaultOperator, - strategies: allocateParams[0].strategies, - expectedStake: expectedCurrentMagnitude + expectedAllocation: Allocation({ + currentMagnitude: uint64(expectedCurrentMagnitude), + pendingDiff: expectedPendingDiff, + effectBlock: deallocationEffectBlock + }), + expectedMagnitudes: Magnitudes({ + encumbered: expectedCurrentMagnitude, + max: uint64(WAD - magnitudeSlashed), + allocatable: 0 + }) }); - // Check slashable stake after deallocation takes effect - _checkSlashableStake({ - operatorSet: allocateParams[0].operatorSet, - operator: defaultOperator, - strategies: allocateParams[0].strategies, - expectedStake: expectedCurrentMagnitude - uint128(-expectedPendingDiff) - 1, - futureBlock: deallocationEffectBlock - }); - - assertEq( - expectedCurrentMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, allocateParams[0].strategies[0]), - "encumberedMagnitude not updated" - ); - assertEq( - WAD - slashingParams.wadsToSlash[0], - allocationManager.getMaxMagnitudes(defaultOperator, allocateParams[0].strategies)[0], - "maxMagnitude not updated" - ); - cheats.roll(deallocationEffectBlock); allocationManager.clearDeallocationQueue(defaultOperator, allocateParams[0].strategies, _maxNumToClear()); + uint64 newMag = uint64(uint128(int128(uint128(expectedCurrentMagnitude)) + expectedPendingDiff)); + _checkAllocationStorage({ operator: defaultOperator, operatorSet: allocateParams[0].operatorSet, strategy: allocateParams[0].strategies[0], - expectedCurrentMagnitude: deallocateParams[0].newMagnitudes[0] - - deallocateParams[0].newMagnitudes[0] * slashingParams.wadsToSlash[0] / WAD, - expectedPendingDiff: 0, - expectedEffectBlock: 0 - }); - - // Check slashable stake after slash and deallocation - _checkSlashableStake({ - operatorSet: allocateParams[0].operatorSet, - operator: defaultOperator, - strategies: allocateParams[0].strategies, - expectedStake: expectedCurrentMagnitude - uint128(-expectedPendingDiff) - 1 + expectedAllocation: Allocation({currentMagnitude: newMag, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: newMag, + max: uint64(WAD - magnitudeSlashed), + allocatable: uint128(-expectedPendingDiff) // This works because we allocated all in the randomization allocation helper + }) }); } /** * Allocates all magnitude to a single opSet. Then slashes the entire magnitude - * Asserts that: - * 1. The operator cannot allocate again + * Validates: + * 1. Storage post slash + * 2. The operator cannot allocate again */ function testRevert_allocateAfterSlashedEntirely() public { // Allocate all magnitude @@ -1145,14 +1207,17 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests _checkSlashEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: WAD.toArrayU256(), - description: "test" + strategy: strategyMock, + wadToSlash: WAD, + description: "test", + currentMag: 0, + maxMag: 0, + encumberedMag: 0 }); // Slash operator for 100% cheats.prank(defaultAVS); - allocationManager.slashOperator( + allocationManager.slashOperator( defaultAVS, SlashingParams({ operator: defaultOperator, @@ -1163,6 +1228,15 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests }) ); + // Validate storage post slash + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: 0, max: 0, allocatable: 0}) + }); + OperatorSet memory operatorSet = _createOperatorSet(OperatorSet(defaultAVS, random().Uint32()), defaultStrategies); AllocateParams[] memory allocateParams2 = _newAllocateParams(operatorSet, 1); @@ -1174,12 +1248,12 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests } /** - * Allocates all magnitude to a single opSet. Deallocateas magnitude. Slashes al + * Allocates all magnitude to a single opSet. Deallocates magnitude. Slashes all * Asserts that: * 1. The Allocation is 0 after slash - * 2. Them sotrage post slash for encumbered and maxMags ais zero + * 2. Them storage post slash for encumbered and maxMags is zero */ - function test_allocateAll_deallocateAll() public { + function test_slash_allocateAll_deallocateAll() public { // Allocate all magnitude cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, _newAllocateParams(defaultOperatorSet, WAD)); @@ -1189,17 +1263,13 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, _newAllocateParams(defaultOperatorSet, 0)); - _checkSlashEvents({ - operator: defaultOperator, - operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: WAD.toArrayU256(), - description: "test" - }); + // Validate event for the deallocation + cheats.expectEmit(true, true, true, true, address(allocationManager)); + emit AllocationUpdated(defaultOperator, defaultOperatorSet, strategyMock, 0, uint32(block.number + DEALLOCATION_DELAY)); // Slash operator for 100% cheats.prank(defaultAVS); - allocationManager.slashOperator( + allocationManager.slashOperator( defaultAVS, SlashingParams({ operator: defaultOperator, @@ -1210,24 +1280,30 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests }) ); - assertEq( - 0, allocationManager.encumberedMagnitude(defaultOperator, strategyMock), "encumberedMagnitude not updated" - ); - assertEq( - 0, allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], "maxMagnitude not updated" - ); + // forgefmt: disable-next-item _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: 0, - expectedEffectBlock: block.number + DEALLOCATION_DELAY + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: 0, effectBlock: uint32(block.number) + DEALLOCATION_DELAY}), + expectedMagnitudes: Magnitudes({encumbered: 0, max: 0, allocatable: 0}) }); + + // Complete deallocation + cheats.roll(uint32(block.number) + DEALLOCATION_DELAY); + allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); + + // Validate allocatable amount is 0 + assertEq( + 0, + allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), + "Allocatable magnitude should be 0" + ); } /** - * Slashes the operator after deallocation, even if the deallocation has not been cleared. Validates that: + * Slashes the operator after deallocation, even if the deallocation has not been cleared. + * Validates that: * 1. Even if we do not clear deallocation queue, the deallocation is NOT slashed from since we're passed the deallocationEffectBlock * 2. Validates storage post slash & post clearing deallocation queue * 3. Max magnitude only decreased proportionally by the magnitude set after deallocation @@ -1245,16 +1321,6 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests allocationManager.modifyAllocations(defaultOperator, deallocateParams); uint32 deallocationEffectBlock = uint32(block.number + DEALLOCATION_DELAY); - // Check storage post deallocation - _checkAllocationStorage({ - operator: defaultOperator, - operatorSet: defaultOperatorSet, - strategy: strategyMock, - expectedCurrentMagnitude: WAD, - expectedPendingDiff: -5e17, - expectedEffectBlock: deallocationEffectBlock - }); - // Warp to deallocation effect block cheats.roll(deallocationEffectBlock); @@ -1270,63 +1336,51 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests uint64 expectedEncumberedMagnitude = 375e15; // 25e16 is slashed. 5e17 was previously uint64 magnitudeAfterSlash = 375e15; uint64 maxMagnitudeAfterSlash = 875e15; // Operator can only allocate up to 75e16 magnitude since 25% is slashed + uint256 expectedSlashedMagnitude = SlashingLib.mulWadRoundUp(5e17, 25e16); + // Slash Operator, only emit events assuming that there is no deallocation _checkSlashEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, - strategies: defaultStrategies, - wadsToSlash: uint256(25e16).toArrayU256(), - description: "test" + strategy: strategyMock, + wadToSlash: expectedSlashedMagnitude, + description: "test", + currentMag: magnitudeAfterSlash, + maxMag: maxMagnitudeAfterSlash, + encumberedMag: expectedEncumberedMagnitude }); - - // Slash Operator, only emit events assuming that there is no deallocation + cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); - // Check storage post slash - assertEq( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - maxMagnitudeAfterSlash, - allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0], - "maxMagnitude not updated" - ); + allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); + + uint64 allocatableMagnitudeAfterSlash = allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock); + _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: magnitudeAfterSlash, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: magnitudeAfterSlash, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMagnitude, + max: maxMagnitudeAfterSlash, + allocatable: allocatableMagnitudeAfterSlash + }) }); - - uint64 allocatableMagnitudeAfterSlash = allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock); - - // Check storage after complete modification. - allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); - assertEq( - allocatableMagnitudeAfterSlash, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatable mag after slash shoudl be equal to allocatable mag after clearing queue" - ); } /** - * Allocates to multiple operatorSets for a strategy. Only slashes from one operatorSet. Validates - * 1. The slashable shares of each operatorSet after magnitude allocation - * 2. The first operatorSet has less slashable shares post slash - * 3. The second operatorSet has the same number slashable shares post slash - * 4. The PROPORTION that is slashable for opSet 2 has increased - * 5. Encumbered magnitude, total allocatable magnitude + * Allocates to multiple operatorSets for a strategy. Only slashes from one operatorSet. + * Validates: + * 1. The first operatorSet has less slashable shares post slash + * 2. The second operatorSet has the same number slashable shares post slash (within slippage) + * 3. The PROPORTION that is slashable for opSet 2 has increased */ - function test_allocateMultipleOpsets_slashSingleOpset() public { - // Set 100e18 shares for operator in DM - uint256 operatorShares = 100e18; - delegationManagerMock.setOperatorShares(defaultOperator, strategyMock, operatorShares); - uint64 magnitudeToAllocate = 4e17; + function testFuzz_allocateMultipleOpsets_slashSingleOpset(Randomness r) rand(r) public { + // Get magnitude to allocate + uint64 magnitudeToAllocate = r.Uint64(1, 5e17); + uint256 wadToSlash = r.Uint256(1, 1e18); OperatorSet memory operatorSet = OperatorSet(defaultAVS, 1); OperatorSet memory operatorSet2 = OperatorSet(defaultAVS, 2); @@ -1340,155 +1394,192 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests _createOperatorSet(OperatorSet(defaultAVS, 2), defaultStrategies), magnitudeToAllocate )[0]; + // Register operator for both operatorSets _registerForOperatorSet(defaultOperator, operatorSet); _registerForOperatorSet(defaultOperator, operatorSet2); + // Modify allocations cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); // Get slashable shares for each operatorSet - address[] memory operatorArray = new address[](1); - operatorArray[0] = defaultOperator; - - uint256 maxMagnitude = allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0]; - uint256 opSet2PortionOfMaxMagnitude = uint256(magnitudeToAllocate) * WAD / maxMagnitude; - + uint256 opset2SlashableSharesBefore = allocationManager.getMinimumSlashableStake(operatorSet2, defaultOperator.toArray(), defaultStrategies, uint32(block.number))[0][0]; // Slash operator on operatorSet1 for 50% SlashingParams memory slashingParams = SlashingParams({ operator: defaultOperator, operatorSetId: allocateParams[0].operatorSet.id, strategies: defaultStrategies, - wadsToSlash: 5e17.toArrayU256(), + wadsToSlash: wadToSlash.toArrayU256(), description: "test" }); - _checkSlashEvents({ - operator: defaultOperator, - operatorSet: operatorSet, - strategies: defaultStrategies, - wadsToSlash: slashingParams.wadsToSlash, - description: "test" + (, uint64 expectedCurrentMag, uint64 expectedMaxMag, uint64 expectedEncumberedMag) = _getExpectedSlashVals({ + magBeforeSlash: allocateParams[0].newMagnitudes[0], + wadToSlash: slashingParams.wadsToSlash[0], + encumberedMagBeforeSlash: allocateParams[0].newMagnitudes[0] * 2 }); // Slash Operator cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); - // Operator should now have 80e18 shares, since half of 40e18 was slashed - delegationManagerMock.setOperatorShares(defaultOperator, strategyMock, 80e18); + // Validate storage operatorSet1 + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: operatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: expectedCurrentMag, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMag, + max: expectedMaxMag, + allocatable: expectedMaxMag - expectedEncumberedMag + }) + }); - // Validate encumbered and total allocatable magnitude - uint256 maxMagnitudeAfterSlash = allocationManager.getMaxMagnitudes(defaultOperator, defaultStrategies)[0]; - uint256 expectedEncumberedMagnitude = 6e17; // 4e17 from opSet2, 2e17 from opSet1 - assertEq( - expectedEncumberedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - maxMagnitudeAfterSlash - expectedEncumberedMagnitude, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude should be diff of maxMagnitude and encumberedMagnitude" - ); + // Validate storage for operatorSet2 + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: operatorSet2, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: magnitudeToAllocate, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMag, + max: expectedMaxMag, + allocatable: expectedMaxMag - expectedEncumberedMag + }) + }); // Check proportion after slash - uint256 opSet2PortionOfMaxMagnitudeAfterSlash = uint256(magnitudeToAllocate) * WAD / maxMagnitudeAfterSlash; + uint256 opSet2PortionOfMaxMagnitudeAfterSlash = uint256(magnitudeToAllocate) * WAD / expectedMaxMag; assertGt( opSet2PortionOfMaxMagnitudeAfterSlash, - opSet2PortionOfMaxMagnitude, + magnitudeToAllocate, // This is the same as proportion before slash "opSet2 should have a greater proportion to slash from previous" ); + + // Assert that slashable stake is the same - we add slippage here due to rounding error from the slash itself + assertEq( + opset2SlashableSharesBefore, + allocationManager.getMinimumSlashableStake(operatorSet2, defaultOperator.toArray(), defaultStrategies, uint32(block.number))[0][0] + + 1, + "opSet2 slashable shares should be the same" + ); } /** - * Allocates to multiple strategies for the given operatorSetKey. Slashes from both strategies Validates a slash propogates to both strategies. + * Allocates to multiple strategies for the given operatorSetKey. Slashes from both strategies Validates a slash propagates to both strategies. * Validates that * 1. Proper events are emitted for each strategy slashed * 2. Each strategy is slashed proportional to its allocation * 3. Storage is updated for each strategy, opSet */ - function test_allocateMultipleStrategies_slashMultiple() public { - // Allocate to each strategy - uint64 strategy1Magnitude = 5e17; - uint64 strategy2Magnitude = WAD; + function testFuzz_allocateMultipleStrategies_slashMultiple(Randomness r) rand(r) public { + // Initialize random params + uint64 strategy1Magnitude = r.Uint64(1, 1e18); + uint64 strategy2Magnitude = r.Uint64(1, 1e18); + uint256 wadToSlash = r.Uint256(1, 1e18); + // Crate and allocate to operatorSets OperatorSet memory operatorSet = OperatorSet(defaultAVS, random().Uint32()); _createOperatorSet(operatorSet, random().StrategyArray(2)); _registerForOperatorSet(defaultOperator, operatorSet); IStrategy[] memory strategies = allocationManager.getStrategiesInOperatorSet(operatorSet); - AllocateParams memory allocateParams = - AllocateParams({operatorSet: operatorSet, strategies: strategies, newMagnitudes: new uint64[](2)}); - allocateParams.newMagnitudes[0] = strategy1Magnitude; - allocateParams.newMagnitudes[1] = strategy2Magnitude; - - cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, allocateParams.toArray()); - cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + uint256[] memory wadsToSlash = new uint256[](strategies.length); + { + if (strategies[1] < strategies[0]) { + IStrategy temp = strategies[0]; + strategies[0] = strategies[1]; + strategies[1] = temp; + } + AllocateParams memory allocateParams = + AllocateParams({operatorSet: operatorSet, strategies: strategies, newMagnitudes: new uint64[](2)}); + allocateParams.newMagnitudes[0] = strategy1Magnitude; + allocateParams.newMagnitudes[1] = strategy2Magnitude; - uint256[] memory wadsToSlash = new uint256[](2); - wadsToSlash[0] = 6e17; - wadsToSlash[1] = 6e17; + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams.toArray()); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - // Slash operator on both strategies for 60% - SlashingParams memory slashingParams = SlashingParams({ - operator: defaultOperator, - operatorSetId: operatorSet.id, - strategies: strategies, - wadsToSlash: wadsToSlash, - description: "test" - }); + for (uint256 i = 0; i < strategies.length; i++) { + wadsToSlash[i] = wadToSlash; + } + } + // Store post-slash vars to check against uint64[] memory expectedEncumberedMags = new uint64[](2); - expectedEncumberedMags[0] = 2e17; // 60% of 5e17 - expectedEncumberedMags[1] = 4e17; // 60% of WAD - + uint256[] memory expectedSlashedMagnitude = new uint256[](2); uint64[] memory expectedMagnitudeAfterSlash = new uint64[](2); - expectedMagnitudeAfterSlash[0] = 2e17; - expectedMagnitudeAfterSlash[1] = 4e17; - uint64[] memory expectedMaxMagnitudeAfterSlash = new uint64[](2); - expectedMaxMagnitudeAfterSlash[0] = 7e17; - expectedMaxMagnitudeAfterSlash[1] = 4e17; + + { + (uint256 strat1ExpectedWadSlashed, uint64 strat1ExpectedCurrentMag, uint64 strat1ExpectedMaxMag, uint64 strat1ExpectedEncumberedMag) = _getExpectedSlashVals({ + magBeforeSlash: strategy1Magnitude, + wadToSlash: wadToSlash + }); + expectedEncumberedMags[0] = strat1ExpectedEncumberedMag; + expectedSlashedMagnitude[0] = strat1ExpectedWadSlashed; + expectedMagnitudeAfterSlash[0] = strat1ExpectedCurrentMag; + expectedMaxMagnitudeAfterSlash[0] = strat1ExpectedMaxMag; + } + { + (uint256 strat2ExpectedWadSlashed, uint64 strat2ExpectedCurrentMag, uint64 strat2ExpectedMaxMag, uint64 strat2ExpectedEncumberedMag) = _getExpectedSlashVals({ + magBeforeSlash: strategy2Magnitude, + wadToSlash: wadToSlash + }); + expectedEncumberedMags[1] = strat2ExpectedEncumberedMag; + expectedSlashedMagnitude[1] = strat2ExpectedWadSlashed; + expectedMagnitudeAfterSlash[1] = strat2ExpectedCurrentMag; + expectedMaxMagnitudeAfterSlash[1] = strat2ExpectedMaxMag; + } _checkSlashEvents({ operator: defaultOperator, operatorSet: operatorSet, strategies: strategies, - wadsToSlash: wadsToSlash, - description: "test" + wadToSlash: expectedSlashedMagnitude, + description: "test", + currentMags: expectedMagnitudeAfterSlash, + maxMags: expectedMaxMagnitudeAfterSlash, + encumberedMags: expectedEncumberedMags }); // Slash Operator - cheats.prank(defaultAVS); - allocationManager.slashOperator(defaultAVS, slashingParams); + { + SlashingParams memory slashingParams = SlashingParams({ + operator: defaultOperator, + operatorSetId: operatorSet.id, + strategies: strategies, + wadsToSlash: wadsToSlash, + description: "test" + }); + cheats.prank(defaultAVS); + allocationManager.slashOperator(defaultAVS, slashingParams); + } // Check storage for (uint256 i; i < strategies.length; ++i) { - assertEq( - expectedEncumberedMags[i], - allocationManager.encumberedMagnitude(defaultOperator, strategies[i]), - "encumberedMagnitude not updated" - ); - assertEq( - expectedMaxMagnitudeAfterSlash[i] - expectedMagnitudeAfterSlash[i], - allocationManager.getAllocatableMagnitude(defaultOperator, strategies[i]), - "allocatableMagnitude not updated" - ); _checkAllocationStorage({ operator: defaultOperator, operatorSet: operatorSet, strategy: strategies[i], - expectedCurrentMagnitude: expectedMagnitudeAfterSlash[i], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({ + currentMagnitude: expectedMagnitudeAfterSlash[i], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMags[i], + max: expectedMaxMagnitudeAfterSlash[i], + allocatable: expectedMaxMagnitudeAfterSlash[i] - expectedEncumberedMags[i] + }) }); } } /// @dev Allocates magnitude. Deallocates some. Slashes a portion, and then allocates up to the max available magnitude - function testFuzz_allocate_deallocate_slashWhilePending_allocateMax( + function testFuzz_allocate_deallocate_allocateMax( Randomness r ) public rand(r) { AllocateParams[] memory allocateParams = r.AllocateParams({avs: defaultAVS, numAllocations: 1, numStrats: 1}); @@ -1515,71 +1606,70 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests operator: defaultOperator, operatorSetId: operatorSet.id, strategies: strategy.toArray(), - wadsToSlash: r.Uint64(0.01 ether, 0.99 ether).toArrayU256(), + wadsToSlash: (r.Uint256(0.01 ether, 0.99 ether)).toArrayU256(), description: "test" }); - uint256 magnitudeBeforeSlash = deallocateParams[0].newMagnitudes[0]; - uint256 slashedMagnitude = magnitudeBeforeSlash * slashingParams.wadsToSlash[0] / WAD; - uint256 currentMagnitude = magnitudeBeforeSlash - slashedMagnitude - 1; - uint256 maxMagnitude = WAD - slashedMagnitude - 1; + (uint256 expectedWadSlashed, uint64 expectedCurrentMag, uint64 expectedMaxMag, uint64 expectedEncumberedMag) = _getExpectedSlashVals({ + magBeforeSlash: deallocateParams[0].newMagnitudes[0], + wadToSlash: slashingParams.wadsToSlash[0] + }); _checkSlashEvents({ operator: defaultOperator, operatorSet: operatorSet, - strategies: strategy.toArray(), - wadsToSlash: slashingParams.wadsToSlash, - description: "test" + strategy: allocateParams[0].strategies[0], + wadToSlash: expectedWadSlashed, + description: "test", + currentMag: expectedCurrentMag, + maxMag: expectedMaxMag, + encumberedMag: expectedEncumberedMag }); cheats.prank(defaultAVS); allocationManager.slashOperator(defaultAVS, slashingParams); - assertEq( - currentMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategy), - "encumberedMagnitude should be half of firstMod" - ); + // Clear deallocation queue. + allocationManager.clearDeallocationQueue(defaultOperator, strategy.toArray(), _maxNumToClear()); _checkAllocationStorage({ operator: defaultOperator, operatorSet: operatorSet, strategy: strategy, - expectedCurrentMagnitude: uint64(currentMagnitude), - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: expectedCurrentMag, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedEncumberedMag, + max: expectedMaxMag, + allocatable: expectedMaxMag - expectedEncumberedMag + }) }); - // Clear deallocation queue. - allocationManager.clearDeallocationQueue(defaultOperator, strategy.toArray(), _maxNumToClear()); - - assertEq( - maxMagnitude, - allocationManager.getMaxMagnitudes(defaultOperator, strategy.toArray())[0], - "maxMagnitude should be expectedMaxMagnitude" - ); - - assertEq( - maxMagnitude - currentMagnitude, - allocationManager.getAllocatableMagnitude(defaultOperator, strategy), - "allocatableMagnitude should be expectedAllocatable" - ); - // Allocate up to max magnitude - AllocateParams[] memory allocateParams2 = _newAllocateParams(operatorSet, uint64(maxMagnitude)); + AllocateParams[] memory allocateParams2 = _newAllocateParams(operatorSet, expectedMaxMag); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams2); - // Assert that encumbered is expectedMaxMagnitude - assertEq( - 0, allocationManager.getAllocatableMagnitude(defaultOperator, strategy), "allocatableMagnitude should be 0" - ); + int128 pendingDiff = int128(uint128(expectedMaxMag - expectedCurrentMag)); + + // Check storage + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: operatorSet, + strategy: strategy, + expectedAllocation: Allocation({currentMagnitude: expectedCurrentMag, pendingDiff: pendingDiff, effectBlock: _defaultAllocEffectBlock()}), + expectedMagnitudes: Magnitudes({ + encumbered: expectedMaxMag, + max: expectedMaxMag, + allocatable: 0 + }) + }); } } contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTests { using ArrayLib for *; using OperatorSetLib for *; + using SlashingLib for *; function test_revert_paused() public { allocationManager.pause(2 ** PAUSED_MODIFY_ALLOCATIONS); @@ -1703,59 +1793,6 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe allocationManager.modifyAllocations(defaultOperator, allocateParams); } - function testFuzz_revert_overAllocate( - Randomness r - ) public rand(r) { - uint8 numOpSets = uint8(r.Uint256(2, FUZZ_MAX_OP_SETS)); - - // Create and register for operator sets - OperatorSet[] memory operatorSets = r.OperatorSetArray(defaultAVS, numOpSets); - _createOperatorSets(operatorSets, defaultStrategies); - - AllocateParams[] memory allocateParams = _randAllocateParams_SingleMockStrategy(operatorSets); - uint256 randIdx = r.Uint256(0, allocateParams.length - 1); - - allocateParams[randIdx].newMagnitudes[0] = WAD + 1; - - // Overallocate - cheats.expectRevert(InsufficientMagnitude.selector); - cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, allocateParams); - } - - // TODO: yash - // function test_allocateMaxToMultipleStrategies( - // Randomness r - // ) public rand(r) { - // // Create a handful of operator sets under the same AVS, each with a unique strategy - // OperatorSet[] memory operatorSets = _newOperatorSets_SingleUniqueStrategy(defaultAVS, r.Uint256(2, 10)); - - // // Register for each operator set - // _registerForOperatorSets(defaultOperator, operatorSets); - - // // Allocate max to each operator set - // AllocateParams[] memory allocateParams = new AllocateParams[](operatorSets.length); - // for (uint256 i = 0; i < operatorSets.length; i++) { - // allocateParams[i] = AllocateParams({ - // operatorSet: operatorSets[i], - // strategies: allocationManager.getStrategiesInOperatorSet(operatorSets[i]), - // newMagnitudes: WAD.toArrayU64() - // }); - // } - - // cheats.prank(defaultOperator); - // allocationManager.modifyAllocations(defaultOperator, allocateParams); - - // // Ensure encumbered magnitude is updated for each strategy - // for (uint256 i = 0; i < allocateParams.length; i++) { - // assertEq( - // WAD, - // allocationManager.encumberedMagnitude(defaultOperator, allocateParams[i].strategies[0]), - // "encumberedMagnitude not max" - // ); - // } - // } - function test_revert_allocateDeallocate_modificationPending() public { // Allocate AllocateParams[] memory allocateParams = _randAllocateParams_DefaultOpSet(); @@ -1789,11 +1826,14 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe allocationManager.modifyAllocations(defaultOperator, allocateParams); } - /// @dev Set allocation delay > ALLOCATION_CONFIGURATION_DELAY, allocate, - /// set allocation delay to < ALLOCATION_CONFIGURATION_DELAY, allocate again - /// once new delay is sect. - /// - /// NOTE: Should be able to allocate faster than `ALLOCATION_CONFIGURATION_DELAY`. + /** + * @notice Tests edge cases around allocation delay: + * 1. Set allocation delay to a value greater than ALLOCATION_CONFIGURATION_DELAY + * 2. Allocate magnitude before the configured delay is hit + * 3. Set allocation delay to a value less than ALLOCATION_CONFIGURATION_DELAY + * 4. Allocate magnitude after allocation in step 2 takes effect, but before the new delay is hit + * Validates that you should be able to allocate in step 4 since there is no other pending modifications + */ function testFuzz_ShouldBeAbleToAllocateSoonerThanLastDelay( Randomness r ) public rand(r) { @@ -1809,14 +1849,40 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe allocationManager.setAllocationDelay(defaultOperator, firstDelay); allocationManager.modifyAllocations(defaultOperator, _newAllocateParams(defaultOperatorSet, half)); + + // Validate storage - the `firstDelay` should not be applied yet + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: int64(half), effectBlock: _defaultAllocEffectBlock()}), + expectedMagnitudes: Magnitudes({encumbered: half, max: WAD, allocatable: WAD - half}) + }); allocationManager.setAllocationDelay(defaultOperator, secondDelay); - cheats.roll(block.number + secondDelay); - allocationManager.modifyAllocations(defaultOperator, _newAllocateParams(OperatorSet(defaultAVS, 1), half)); + + cheats.roll(block.number + ALLOCATION_CONFIGURATION_DELAY); + allocationManager.modifyAllocations(defaultOperator, _newAllocateParams(defaultOperatorSet, half+1)); cheats.stopPrank(); + + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: half, pendingDiff: int64(1), effectBlock: uint32(block.number + secondDelay)}), + expectedMagnitudes: Magnitudes({encumbered: half+1, max: WAD, allocatable: WAD - (half + 1)}) + }); } + /** + * @notice Allocates a random magnitude to the default operatorSet. + * Validates: + * 1. Storage is clear prior to allocation + * 2. Events are emitted + * 3. Allocation storage/introspection after allocation + * 4. Allocation storage/introspection after roll to allocation effect block + */ function testFuzz_allocate_singleStrat_singleOperatorSet( Randomness r ) public rand(r) { @@ -1825,7 +1891,7 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe // Save vars to check against uint64 magnitude = allocateParams[0].newMagnitudes[0]; - uint32 effectBlock = uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + uint32 effectBlock = _defaultAllocEffectBlock(); // Check that the operator has no allocated sets/strats before allocation OperatorSet[] memory allocatedSets = allocationManager.getAllocatedSets(defaultOperator); @@ -1838,7 +1904,7 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - currentMagnitude: magnitude, + magnitude: magnitude, encumberedMagnitude: magnitude, effectBlock: effectBlock }); @@ -1847,8 +1913,9 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); - // Check storage + // Check storage Prior to Completion + // 1. Validate allocated sets and strategies allocatedSets = allocationManager.getAllocatedSets(defaultOperator); allocatedStrats = allocationManager.getAllocatedStrategies(defaultOperator, defaultOperatorSet); assertEq(allocatedSets.length, 1, "should have a single allocated set"); @@ -1856,37 +1923,38 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe assertEq(allocatedStrats.length, 1, "should have a single allocated strategy to default set"); assertEq(address(allocatedStrats[0]), address(strategyMock), "should have allocated default strat"); - assertEq( - magnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - WAD - magnitude, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude not calcualted correctly" - ); + // 2. Validate allocation + info _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: int128(uint128(magnitude)), - expectedEffectBlock: effectBlock + expectedAllocation: Allocation({ + currentMagnitude: 0, + pendingDiff: int128(uint128(magnitude)), + effectBlock: effectBlock + }), + expectedMagnitudes: Magnitudes({encumbered: magnitude, max: WAD, allocatable: WAD - magnitude}) }); - // Check storage after roll to completion + + // 3. Check allocation and info after roll to completion cheats.roll(effectBlock); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: magnitude, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: magnitude, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: magnitude, max: WAD, allocatable: WAD - magnitude}) }); } + /** + * @notice Allocates magnitude for a single strategy to multiple operatorSets + * Validates: + * 1. Events + * 2. Allocation storage/introspection after allocation + * 3. Allocation storage/introspection after roll to allocation effect block + */ function testFuzz_allocate_singleStrat_multipleSets( Randomness r ) public rand(r) { @@ -1900,98 +1968,101 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe _registerForOperatorSets(defaultOperator, operatorSets); // Save vars to check against - uint32 effectBlock = uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + uint32 effectBlock = _defaultAllocEffectBlock(); uint64 usedMagnitude; for (uint256 i; i < allocateParams.length; ++i) { usedMagnitude += allocateParams[i].newMagnitudes[0]; } - // Check that the operator has no allocated sets/strats before allocation - OperatorSet[] memory allocatedSets = allocationManager.getAllocatedSets(defaultOperator); - IStrategy[] memory allocatedStrats = - allocationManager.getAllocatedStrategies(defaultOperator, defaultOperatorSet); - assertEq(allocatedSets.length, 0, "should not have any allocated sets before allocation"); - assertEq(allocatedStrats.length, 0, "should not have any allocated strats before allocation"); - + // Validate events for (uint256 i; i < allocateParams.length; ++i) { + // There is only one strategy in each allocateParams, so we don't need a nested for loop _checkAllocationEvents({ operator: defaultOperator, operatorSet: operatorSets[i], strategy: strategyMock, - currentMagnitude: allocateParams[i].newMagnitudes[0], - encumberedMagnitude: allocateParams[i].newMagnitudes[0], + magnitude: allocateParams[i].newMagnitudes[0], + encumberedMagnitude: _encumberedMagnitudes[strategyMock] + allocateParams[i].newMagnitudes[0], effectBlock: effectBlock }); + _encumberedMagnitudes[strategyMock] += allocateParams[i].newMagnitudes[0]; } + // Allocate magnitude cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); // Check storage - assertEq( - usedMagnitude, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - assertEq( - WAD - usedMagnitude, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude not calcualted correctly" - ); - allocatedSets = allocationManager.getAllocatedSets(defaultOperator); + // 1. Sanity check number of allocated sets + OperatorSet[] memory allocatedSets = allocationManager.getAllocatedSets(defaultOperator); assertEq(allocatedSets.length, numOpSets, "should have multiple allocated sets"); + // 2. Check storage after allocation for (uint256 i; i < allocateParams.length; ++i) { _checkAllocationStorage({ operator: defaultOperator, operatorSet: operatorSets[i], strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: int128(uint128(allocateParams[i].newMagnitudes[0])), - expectedEffectBlock: effectBlock + expectedAllocation: Allocation({ + currentMagnitude: 0, + pendingDiff: int128(uint128(allocateParams[i].newMagnitudes[0])), + effectBlock: effectBlock + }), + expectedMagnitudes: Magnitudes({ + encumbered: _encumberedMagnitudes[strategyMock], + max: WAD, + allocatable: WAD - _encumberedMagnitudes[strategyMock] + }) }); - allocatedStrats = allocationManager.getAllocatedStrategies(defaultOperator, operatorSets[i]); + IStrategy[] memory allocatedStrats = allocationManager.getAllocatedStrategies(defaultOperator, operatorSets[i]); assertEq(allocatedStrats.length, 1, "should have a single allocated strategy to each set"); assertEq(address(allocatedStrats[0]), address(strategyMock), "should have allocated default strat"); assertEq(allocatedSets[i].key(), operatorSets[i].key(), "should be allocated to expected set"); } - // Check storage after roll to completion + // 3. Check storage after roll to completion cheats.roll(effectBlock); for (uint256 i; i < allocateParams.length; ++i) { _checkAllocationStorage({ operator: defaultOperator, operatorSet: operatorSets[i], strategy: strategyMock, - expectedCurrentMagnitude: allocateParams[i].newMagnitudes[0], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({ + currentMagnitude: allocateParams[i].newMagnitudes[0], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: _encumberedMagnitudes[strategyMock], + max: WAD, + allocatable: WAD - _encumberedMagnitudes[strategyMock] + }) }); } } + /** + * @notice Allocates once, warps to allocation effect block, then allocates again + * Validates: + * 1. Events for each allocation + * 2. Allocation storage/introspection immediately after each allocation + */ function testFuzz_allocateMultipleTimes( Randomness r ) public rand(r) { uint64 firstAlloc = r.Uint64(1, WAD - 1); uint64 secondAlloc = r.Uint64(firstAlloc + 1, WAD); - // Check that the operator has no allocated sets/strats before allocation - OperatorSet[] memory allocatedSets = allocationManager.getAllocatedSets(defaultOperator); - IStrategy[] memory allocatedStrats = - allocationManager.getAllocatedStrategies(defaultOperator, defaultOperatorSet); - assertEq(allocatedSets.length, 0, "should not have any allocated sets before allocation"); - assertEq(allocatedStrats.length, 0, "should not have any allocated strats before allocation"); - + // Validate events _checkAllocationEvents({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - currentMagnitude: firstAlloc, + magnitude: firstAlloc, encumberedMagnitude: firstAlloc, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + effectBlock: _defaultAllocEffectBlock() }); // Allocate magnitude @@ -1999,6 +2070,14 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: int64(firstAlloc), effectBlock: _defaultAllocEffectBlock()}), + expectedMagnitudes: Magnitudes({encumbered: firstAlloc, max: WAD, allocatable: WAD - firstAlloc}) + }); + // Warp to allocation complete block cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); @@ -2009,29 +2088,28 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - currentMagnitude: firstAlloc + secondAlloc, - encumberedMagnitude: firstAlloc + secondAlloc, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + magnitude: secondAlloc, + encumberedMagnitude: secondAlloc, + effectBlock: _defaultAllocEffectBlock() }); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); // Check storage - assertEq( - secondAlloc, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude not updated" - ); - - allocatedSets = allocationManager.getAllocatedSets(defaultOperator); - allocatedStrats = allocationManager.getAllocatedStrategies(defaultOperator, defaultOperatorSet); - assertEq(allocatedSets.length, 1, "should have a single allocated set"); - assertEq(allocatedSets[0].key(), defaultOperatorSet.key(), "should be allocated to default set"); - assertEq(allocatedStrats.length, 1, "should have a single allocated strategy to default set"); - assertEq(address(allocatedStrats[0]), address(strategyMock), "should have allocated default strat"); + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: firstAlloc, pendingDiff: int64(secondAlloc - firstAlloc), effectBlock: _defaultAllocEffectBlock()}), + expectedMagnitudes: Magnitudes({encumbered: secondAlloc, max: WAD, allocatable: WAD - secondAlloc}) + }); } + /** + * Allocates maximum magnitude to multiple strategies for the same operatorSet + * Validates that encumbered magnitude is max for each strategy + */ function testFuzz_allocateMaxToMultipleStrategies( Randomness r ) public rand(r) { @@ -2048,9 +2126,9 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: operatorSet, strategy: strategies[i], - currentMagnitude: WAD, + magnitude: WAD, encumberedMagnitude: WAD, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + effectBlock: _defaultAllocEffectBlock() }); } @@ -2072,10 +2150,12 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe /** * Allocates to `firstMod` magnitude and then deallocate to `secondMod` magnitude - * Validates the storage - * - 1. After deallocation is called - * - 2. After the deallocationd delay is hit - * - 3. After the deallocation queue is cleared + * Validates: + * 1. Events are valid for the allocation and deallocation + * 2. Storage after the allocation is made + * 3. Storage after the deallocation is made + * 4. Storage after the deallocation effect block is hit + * 5. Storage after the deallocation queue is cleared (specifically encumbered mag is decreased) */ function testFuzz_allocate_deallocate_whenRegistered( Randomness r @@ -2091,9 +2171,9 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - currentMagnitude: firstMod, + magnitude: firstMod, encumberedMagnitude: firstMod, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + effectBlock: _defaultAllocEffectBlock() }); cheats.prank(defaultOperator); @@ -2105,39 +2185,30 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe // Deallocate allocateParams = _newAllocateParams(defaultOperatorSet, secondMod); - _checkAllocationEvents({ + _checkDeallocationEvent({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - currentMagnitude: firstMod - secondMod, - encumberedMagnitude: firstMod - secondMod, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + magnitude: secondMod, + effectBlock: uint32(block.number + DEALLOCATION_DELAY) }); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); // Check storage after dealloc - assertEq( - firstMod, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should not be updated" - ); - assertEq( - WAD - firstMod, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude not calcualted correctly" - ); - uint32 effectBlock = uint32(block.number + DEALLOCATION_DELAY); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: firstMod, - expectedPendingDiff: -int128(uint128(firstMod - secondMod)), - expectedEffectBlock: effectBlock + expectedAllocation: Allocation({ + currentMagnitude: firstMod, + pendingDiff: -int128(uint128(firstMod - secondMod)), + effectBlock: effectBlock + }), + expectedMagnitudes: Magnitudes({encumbered: firstMod, max: WAD, allocatable: WAD - firstMod}) }); // Check storage after roll to completion @@ -2146,28 +2217,116 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: secondMod, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: secondMod, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: firstMod, max: WAD, allocatable: WAD - secondMod}) }); - assertEq( - firstMod, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should not be updated" - ); // Check storage after clearing deallocation queue allocationManager.clearDeallocationQueue(defaultOperator, strategyMock.toArray(), uint16(1).toArrayU16()); - assertEq( - secondMod, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should be updated" - ); + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: secondMod, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: secondMod, max: WAD, allocatable: WAD - secondMod}) + }); + } + + /** + * Allocates to an operatorSet, then fully deallocates after the strategy is removed from the set. + * Validates that the deallocation takes effect immediately after the strategy is removed + */ + function test_allocate_removeStrategyFromSet_fullyDeallocate() public { + // Allocate + AllocateParams[] memory allocateParams = _randAllocateParams_SingleMockStrategy(defaultOperatorSet.toArray()); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // Remove strategy from operatorSet + cheats.prank(defaultAVS); + allocationManager.removeStrategiesFromOperatorSet(defaultAVS, defaultOperatorSet.id, defaultStrategies); + + // Deallocate All Instantly + AllocateParams[] memory deallocateParams = allocateParams; + deallocateParams[0].newMagnitudes[0] = 0; + + // We check the allocation event and not the deallocation event since the encumbered mag is updated too! + _checkAllocationEvents({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + magnitude: 0, + encumberedMagnitude: 0, + effectBlock: uint32(block.number) + }); + + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, deallocateParams); + + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: 0, max: WAD, allocatable: WAD}) + }); + } + + /** + * Allocates to an operatorSet, deallocates, then removes a strategy from the operatorSet + * Validates that: + * 1. The deallocation still completes at its expected time + */ + function testFuzz_allocate_deallocate_removeStrategyFromSet(Randomness r) public { + // Allocate + AllocateParams[] memory allocateParams = _randAllocateParams_SingleMockStrategy(defaultOperatorSet.toArray()); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // Deallocate + AllocateParams[] memory deallocateParams = r.DeallocateParams(allocateParams); + uint32 deallocEffectBlock = uint32(block.number + DEALLOCATION_DELAY); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, deallocateParams); + + // Remove strategy from operatorSet + cheats.prank(defaultAVS); + allocationManager.removeStrategiesFromOperatorSet(defaultAVS, defaultOperatorSet.id, defaultStrategies); + + // Roll to just before deallocation complete block & clear deallocation queue for sanity + cheats.roll(deallocEffectBlock - 1); + allocationManager.clearDeallocationQueue(defaultOperator, strategyMock.toArray(), _maxNumToClear()); + + int128 expectedDiff = -int128(uint128(allocateParams[0].newMagnitudes[0] - deallocateParams[0].newMagnitudes[0])); + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: allocateParams[0].newMagnitudes[0], pendingDiff: expectedDiff, effectBlock: deallocEffectBlock}), + expectedMagnitudes: Magnitudes({encumbered: allocateParams[0].newMagnitudes[0], max: WAD, allocatable: WAD - allocateParams[0].newMagnitudes[0]}) + }); + + // Roll to deallocation complete block + cheats.roll(deallocEffectBlock); + + // Note that the encumbered mag hasn't been updated since we haven't cleared the deallocaction queue! + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + expectedAllocation: Allocation({currentMagnitude: deallocateParams[0].newMagnitudes[0], pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: allocateParams[0].newMagnitudes[0], max: WAD, allocatable: WAD - deallocateParams[0].newMagnitudes[0]}) + }); } /** * Allocates to an operator set, then fully deallocates when not registered to the set. - * Checks that deallocation is instant and can be reallocated instantly. + * Validates that: + * 1. Events are properly emitted post instantaneous deallocation + * 2. The deallocation is instant & can be reallocated immediately + * 3. Storage/introspection post combined deallocation/allocation */ function testFuzz_allocate_fullyDeallocate_reallocate_WhenNotRegistered( Randomness r @@ -2175,31 +2334,15 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe // Bound allocation and deallocation uint64 firstMod = r.Uint64(1, WAD); - // Create a new operator sets that the operator is not registered for + // Create new operator sets that the operator is not registered for OperatorSet memory operatorSetA = _createOperatorSet(OperatorSet(defaultAVS, r.Uint32()), defaultStrategies); OperatorSet memory operatorSetB = _createOperatorSet(OperatorSet(defaultAVS, r.Uint32()), defaultStrategies); // Allocate magnitude to operator set AllocateParams[] memory allocateParams = _newAllocateParams(operatorSetA, firstMod); - - _checkAllocationEvents({ - operator: defaultOperator, - operatorSet: operatorSetA, - strategy: strategyMock, - currentMagnitude: firstMod, - encumberedMagnitude: firstMod, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) - }); - cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); - assertEq( - firstMod, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should equal firstMod" - ); - // Warp to allocation complete block cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); @@ -2208,46 +2351,36 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe allocateParams[0] = _newAllocateParams(operatorSetA, 0)[0]; allocateParams[1] = _newAllocateParams(operatorSetB, firstMod)[0]; + // We check the allocation event and not the deallocation event since + // encumbered magnitude is also updated here _checkAllocationEvents({ operator: defaultOperator, operatorSet: operatorSetA, strategy: strategyMock, - currentMagnitude: 0, + magnitude: 0, encumberedMagnitude: 0, - effectBlock: 0 + effectBlock: uint32(block.number) // Instant deallocation }); _checkAllocationEvents({ operator: defaultOperator, operatorSet: operatorSetB, strategy: strategyMock, - currentMagnitude: firstMod, + magnitude: firstMod, encumberedMagnitude: firstMod, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + effectBlock: _defaultAllocEffectBlock() }); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); - // Check storage after dealloc - assertEq( - firstMod, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should not be changed" - ); - assertEq( - WAD - firstMod, - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - "allocatableMagnitude not calculated correctly" - ); - + // Check storage after deallocation // Check operator set A _checkAllocationStorage({ operator: defaultOperator, operatorSet: operatorSetA, strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: firstMod, max: WAD, allocatable: WAD - firstMod}) // This is from opsetB }); // Check operator set B @@ -2255,15 +2388,21 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: operatorSetB, strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: int64(firstMod), - expectedEffectBlock: block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY + expectedAllocation: Allocation({ + currentMagnitude: 0, + pendingDiff: int128(uint128(firstMod)), + effectBlock: _defaultAllocEffectBlock() + }), + expectedMagnitudes: Magnitudes({encumbered: firstMod, max: WAD, allocatable: WAD - firstMod}) }); } /** - * Allocate to an operator set using magnitude that is only available if the deallocation - * queue is cleared + * Allocates all magnitude to a single strategy across multiple operatorSets. Deallocates fully, and then reallocates + * Validates: + * 1. Events are emitted for the allocation, deallocation, and reallocation (including the deallocation queue clear) + * 2. Stake is fully allocated & encumbered mag used up + * 3. Stake can be reallocated after the deallocation delay */ function testFuzz_allocate_fromClearedDeallocQueue( Randomness r @@ -2276,15 +2415,17 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe _registerForOperatorSets(defaultOperator, deallocSets); AllocateParams[] memory allocateParams = _randAllocateParams_SingleMockStrategy_AllocAll(deallocSets); - for (uint256 i; i < numOpSets; ++i) { + for (uint256 i; i < allocateParams.length; ++i) { + // There is only one strategy each allocateParams, so we don't need a nested for loop _checkAllocationEvents({ operator: defaultOperator, - operatorSet: deallocSets[i], + operatorSet: allocateParams[i].operatorSet, strategy: strategyMock, - currentMagnitude: WAD, - encumberedMagnitude: WAD, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + magnitude: allocateParams[i].newMagnitudes[0], + encumberedMagnitude: _encumberedMagnitudes[strategyMock] + allocateParams[i].newMagnitudes[0], + effectBlock: _defaultAllocEffectBlock() }); + _encumberedMagnitudes[strategyMock] += allocateParams[i].newMagnitudes[0]; } cheats.prank(defaultOperator); @@ -2303,13 +2444,12 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe AllocateParams[] memory deallocateParams = _newAllocateParams(deallocSets, 0); for (uint256 i; i < numOpSets; ++i) { - _checkAllocationEvents({ + _checkDeallocationEvent({ operator: defaultOperator, operatorSet: deallocSets[i], strategy: strategyMock, - currentMagnitude: 0, - encumberedMagnitude: 0, - effectBlock: 0 + magnitude: 0, + effectBlock: uint32(block.number + DEALLOCATION_DELAY) }); } @@ -2339,13 +2479,19 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe _registerForOperatorSet(defaultOperator, finalOpSet); AllocateParams[] memory finalAllocParams = _newAllocateParams(finalOpSet, WAD); + _checkClearDeallocationQueueEvents({ + operator: defaultOperator, + strategy: strategyMock, + encumberedMagnitude: 0 + }); + _checkAllocationEvents({ operator: defaultOperator, operatorSet: finalOpSet, strategy: strategyMock, - currentMagnitude: WAD, + magnitude: WAD, encumberedMagnitude: WAD, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + effectBlock: _defaultAllocEffectBlock() }); cheats.prank(defaultOperator); @@ -2357,62 +2503,40 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe operator: defaultOperator, operatorSet: finalOpSet, strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: int64(WAD), - expectedEffectBlock: block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY + expectedAllocation: Allocation({ + currentMagnitude: 0, + pendingDiff: int128(uint128(WAD)), + effectBlock: _defaultAllocEffectBlock() + }), + expectedMagnitudes: Magnitudes({encumbered: WAD, max: WAD, allocatable: 0}) }); - assertEq( - allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock), - 0, - "operator should not have any remaining allocatable magnitude" - ); - assertEq( - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - WAD, - "all magnitude should be allocated" - ); - - for (uint256 i; i < deallocSets.length; ++i) { - _checkAllocationStorage({ - operator: defaultOperator, - operatorSet: deallocSets[i], - strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: 0, - expectedEffectBlock: 0 - }); - } } + /** + * Allocates all mag and then deallocates all mag + * Validates + * 1. Events for the deallocation + * 2. Storage after deallocation + * 3. Storage after clearing the deallocation queue + */ function test_deallocate_all() public { - // Allocate + // Allocate all AllocateParams[] memory allocateParams = _newAllocateParams(defaultOperatorSet, WAD); - - _checkAllocationEvents({ - operator: defaultOperator, - operatorSet: defaultOperatorSet, - strategy: strategyMock, - currentMagnitude: WAD, - encumberedMagnitude: WAD, - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) - }); - cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); // Warp to allocation complete block cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - // Deallocate + // Deallocate all allocateParams[0].newMagnitudes[0] = 0; - _checkAllocationEvents({ + _checkDeallocationEvent({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - currentMagnitude: 0, - encumberedMagnitude: 0, - effectBlock: 0 + magnitude: 0, + effectBlock: uint32(block.number + DEALLOCATION_DELAY) }); cheats.prank(defaultOperator); @@ -2423,114 +2547,24 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, uint16(1).toArrayU16()); // Check storage - assertEq( - 0, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should be updated" - ); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: 0, - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({currentMagnitude: 0, pendingDiff: 0, effectBlock: 0}), + expectedMagnitudes: Magnitudes({encumbered: 0, max: WAD, allocatable: WAD}) }); } - function testFuzz_allocate_deallocate_singleStrat_multipleOperatorSets( - Randomness r - ) public rand(r) { - uint8 numOpSets = uint8(r.Uint256(1, FUZZ_MAX_OP_SETS)); - - // Create and register for operator sets, each with a single default strategy - OperatorSet[] memory operatorSets = r.OperatorSetArray(defaultAVS, numOpSets); - _createOperatorSets(operatorSets, defaultStrategies); - _registerForOperatorSets(defaultOperator, operatorSets); - - (AllocateParams[] memory allocateParams, AllocateParams[] memory deallocateParams) = - _randAllocAndDeallocParams_SingleMockStrategy(operatorSets); - - // Allocate - for (uint256 i; i < allocateParams.length; ++i) { - _checkAllocationEvents({ - operator: defaultOperator, - operatorSet: operatorSets[i], - strategy: strategyMock, - currentMagnitude: allocateParams[i].newMagnitudes[0], - encumberedMagnitude: allocateParams[i].newMagnitudes[0], - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) - }); - } - - cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, allocateParams); - uint64 encumberedMagnitudeAfterAllocation = allocationManager.encumberedMagnitude(defaultOperator, strategyMock); - - // Warp to allocation complete block - cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - - // Calculate post-deallocation magnitude - // We can add each entry to this value because each operator set is using the same strategy - uint64 postDeallocMag; - for (uint256 i; i < deallocateParams.length; ++i) { - postDeallocMag += deallocateParams[i].newMagnitudes[0]; - _checkAllocationEvents({ - operator: defaultOperator, - operatorSet: operatorSets[i], - strategy: strategyMock, - currentMagnitude: deallocateParams[i].newMagnitudes[0], - encumberedMagnitude: deallocateParams[i].newMagnitudes[0], - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) - }); - } - - cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, deallocateParams); - - // Check storage after dealloc - assertEq( - encumberedMagnitudeAfterAllocation, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should not be updated" - ); - - for (uint256 i; i < allocateParams.length; ++i) { - _checkAllocationStorage({ - operator: defaultOperator, - operatorSet: operatorSets[i], - strategy: strategyMock, - expectedCurrentMagnitude: allocateParams[i].newMagnitudes[0], - expectedPendingDiff: -int64(allocateParams[i].newMagnitudes[0] - deallocateParams[i].newMagnitudes[0]), - expectedEffectBlock: block.number + DEALLOCATION_DELAY - }); - } - - // Check storage after roll to completion - cheats.roll(block.number + DEALLOCATION_DELAY); - - for (uint256 i; i < allocateParams.length; ++i) { - _checkAllocationStorage({ - operator: defaultOperator, - operatorSet: operatorSets[i], - strategy: strategyMock, - expectedCurrentMagnitude: deallocateParams[i].newMagnitudes[0], - expectedPendingDiff: 0, - expectedEffectBlock: 0 - }); - } - - // Clear deallocation queue - allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, type(uint16).max.toArrayU16()); - // Check storage after clearing deallocation queue - assertEq( - postDeallocMag, - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should be updated" - ); - } - - function testFuzz_MultipleSetsAndStrats( + + /** + * Allocates, deallocates, and then clears the deallocation queue. Multiple strategies & sets in a single operatorSet + * Validates: + * 1. Events for allocation, deallocation, and deallocation queue clear + * 2. Storage after allocation & after allocation effect block + * 3. Storage after deallocation & after deallocation effect block + */ + function testFuzz_lifecycle_allocate_deallocate_MultipleSetsAndStrats( Randomness r ) public rand(r) { uint256 numAllocations = r.Uint256(2, FUZZ_MAX_ALLOCATIONS); @@ -2542,16 +2576,21 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe cheats.prank(defaultAVS); allocationManager.createOperatorSets(defaultAVS, createSetParams); + + for(uint256 i = 0; i < allocateParams.length; i++) { + _registerForOperatorSet(defaultOperator, allocateParams[i].operatorSet); + } + // Allocate for (uint256 i; i < allocateParams.length; ++i) { for (uint256 j; j < allocateParams[i].strategies.length; ++j) { _checkAllocationEvents({ operator: defaultOperator, operatorSet: allocateParams[i].operatorSet, strategy: allocateParams[i].strategies[j], - currentMagnitude: allocateParams[i].newMagnitudes[j], + magnitude: allocateParams[i].newMagnitudes[j], encumberedMagnitude: allocateParams[i].newMagnitudes[j], - effectBlock: uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY) + effectBlock: _defaultAllocEffectBlock() }); } } @@ -2559,47 +2598,107 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, allocateParams); + // Check storage after allocation for (uint256 i; i < allocateParams.length; ++i) { for (uint256 j = 0; j < allocateParams[i].strategies.length; j++) { _checkAllocationStorage({ operator: defaultOperator, - operatorSet: allocateParams[i].operatorSet, - strategy: allocateParams[i].strategies[j], - expectedCurrentMagnitude: 0, - expectedPendingDiff: int64(allocateParams[i].newMagnitudes[j]), - expectedEffectBlock: block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY + operatorSet: allocateParams[i].operatorSet, + strategy: allocateParams[i].strategies[j], + expectedAllocation: Allocation({ + currentMagnitude: 0, + pendingDiff: int128(uint128(allocateParams[i].newMagnitudes[j])), + effectBlock: _defaultAllocEffectBlock() + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[i].newMagnitudes[j], + max: WAD, + allocatable: WAD - allocateParams[i].newMagnitudes[j] + }) + }); + } + } + + // Warp to allocation complete block + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // Check storage after roll to completion + for (uint256 i; i < allocateParams.length; ++i) { + for (uint256 j = 0; j < allocateParams[i].strategies.length; j++) { + _checkAllocationStorage({ + operator: defaultOperator, + operatorSet: allocateParams[i].operatorSet, + strategy: allocateParams[i].strategies[j], + expectedAllocation: Allocation({ + currentMagnitude: allocateParams[i].newMagnitudes[j], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[i].newMagnitudes[j], + max: WAD, + allocatable: WAD - allocateParams[i].newMagnitudes[j] + }) + }); + } + } + + // Deallocate + + for (uint256 i; i < deallocateParams.length; ++i) { + for (uint256 j = 0; j < deallocateParams[i].strategies.length; j++) { + _checkDeallocationEvent({ + operator: defaultOperator, + operatorSet: deallocateParams[i].operatorSet, + strategy: deallocateParams[i].strategies[j], + magnitude: deallocateParams[i].newMagnitudes[j], + effectBlock: uint32(block.number + DEALLOCATION_DELAY) }); } } - cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, deallocateParams); for (uint256 i; i < allocateParams.length; ++i) { for (uint256 j = 0; j < allocateParams[i].strategies.length; j++) { + int128 expectedDiff = -int128(uint128(allocateParams[i].newMagnitudes[j] - deallocateParams[i].newMagnitudes[j])); _checkAllocationStorage({ operator: defaultOperator, - operatorSet: allocateParams[i].operatorSet, - strategy: allocateParams[i].strategies[j], - expectedCurrentMagnitude: allocateParams[i].newMagnitudes[j], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + operatorSet: deallocateParams[i].operatorSet, + strategy: deallocateParams[i].strategies[j], + expectedAllocation: Allocation({ + currentMagnitude: allocateParams[i].newMagnitudes[j], + pendingDiff: expectedDiff, + effectBlock: uint32(block.number + DEALLOCATION_DELAY) + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[i].newMagnitudes[j], + max: WAD, + allocatable: WAD - allocateParams[i].newMagnitudes[j] + }) }); } } - cheats.prank(defaultOperator); - allocationManager.modifyAllocations(defaultOperator, deallocateParams); - - // Deallocations are immediate if the operator's allocation is not slashable. + // Warp to deallocation complete block + cheats.roll(block.number + DEALLOCATION_DELAY); for (uint256 i; i < allocateParams.length; ++i) { for (uint256 j = 0; j < allocateParams[i].strategies.length; j++) { _checkAllocationStorage({ operator: defaultOperator, - operatorSet: allocateParams[i].operatorSet, + operatorSet: deallocateParams[i].operatorSet, strategy: allocateParams[i].strategies[j], - expectedCurrentMagnitude: deallocateParams[i].newMagnitudes[j], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({ + currentMagnitude: deallocateParams[i].newMagnitudes[j], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[i].newMagnitudes[j], + max: WAD, + allocatable: WAD - deallocateParams[i].newMagnitudes[j] + }) }); } } @@ -2610,7 +2709,7 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU using ArrayLib for *; /// ----------------------------------------------------------------------- - /// clearModificationQueue() + /// clearDeallocationQueue() /// ----------------------------------------------------------------------- function test_revert_paused() public { @@ -2660,9 +2759,16 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: allocateParams[0].newMagnitudes[0], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({ + currentMagnitude: allocateParams[0].newMagnitudes[0], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[0].newMagnitudes[0], + max: WAD, + allocatable: WAD - allocateParams[0].newMagnitudes[0] + }) }); } @@ -2673,7 +2779,7 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU * - Clears deallocation queue when the dealloc can be completed * - Assert events & validates storage after the deallocateParams are completed */ - function testFuzz_allocate_deallocate_whenRegistered( + function testFuzz_allocate_deallocate( Randomness r ) public rand(r) { // Generate a random allocation and subsequent deallocation from the default operator set @@ -2688,46 +2794,62 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); // Deallocate + _checkDeallocationEvent({ + operator: defaultOperator, + operatorSet: defaultOperatorSet, + strategy: strategyMock, + magnitude: deallocateParams[0].newMagnitudes[0], + effectBlock: uint32(block.number + DEALLOCATION_DELAY) + }); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, deallocateParams); // Clear queue - since we have not rolled forward, this should be a no-op allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); - assertEq( - allocateParams[0].newMagnitudes[0], - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should not be updated" - ); // Validate storage - encumbered magnitude should just be allocateParams (we only have 1 allocation) _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: allocateParams[0].newMagnitudes[0], - expectedPendingDiff: -int128(uint128(allocateParams[0].newMagnitudes[0] - deallocateParams[0].newMagnitudes[0])), - expectedEffectBlock: block.number + DEALLOCATION_DELAY + expectedAllocation: Allocation({ + currentMagnitude: allocateParams[0].newMagnitudes[0], + pendingDiff: -int128(uint128(allocateParams[0].newMagnitudes[0] - deallocateParams[0].newMagnitudes[0])), + effectBlock: uint32(block.number + DEALLOCATION_DELAY) + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[0].newMagnitudes[0], + max: WAD, + allocatable: WAD - allocateParams[0].newMagnitudes[0] + }) }); // Warp to deallocation complete block cheats.roll(block.number + DEALLOCATION_DELAY); // Clear queue + _checkClearDeallocationQueueEvents({ + operator: defaultOperator, + strategy: strategyMock, + encumberedMagnitude: deallocateParams[0].newMagnitudes[0] + }); allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); // Validate storage - encumbered magnitude should just be deallocateParams (we only have 1 deallocation) - assertEq( - deallocateParams[0].newMagnitudes[0], - allocationManager.encumberedMagnitude(defaultOperator, strategyMock), - "encumberedMagnitude should be updated" - ); _checkAllocationStorage({ operator: defaultOperator, operatorSet: defaultOperatorSet, strategy: strategyMock, - expectedCurrentMagnitude: deallocateParams[0].newMagnitudes[0], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + expectedAllocation: Allocation({ + currentMagnitude: deallocateParams[0].newMagnitudes[0], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: deallocateParams[0].newMagnitudes[0], + max: WAD, + allocatable: WAD - deallocateParams[0].newMagnitudes[0] + }) }); } @@ -2736,7 +2858,7 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU * - The deallocation does not block state updates from the second allocation, even though the allocation has an earlier * effect block */ - function test_allocate_deallocate_allocate_whenRegistered() public { + function test_allocate_deallocate_allocate() public { // Allocate half of mag to default operator set AllocateParams[] memory firstAllocation = _newAllocateParams(defaultOperatorSet, 5e17); cheats.prank(defaultOperator); @@ -2758,14 +2880,14 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU _registerForOperatorSet(defaultOperator, newOperatorSet); // Allocate 33e16 mag to new operator set - uint32 allocationEffectBlock = uint32(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + uint32 allocationEffectBlock = _defaultAllocEffectBlock(); AllocateParams[] memory secondAllocation = _newAllocateParams(newOperatorSet, 33e16); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, secondAllocation); allocation = allocationManager.getAllocation(defaultOperator, newOperatorSet, strategyMock); assertEq(allocationEffectBlock, allocation.effectBlock, "effect block not correct"); - // Warp to allocation effect block & clear the queue + // Warp to allocation effect block & clear the queue - clearing is a noop here cheats.roll(allocationEffectBlock); allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); @@ -2777,6 +2899,15 @@ contract AllocationManagerUnitTests_ClearDeallocationQueue is AllocationManagerU AllocateParams[] memory thirdAllocation = _newAllocateParams(newOperatorSet, 10e16); cheats.prank(defaultOperator); allocationManager.modifyAllocations(defaultOperator, thirdAllocation); + + // Warp & validate deallocation + cheats.roll(deallocationEffectBlock); + _checkClearDeallocationQueueEvents({ + operator: defaultOperator, + strategy: strategyMock, + encumberedMagnitude: 58e16 + }); + allocationManager.clearDeallocationQueue(defaultOperator, defaultStrategies, _maxNumToClear()); } /** @@ -2857,7 +2988,7 @@ contract AllocationManagerUnitTests_SetAllocationDelay is AllocationManagerUnitT function test_revert_callerNotOperator() public { delegationManagerMock.setIsOperator(operatorToSet, false); cheats.prank(operatorToSet); - cheats.expectRevert(OperatorNotRegistered.selector); + cheats.expectRevert(InvalidOperator.selector); allocationManager.setAllocationDelay(operatorToSet, 1); } @@ -3034,7 +3165,7 @@ contract AllocationManagerUnitTests_registerForOperatorSets is AllocationManager allocationManager.createOperatorSets(defaultAVS, createSetParams); for (uint256 j; j < numOpSets; ++j) { - cheats.expectEmit(true, true, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit OperatorAddedToOperatorSet(operator, OperatorSet(defaultAVS, operatorSetIds[j])); } @@ -3135,7 +3266,7 @@ contract AllocationManagerUnitTests_deregisterFromOperatorSets is AllocationMana allocationManager.registerForOperatorSets(operator, RegisterParams(defaultAVS, operatorSetIds, "")); for (uint256 j; j < numOpSets; ++j) { - cheats.expectEmit(true, true, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit OperatorRemovedFromOperatorSet(operator, OperatorSet(defaultAVS, operatorSetIds[j])); } @@ -3143,7 +3274,12 @@ contract AllocationManagerUnitTests_deregisterFromOperatorSets is AllocationMana defaultAVS, abi.encodeWithSelector(IAVSRegistrar.deregisterOperator.selector, operator, operatorSetIds) ); - cheats.prank(operator); + bool callFromAVS = r.Boolean(); + if (callFromAVS) { + cheats.prank(defaultAVS); + } else { + cheats.prank(operator); + } allocationManager.deregisterFromOperatorSets(DeregisterParams(operator, defaultAVS, operatorSetIds)); assertEq(allocationManager.getRegisteredSets(operator).length, 0, "should not be registered for any sets"); @@ -3186,14 +3322,18 @@ contract AllocationManagerUnitTests_addStrategiesToOperatorSet is AllocationMana for (uint256 i; i < MAX_OPERATOR_SET_STRATEGY_LIST_LENGTH - 1; ++i) { allocationManager.addStrategiesToOperatorSet( - defaultAVS, defaultOperatorSet.id, IStrategy(cheats.randomAddress()).toArray() + defaultAVS, + defaultOperatorSet.id, + IStrategy(cheats.randomAddress()).toArray() ); } cheats.expectRevert(MaxStrategiesExceeded.selector); allocationManager.addStrategiesToOperatorSet( - defaultAVS, defaultOperatorSet.id, IStrategy(cheats.randomAddress()).toArray() - ); + defaultAVS, + defaultOperatorSet.id, + IStrategy(cheats.randomAddress()).toArray() + ); } function testFuzz_addStrategiesToOperatorSet_Correctness( @@ -3205,7 +3345,7 @@ contract AllocationManagerUnitTests_addStrategiesToOperatorSet is AllocationMana for (uint256 i; i < numStrategies; ++i) { strategies[i] = IStrategy(r.Address()); - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit StrategyAddedToOperatorSet(defaultOperatorSet, strategies[i]); } @@ -3247,7 +3387,7 @@ contract AllocationManagerUnitTests_removeStrategiesFromOperatorSet is Allocatio allocationManager.addStrategiesToOperatorSet(defaultAVS, defaultOperatorSet.id, strategies); for (uint256 i; i < numStrategies; ++i) { - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit StrategyRemovedFromOperatorSet(defaultOperatorSet, strategies[i]); } @@ -3271,17 +3411,18 @@ contract AllocationManagerUnitTests_createOperatorSets is AllocationManagerUnitT function testRevert_createOperatorSets_InvalidOperatorSet() public { cheats.prank(defaultAVS); cheats.expectRevert(InvalidOperatorSet.selector); - allocationManager.createOperatorSets( - defaultAVS, CreateSetParams(defaultOperatorSet.id, defaultStrategies).toArray() - ); + allocationManager.createOperatorSets(defaultAVS, CreateSetParams(defaultOperatorSet.id, defaultStrategies).toArray()); } function testRevert_createOperatorSets_MaxStrategiesExceeded() public { cheats.prank(defaultAVS); cheats.expectRevert(MaxStrategiesExceeded.selector); allocationManager.createOperatorSets( - defaultAVS, - CreateSetParams(defaultOperatorSet.id, new IStrategy[](MAX_OPERATOR_SET_STRATEGY_LIST_LENGTH + 1)).toArray() + defaultAVS, + CreateSetParams( + defaultOperatorSet.id, + new IStrategy[](MAX_OPERATOR_SET_STRATEGY_LIST_LENGTH + 1) + ).toArray() ); } @@ -3297,10 +3438,10 @@ contract AllocationManagerUnitTests_createOperatorSets is AllocationManagerUnitT for (uint256 i; i < numOpSets; ++i) { createSetParams[i].operatorSetId = r.Uint32(1, type(uint32).max); createSetParams[i].strategies = r.StrategyArray(numStrategies); - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit OperatorSetCreated(OperatorSet(avs, createSetParams[i].operatorSetId)); for (uint256 j; j < numStrategies; ++j) { - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit StrategyAddedToOperatorSet( OperatorSet(avs, createSetParams[i].operatorSetId), createSetParams[i].strategies[j] ); @@ -3328,13 +3469,20 @@ contract AllocationManagerUnitTests_createOperatorSets is AllocationManagerUnitT } contract AllocationManagerUnitTests_setAVSRegistrar is AllocationManagerUnitTests { + + function test_getAVSRegistrar() public { + address randomAVS = random().Address(); + IAVSRegistrar avsRegistrar = allocationManager.getAVSRegistrar(randomAVS); + assertEq(address(avsRegistrar), address(randomAVS), "AVS registrar should return default"); + } + function testFuzz_setAVSRegistrar_Correctness( Randomness r ) public rand(r) { address avs = r.Address(); IAVSRegistrar avsRegistrar = IAVSRegistrar(r.Address()); - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit AVSRegistrarSet(avs, avsRegistrar); cheats.prank(avs); @@ -3346,7 +3494,7 @@ contract AllocationManagerUnitTests_setAVSRegistrar is AllocationManagerUnitTest contract AllocationManagerUnitTests_updateAVSMetadataURI is AllocationManagerUnitTests { function test_updateAVSMetadataURI_Correctness() public { string memory newURI = "test"; - cheats.expectEmit(true, false, false, false, address(allocationManager)); + cheats.expectEmit(true, true, true, true, address(allocationManager)); emit AVSMetadataURIUpdated(defaultAVS, newURI); cheats.prank(defaultAVS); allocationManager.updateAVSMetadataURI(defaultAVS, newURI); @@ -3354,6 +3502,8 @@ contract AllocationManagerUnitTests_updateAVSMetadataURI is AllocationManagerUni } contract AllocationManagerUnitTests_getStrategyAllocations is AllocationManagerUnitTests { + using ArrayLib for *; + function testFuzz_getStrategyAllocations_Correctness( Randomness r ) public rand(r) { @@ -3369,17 +3519,299 @@ contract AllocationManagerUnitTests_getStrategyAllocations is AllocationManagerU cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); - (OperatorSet[] memory operatorSets, Allocation[] memory allocations) = + (OperatorSet[] memory operatorSets, ) = allocationManager.getStrategyAllocations(defaultOperator, allocateParams[0].strategies[0]); assertEq(operatorSets[0].avs, allocateParams[0].operatorSet.avs, "should be defaultAVS"); assertEq(operatorSets[0].id, allocateParams[0].operatorSet.id, "should be defaultOperatorSet"); _checkAllocationStorage({ - allocation: allocations[0], - expectedCurrentMagnitude: allocateParams[0].newMagnitudes[0], - expectedPendingDiff: 0, - expectedEffectBlock: 0 + operator: defaultOperator, + operatorSet: operatorSets[0], + strategy: createSetParams[0].strategies[0], + expectedAllocation: Allocation({ + currentMagnitude: allocateParams[0].newMagnitudes[0], + pendingDiff: 0, + effectBlock: 0 + }), + expectedMagnitudes: Magnitudes({ + encumbered: allocateParams[0].newMagnitudes[0], + max: WAD, + allocatable: WAD - allocateParams[0].newMagnitudes[0] + }) + }); + } +} + +contract AllocationManagerUnitTests_getSlashableStake is AllocationManagerUnitTests { + using SlashingLib for *; + + /** + * Allocates half of magnitude for a single strategy to an operatorSet. Then allocates again. Slashes 50% + * of the first allocation. Validates slashable stake at each step. + */ + function test_allocate_onePendingAllocation( + Randomness r + ) public rand(r) { + // Generate allocation for `strategyMock`, we allocate half + { + AllocateParams[] memory allocateParams = _newAllocateParams(defaultOperatorSet, 5e17); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + } + + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(5e17) + }); + + // Allocate the other half + AllocateParams[] memory allocateParams2 = _newAllocateParams(defaultOperatorSet, WAD); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams2); + uint32 secondAllocEffectBlock = _defaultAllocEffectBlock(); + + // Check minimum slashable stake remains the same + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(5e17) + }); + + // Check minimum slashable stake would not change even after the second allocation becomes effective + // This is because the allocation is not effective yet & we're getting a MINIMUM + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(5e17), + futureBlock: secondAllocEffectBlock + 1 + }); + + // Check minimum slashable stake after the second allocation becomes effective + cheats.roll(secondAllocEffectBlock); + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES + }); + } + + /** + * Allocates to `firstMod` magnitude and then deallocate to `secondMod` magnitude + * Validates slashable stake at each step after allocation and deallocation + */ + function testFuzz_allocate_deallocate_validateSlashableStake( + Randomness r + ) public rand(r) { + // Bound allocation and deallocation + uint64 firstMod = r.Uint64(1, WAD); + uint64 secondMod = r.Uint64(0, firstMod - 1); + + // Allocate magnitude to default registered set + AllocateParams[] memory allocateParams = _newAllocateParams(defaultOperatorSet, firstMod); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + + // 1. Validate slashable stake. + // This value should be 0 even at the effectBlock since its minimal slashable stake + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: 0, + futureBlock: _defaultAllocEffectBlock() + }); + + // Warp to allocation complete block + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // 2. Check slashable stake after allocation effect block + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(firstMod) + }); + + // Deallocate + allocateParams = _newAllocateParams(defaultOperatorSet, secondMod); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + // 3. Check slashable stake after deallocation - should be same at current block + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(firstMod), + futureBlock: uint32(block.number) + }); + + // 4. Check slashable stake at the deallocation effect block + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(secondMod), + futureBlock: uint32(block.number + DEALLOCATION_DELAY) + }); + + // Warp to deallocation effect block + cheats.roll(block.number + DEALLOCATION_DELAY); + + // 5. Check slashable stake at the deallocation effect block + _checkSlashableStake({ + operatorSet: defaultOperatorSet, + operator: defaultOperator, + strategies: defaultStrategies, + expectedSlashableStake: DEFAULT_OPERATOR_SHARES.mulWad(secondMod) + }); + } + + /** + * Allocates all of magnitude to a single strategy to an operatorSet. + * Deallocate some portion. Finally, slash while deallocation is pending + */ + function testFuzz_SlashWhileDeallocationPending( + Randomness r + ) public rand(r) { + // Initialize state + AllocateParams[] memory allocateParams = r.AllocateParams(defaultAVS, 1, 1); + AllocateParams[] memory deallocateParams = r.DeallocateParams(allocateParams); + CreateSetParams[] memory createSetParams = r.CreateSetParams(allocateParams); + RegisterParams memory registerParams = r.RegisterParams(allocateParams); + SlashingParams memory slashingParams = r.SlashingParams(defaultOperator, allocateParams[0]); + + delegationManagerMock.setOperatorShares( + defaultOperator, allocateParams[0].strategies[0], DEFAULT_OPERATOR_SHARES + ); + + cheats.prank(defaultAVS); + allocationManager.createOperatorSets(defaultAVS, createSetParams); + cheats.startPrank(defaultOperator); + allocationManager.registerForOperatorSets(defaultOperator, registerParams); + + // Allocate + allocationManager.modifyAllocations(defaultOperator, allocateParams); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // Deallocate + allocationManager.modifyAllocations(defaultOperator, deallocateParams); + uint32 deallocationEffectBlock = uint32(block.number + DEALLOCATION_DELAY); + cheats.stopPrank(); + + // Check slashable stake after deallocation (still pending; no change) + _checkSlashableStake({ + operatorSet: allocateParams[0].operatorSet, + operator: defaultOperator, + strategies: allocateParams[0].strategies, + expectedSlashableStake: allocateParams[0].newMagnitudes[0] + }); + + // Check slashable stake after deallocation takes effect, before slashing + _checkSlashableStake({ + operatorSet: allocateParams[0].operatorSet, + operator: defaultOperator, + strategies: allocateParams[0].strategies, + expectedSlashableStake: deallocateParams[0].newMagnitudes[0], + futureBlock: deallocationEffectBlock + }); + + uint256 magnitudeAllocated = allocateParams[0].newMagnitudes[0]; + uint256 magnitudeDeallocated = magnitudeAllocated - deallocateParams[0].newMagnitudes[0]; + uint256 magnitudeSlashed = magnitudeAllocated.mulWad(slashingParams.wadsToSlash[0]); + uint256 expectedCurrentMagnitude = magnitudeAllocated - magnitudeSlashed; + int128 expectedPendingDiff = + -int128(uint128(magnitudeDeallocated - magnitudeDeallocated.mulWadRoundUp(slashingParams.wadsToSlash[0]))); + + // Slash + cheats.prank(defaultAVS); + allocationManager.slashOperator(defaultAVS, slashingParams); + + // Check slashable stake after slash + _checkSlashableStake({ + operatorSet: allocateParams[0].operatorSet, + operator: defaultOperator, + strategies: allocateParams[0].strategies, + expectedSlashableStake: expectedCurrentMagnitude + }); + + // Check slashable stake after deallocation takes effect + // Add 1 slippage for rounding down slashable stake + _checkSlashableStake({ + operatorSet: allocateParams[0].operatorSet, + operator: defaultOperator, + strategies: allocateParams[0].strategies, + expectedSlashableStake: expectedCurrentMagnitude - uint128(-expectedPendingDiff) - 1, + futureBlock: deallocationEffectBlock + }); + + cheats.roll(deallocationEffectBlock); + allocationManager.clearDeallocationQueue(defaultOperator, allocateParams[0].strategies, _maxNumToClear()); + + // Check slashable stake after slash and deallocation + // Add 1 slippage for rounding down slashable stake + _checkSlashableStake({ + operatorSet: allocateParams[0].operatorSet, + operator: defaultOperator, + strategies: allocateParams[0].strategies, + expectedSlashableStake: expectedCurrentMagnitude - uint128(-expectedPendingDiff) - 1 }); } } + +contract AllocationManagerUnitTests_getMaxMagnitudesAtBlock is AllocationManagerUnitTests { + using ArrayLib for *; + + function testFuzz_correctness(Randomness r) rand(r) public { + // Randomly allocate + AllocateParams[] memory allocateParams = _randAllocateParams_DefaultOpSet(); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(defaultOperator, allocateParams); + cheats.roll(block.number + DEFAULT_OPERATOR_ALLOCATION_DELAY); + + // Slash first time + SlashingParams memory slashParams = SlashingParams({ + operator: defaultOperator, + operatorSetId: defaultOperatorSet.id, + strategies: defaultStrategies, + wadsToSlash: r.Uint256(0.1 ether, 0.99 ether).toArrayU256(), + description: "test" + }); + uint32 firstSlashBlock = uint32(block.number); + cheats.prank(defaultAVS); + allocationManager.slashOperator(defaultAVS, slashParams); + uint64 maxMagnitudeAfterFirstSlash = allocationManager.getMaxMagnitude(defaultOperator, strategyMock); + + // Warp to random block + uint32 secondSlashBlock = uint32(block.number + r.Uint32()); + cheats.roll(secondSlashBlock); + + // Slash second time + slashParams.wadsToSlash = (r.Uint64(0.1 ether, 0.99 ether)).toArrayU256(); + cheats.prank(defaultAVS); + allocationManager.slashOperator(defaultAVS, slashParams); + uint64 maxMagnitudeAfterSecondSlash = allocationManager.getMaxMagnitude(defaultOperator, strategyMock); + + // Warp to a block after the second slash + cheats.roll(block.number + r.Uint32()); + + // Validate get max magnitudes at block + assertEq( + allocationManager.getMaxMagnitudesAtBlock(defaultOperator, defaultStrategies, firstSlashBlock)[0], + maxMagnitudeAfterFirstSlash, + "max magnitude after first slash not correct" + ); + + assertEq( + allocationManager.getMaxMagnitudesAtBlock(defaultOperator, defaultStrategies, secondSlashBlock)[0], + maxMagnitudeAfterSecondSlash, + "max magnitude after second slash not correct" + ); + } +} \ No newline at end of file diff --git a/src/test/unit/RewardsCoordinatorUnit.t.sol b/src/test/unit/RewardsCoordinatorUnit.t.sol index b01410426..0cd37b49e 100644 --- a/src/test/unit/RewardsCoordinatorUnit.t.sol +++ b/src/test/unit/RewardsCoordinatorUnit.t.sol @@ -38,7 +38,7 @@ contract RewardsCoordinatorUnitTests is EigenLayerUnitTestSetup, IRewardsCoordin IStrategy strategyMock3; StrategyBase strategyImplementation; uint256 mockTokenInitialSupply = 1e38 - 1; - IRewardsCoordinatorTypes.StrategyAndMultiplier[] defaultStrategyAndMultipliers; + StrategyAndMultiplier[] defaultStrategyAndMultipliers; // Config Variables /// @notice intervals(epochs) are 1 weeks @@ -173,13 +173,13 @@ contract RewardsCoordinatorUnitTests is EigenLayerUnitTestSetup, IRewardsCoordin strategyManagerMock.setStrategyWhitelist(strategies[2], true); defaultStrategyAndMultipliers.push( - IRewardsCoordinatorTypes.StrategyAndMultiplier(IStrategy(address(strategies[0])), 1e18) + StrategyAndMultiplier(IStrategy(address(strategies[0])), 1e18) ); defaultStrategyAndMultipliers.push( - IRewardsCoordinatorTypes.StrategyAndMultiplier(IStrategy(address(strategies[1])), 2e18) + StrategyAndMultiplier(IStrategy(address(strategies[1])), 2e18) ); defaultStrategyAndMultipliers.push( - IRewardsCoordinatorTypes.StrategyAndMultiplier(IStrategy(address(strategies[2])), 3e18) + StrategyAndMultiplier(IStrategy(address(strategies[2])), 3e18) ); rewardsCoordinator.setRewardsForAllSubmitter(rewardsForAllSubmitter, true); @@ -216,7 +216,7 @@ contract RewardsCoordinatorUnitTests is EigenLayerUnitTestSetup, IRewardsCoordin return timestamp1 > timestamp2 ? timestamp1 : timestamp2; } - function _assertRewardsClaimedEvents(bytes32 root, IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim, address recipient) internal { + function _assertRewardsClaimedEvents(bytes32 root, RewardsMerkleClaim memory claim, address recipient) internal { address earner = claim.earnerLeaf.earner; address claimer = rewardsCoordinator.claimerFor(earner); if (claimer == address(0)) { @@ -243,7 +243,7 @@ contract RewardsCoordinatorUnitTests is EigenLayerUnitTestSetup, IRewardsCoordin /// @notice given address and array of reward tokens, return array of cumulativeClaimed amonts function _getCumulativeClaimed( address earner, - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim + RewardsMerkleClaim memory claim ) internal view returns (uint256[] memory) { uint256[] memory totalClaimed = new uint256[](claim.tokenLeaves.length); @@ -256,7 +256,7 @@ contract RewardsCoordinatorUnitTests is EigenLayerUnitTestSetup, IRewardsCoordin /// @notice given a claim, return the new cumulativeEarnings for each token function _getCumulativeEarnings( - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim + RewardsMerkleClaim memory claim ) internal pure returns (uint256[] memory) { uint256[] memory earnings = new uint256[](claim.tokenLeaves.length); @@ -269,7 +269,7 @@ contract RewardsCoordinatorUnitTests is EigenLayerUnitTestSetup, IRewardsCoordin function _getClaimTokenBalances( address earner, - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim + RewardsMerkleClaim memory claim ) internal view returns (uint256[] memory) { uint256[] memory balances = new uint256[](claim.tokenLeaves.length); @@ -722,7 +722,7 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi rewardsCoordinator.pause(2 ** PAUSED_AVS_REWARDS_SUBMISSION); cheats.expectRevert(IPausable.CurrentlyPaused.selector); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions; + RewardsSubmission[] memory rewardsSubmissions; rewardsCoordinator.createAVSRewardsSubmission(defaultAVS, rewardsSubmissions); } @@ -738,8 +738,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi _deployMockRewardTokens(address(this), 1); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: IERC20(address(reenterer)), amount: amount, @@ -782,9 +782,9 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory emptyStratsAndMultipliers; - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + StrategyAndMultiplier[] memory emptyStratsAndMultipliers; + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: emptyStratsAndMultipliers, token: rewardToken, amount: amount, @@ -820,8 +820,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -856,12 +856,12 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - IRewardsCoordinatorTypes.StrategyAndMultiplier[] - memory dupStratsAndMultipliers = new IRewardsCoordinatorTypes.StrategyAndMultiplier[](2); + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + StrategyAndMultiplier[] + memory dupStratsAndMultipliers = new StrategyAndMultiplier[](2); dupStratsAndMultipliers[0] = defaultStrategyAndMultipliers[0]; dupStratsAndMultipliers[1] = defaultStrategyAndMultipliers[0]; - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: dupStratsAndMultipliers, token: rewardToken, amount: amount, @@ -899,8 +899,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -939,8 +939,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -983,8 +983,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -1021,8 +1021,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -1061,9 +1061,9 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); defaultStrategyAndMultipliers[0].strategy = IStrategy(address(999)); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -1108,8 +1108,8 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -1163,7 +1163,7 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi cheats.assume(param.avs != address(0)); cheats.prank(rewardsCoordinator.owner()); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](numSubmissions); + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](numSubmissions); bytes32[] memory rewardsSubmissionHashes = new bytes32[](numSubmissions); uint256 startSubmissionNonce = rewardsCoordinator.submissionNonce(param.avs); _deployMockRewardTokens(param.avs, numSubmissions); @@ -1192,7 +1192,7 @@ contract RewardsCoordinatorUnitTests_createAVSRewardsSubmission is RewardsCoordi param.startTimestamp = param.startTimestamp - (param.startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission memory rewardsSubmission = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission memory rewardsSubmission = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardTokens[i], amount: amounts[i], @@ -1251,7 +1251,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllSubmission is RewardsCoo rewardsCoordinator.pause(2 ** PAUSED_REWARDS_FOR_ALL_SUBMISSION); cheats.expectRevert(IPausable.CurrentlyPaused.selector); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions; + RewardsSubmission[] memory rewardsSubmissions; rewardsCoordinator.createRewardsForAllSubmission(rewardsSubmissions); } @@ -1266,8 +1266,8 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllSubmission is RewardsCoo _deployMockRewardTokens(address(this), 1); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: IERC20(address(reenterer)), amount: amount, @@ -1292,7 +1292,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllSubmission is RewardsCoo cheats.assume(invalidSubmitter != rewardsForAllSubmitter); cheats.expectRevert(IRewardsCoordinatorErrors.UnauthorizedCaller.selector); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions; + RewardsSubmission[] memory rewardsSubmissions; rewardsCoordinator.createRewardsForAllSubmission(rewardsSubmissions); } @@ -1330,8 +1330,8 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllSubmission is RewardsCoo startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -1395,7 +1395,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllSubmission is RewardsCoo cheats.assume(2 <= numSubmissions && numSubmissions <= 10); cheats.prank(rewardsCoordinator.owner()); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](numSubmissions); + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](numSubmissions); bytes32[] memory rewardsSubmissionHashes = new bytes32[](numSubmissions); uint256 startSubmissionNonce = rewardsCoordinator.submissionNonce(rewardsForAllSubmitter); _deployMockRewardTokens(rewardsForAllSubmitter, numSubmissions); @@ -1424,7 +1424,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllSubmission is RewardsCoo param.startTimestamp = param.startTimestamp - (param.startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission memory rewardsSubmission = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission memory rewardsSubmission = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardTokens[i], amount: amounts[i], @@ -1483,7 +1483,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllEarners is RewardsCoordi rewardsCoordinator.pause(2 ** PAUSED_REWARD_ALL_STAKERS_AND_OPERATORS); cheats.expectRevert(IPausable.CurrentlyPaused.selector); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions; + RewardsSubmission[] memory rewardsSubmissions; rewardsCoordinator.createRewardsForAllEarners(rewardsSubmissions); } @@ -1498,8 +1498,8 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllEarners is RewardsCoordi _deployMockRewardTokens(address(this), 1); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: IERC20(address(reenterer)), amount: amount, @@ -1524,7 +1524,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllEarners is RewardsCoordi cheats.assume(invalidSubmitter != rewardsForAllSubmitter); cheats.expectRevert(IRewardsCoordinatorErrors.UnauthorizedCaller.selector); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions; + RewardsSubmission[] memory rewardsSubmissions; rewardsCoordinator.createRewardsForAllEarners(rewardsSubmissions); } @@ -1562,8 +1562,8 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllEarners is RewardsCoordi startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](1); - rewardsSubmissions[0] = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](1); + rewardsSubmissions[0] = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, amount: amount, @@ -1627,7 +1627,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllEarners is RewardsCoordi cheats.assume(2 <= numSubmissions && numSubmissions <= 10); cheats.prank(rewardsCoordinator.owner()); - IRewardsCoordinatorTypes.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinatorTypes.RewardsSubmission[](numSubmissions); + RewardsSubmission[] memory rewardsSubmissions = new RewardsSubmission[](numSubmissions); bytes32[] memory rewardsSubmissionHashes = new bytes32[](numSubmissions); uint256 startSubmissionNonce = rewardsCoordinator.submissionNonce(rewardsForAllSubmitter); _deployMockRewardTokens(rewardsForAllSubmitter, numSubmissions); @@ -1656,7 +1656,7 @@ contract RewardsCoordinatorUnitTests_createRewardsForAllEarners is RewardsCoordi param.startTimestamp = param.startTimestamp - (param.startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.RewardsSubmission memory rewardsSubmission = IRewardsCoordinatorTypes.RewardsSubmission({ + RewardsSubmission memory rewardsSubmission = RewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardTokens[i], amount: amounts[i], @@ -1719,7 +1719,7 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission uint256 duration; } - IRewardsCoordinatorTypes.OperatorReward[] defaultOperatorRewards; + OperatorReward[] defaultOperatorRewards; function setUp() public virtual override { RewardsCoordinatorUnitTests.setUp(); @@ -1730,9 +1730,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission operators[2] = makeAddr("operator3"); operators = _sortAddressArrayAsc(operators); - defaultOperatorRewards.push(IRewardsCoordinatorTypes.OperatorReward(operators[0], 1e18)); - defaultOperatorRewards.push(IRewardsCoordinatorTypes.OperatorReward(operators[1], 2e18)); - defaultOperatorRewards.push(IRewardsCoordinatorTypes.OperatorReward(operators[2], 3e18)); + defaultOperatorRewards.push(OperatorReward(operators[0], 1e18)); + defaultOperatorRewards.push(OperatorReward(operators[1], 2e18)); + defaultOperatorRewards.push(OperatorReward(operators[2], 3e18)); // Set the timestamp to when Rewards v2 will realisticly go out (i.e 6 months) cheats.warp(GENESIS_REWARDS_TIMESTAMP + 168 days); @@ -1754,7 +1754,7 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission } function _getTotalRewardsAmount( - IRewardsCoordinatorTypes.OperatorReward[] memory operatorRewards + OperatorReward[] memory operatorRewards ) internal pure returns (uint256) { uint256 totalAmount = 0; for (uint256 i = 0; i < operatorRewards.length; ++i) { @@ -1769,7 +1769,7 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission rewardsCoordinator.pause(2 ** PAUSED_OPERATOR_DIRECTED_AVS_REWARDS_SUBMISSION); cheats.expectRevert(IPausable.CurrentlyPaused.selector); - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] memory operatorDirectedRewardsSubmissions; + OperatorDirectedRewardsSubmission[] memory operatorDirectedRewardsSubmissions; rewardsCoordinator.createOperatorDirectedAVSRewardsSubmission( address(this), operatorDirectedRewardsSubmissions @@ -1794,9 +1794,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission Reenterer reenterer = new Reenterer(); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: IERC20(address(reenterer)), operatorRewards: defaultOperatorRewards, @@ -1845,9 +1845,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -1884,10 +1884,10 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory emptyStratsAndMultipliers; - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + StrategyAndMultiplier[] memory emptyStratsAndMultipliers; + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: emptyStratsAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -1925,10 +1925,10 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - IRewardsCoordinatorTypes.OperatorReward[] memory emptyOperatorRewards; - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + OperatorReward[] memory emptyOperatorRewards; + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: emptyOperatorRewards, @@ -1966,10 +1966,10 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); defaultOperatorRewards[0].operator = address(0); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2007,12 +2007,12 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - IRewardsCoordinatorTypes.OperatorReward[] memory dupOperatorRewards = new IRewardsCoordinatorTypes.OperatorReward[](2); + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + OperatorReward[] memory dupOperatorRewards = new OperatorReward[](2); dupOperatorRewards[0] = defaultOperatorRewards[0]; dupOperatorRewards[1] = defaultOperatorRewards[0]; - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: dupOperatorRewards, @@ -2050,10 +2050,10 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); defaultOperatorRewards[0].amount = 0; - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2093,10 +2093,10 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); defaultOperatorRewards[0].amount = amount; - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2133,9 +2133,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2173,9 +2173,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2213,9 +2213,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission cheats.assume(startTimestamp % CALCULATION_INTERVAL_SECONDS != 0); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2249,9 +2249,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2287,9 +2287,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2327,10 +2327,10 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); defaultStrategyAndMultipliers[0].strategy = IStrategy(address(999)); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2368,13 +2368,13 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - IRewardsCoordinatorTypes.StrategyAndMultiplier[] - memory dupStratsAndMultipliers = new IRewardsCoordinatorTypes.StrategyAndMultiplier[](2); + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + StrategyAndMultiplier[] + memory dupStratsAndMultipliers = new StrategyAndMultiplier[](2); dupStratsAndMultipliers[0] = defaultStrategyAndMultipliers[0]; dupStratsAndMultipliers[1] = defaultStrategyAndMultipliers[0]; - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: dupStratsAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2418,9 +2418,9 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission startTimestamp = startTimestamp - (startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create operator directed rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory operatorDirectedRewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - operatorDirectedRewardsSubmissions[0] = IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + OperatorDirectedRewardsSubmission[] + memory operatorDirectedRewardsSubmissions = new OperatorDirectedRewardsSubmission[](1); + operatorDirectedRewardsSubmissions[0] = OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardToken, operatorRewards: defaultOperatorRewards, @@ -2483,8 +2483,8 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission cheats.assume(param.avs != address(0)); cheats.prank(rewardsCoordinator.owner()); - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] - memory rewardsSubmissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](numSubmissions); + OperatorDirectedRewardsSubmission[] + memory rewardsSubmissions = new OperatorDirectedRewardsSubmission[](numSubmissions); bytes32[] memory rewardsSubmissionHashes = new bytes32[](numSubmissions); uint256 startSubmissionNonce = rewardsCoordinator.submissionNonce(param.avs); _deployMockRewardTokens(param.avs, numSubmissions); @@ -2523,7 +2523,7 @@ contract RewardsCoordinatorUnitTests_createOperatorDirectedAVSRewardsSubmission param.startTimestamp = param.startTimestamp - (param.startTimestamp % CALCULATION_INTERVAL_SECONDS); // 2. Create rewards submission input param - IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory rewardsSubmission = IRewardsCoordinatorTypes + OperatorDirectedRewardsSubmission memory rewardsSubmission = IRewardsCoordinatorTypes .OperatorDirectedRewardsSubmission({ strategiesAndMultipliers: defaultStrategyAndMultipliers, token: rewardTokens[i], @@ -2710,8 +2710,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinator.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinator.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -2764,8 +2764,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -2815,8 +2815,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[0]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[0]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -2866,8 +2866,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[0]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[0]; // 1. Claim against first root { @@ -2997,7 +2997,7 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests cheats.startPrank(claimer); // rootIndex in claim is 0, which is disabled - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim; + RewardsMerkleClaim memory claim; cheats.expectRevert(IRewardsCoordinatorErrors.RootDisabled.selector); rewardsCoordinator.processClaim(claim, claimer); cheats.stopPrank(); @@ -3020,8 +3020,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[0]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[0]; // 1. Claim against first root { @@ -3091,8 +3091,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -3134,8 +3134,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -3175,8 +3175,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -3218,8 +3218,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -3258,8 +3258,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofs(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[2]; + RewardsMerkleClaim[] memory claims = _parseAllProofs(); + RewardsMerkleClaim memory claim = claims[2]; uint32 rootIndex = claim.rootIndex; IRewardsCoordinator.DistributionRoot memory distributionRoot = rewardsCoordinator.getDistributionRootAtIndex( @@ -3298,8 +3298,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofsMaxEarnerAndLeafIndices(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[0]; + RewardsMerkleClaim[] memory claims = _parseAllProofsMaxEarnerAndLeafIndices(); + RewardsMerkleClaim memory claim = claims[0]; // 1. Claim against first root where earner tree is full tree and earner and token index is last index of that tree height { @@ -3364,8 +3364,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofsSingleTokenLeaf(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[0]; + RewardsMerkleClaim[] memory claims = _parseAllProofsSingleTokenLeaf(); + RewardsMerkleClaim memory claim = claims[0]; // 1. Claim against first root where earner tree is full tree and earner and token index is last index of that tree height { @@ -3422,8 +3422,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } // Parse all 3 claim proofs for distributionRoots 0,1,2 respectively - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = _parseAllProofsSingleEarnerLeaf(); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory claim = claims[0]; + RewardsMerkleClaim[] memory claims = _parseAllProofsSingleEarnerLeaf(); + RewardsMerkleClaim memory claim = claims[0]; // 1. Claim against first root where earner tree is full tree and earner and token index is last index of that tree height { @@ -3469,7 +3469,7 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests } /// @notice parse proofs from json file and submitRoot() - function _parseProofData(string memory filePath) internal returns (IRewardsCoordinatorTypes.RewardsMerkleClaim memory) { + function _parseProofData(string memory filePath) internal returns (RewardsMerkleClaim memory) { cheats.readFile(filePath); string memory claimProofData = cheats.readFile(filePath); @@ -3484,7 +3484,7 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests uint256 numTokenLeaves = stdJson.readUint(claimProofData, ".TokenLeavesNum"); uint256 numTokenTreeProofs = stdJson.readUint(claimProofData, ".TokenTreeProofsNum"); - IRewardsCoordinatorTypes.TokenTreeMerkleLeaf[] memory tokenLeaves = new IRewardsCoordinatorTypes.TokenTreeMerkleLeaf[]( + TokenTreeMerkleLeaf[] memory tokenLeaves = new TokenTreeMerkleLeaf[]( numTokenLeaves ); uint32[] memory tokenIndices = new uint32[](numTokenLeaves); @@ -3495,7 +3495,7 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests IERC20 token = IERC20(stdJson.readAddress(claimProofData, tokenKey)); uint256 cumulativeEarnings = stdJson.readUint(claimProofData, amountKey); - tokenLeaves[i] = IRewardsCoordinatorTypes.TokenTreeMerkleLeaf({ + tokenLeaves[i] = TokenTreeMerkleLeaf({ token: token, cumulativeEarnings: cumulativeEarnings }); @@ -3521,11 +3521,11 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests cheats.prank(rewardsUpdater); rewardsCoordinator.submitRoot(merkleRoot, prevRootCalculationEndTimestamp); - IRewardsCoordinatorTypes.RewardsMerkleClaim memory newClaim = IRewardsCoordinatorTypes.RewardsMerkleClaim({ + RewardsMerkleClaim memory newClaim = RewardsMerkleClaim({ rootIndex: rootIndex, earnerIndex: earnerIndex, earnerTreeProof: earnerTreeProof, - earnerLeaf: IRewardsCoordinatorTypes.EarnerTreeMerkleLeaf({earner: earner, earnerTokenRoot: earnerTokenRoot}), + earnerLeaf: EarnerTreeMerkleLeaf({earner: earner, earnerTokenRoot: earnerTokenRoot}), tokenIndices: tokenIndices, tokenTreeProofs: tokenTreeProofs, tokenLeaves: tokenLeaves @@ -3534,8 +3534,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests return newClaim; } - function _parseAllProofs() internal virtual returns (IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory) { - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = new IRewardsCoordinatorTypes.RewardsMerkleClaim[](3); + function _parseAllProofs() internal virtual returns (RewardsMerkleClaim[] memory) { + RewardsMerkleClaim[] memory claims = new RewardsMerkleClaim[](3); claims[0] = _parseProofData("src/test/test-data/rewardsCoordinator/processClaimProofs_Root1.json"); claims[1] = _parseProofData("src/test/test-data/rewardsCoordinator/processClaimProofs_Root2.json"); @@ -3544,8 +3544,8 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests return claims; } - function _parseAllProofsMaxEarnerAndLeafIndices() internal virtual returns (IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory) { - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = new IRewardsCoordinatorTypes.RewardsMerkleClaim[](1); + function _parseAllProofsMaxEarnerAndLeafIndices() internal virtual returns (RewardsMerkleClaim[] memory) { + RewardsMerkleClaim[] memory claims = new RewardsMerkleClaim[](1); claims[0] = _parseProofData( "src/test/test-data/rewardsCoordinator/processClaimProofs_MaxEarnerAndLeafIndices.json" @@ -3554,16 +3554,16 @@ contract RewardsCoordinatorUnitTests_processClaim is RewardsCoordinatorUnitTests return claims; } - function _parseAllProofsSingleTokenLeaf() internal virtual returns (IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory) { - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = new IRewardsCoordinatorTypes.RewardsMerkleClaim[](1); + function _parseAllProofsSingleTokenLeaf() internal virtual returns (RewardsMerkleClaim[] memory) { + RewardsMerkleClaim[] memory claims = new RewardsMerkleClaim[](1); claims[0] = _parseProofData("src/test/test-data/rewardsCoordinator/processClaimProofs_SingleTokenLeaf.json"); return claims; } - function _parseAllProofsSingleEarnerLeaf() internal virtual returns (IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory) { - IRewardsCoordinatorTypes.RewardsMerkleClaim[] memory claims = new IRewardsCoordinatorTypes.RewardsMerkleClaim[](1); + function _parseAllProofsSingleEarnerLeaf() internal virtual returns (RewardsMerkleClaim[] memory) { + RewardsMerkleClaim[] memory claims = new RewardsMerkleClaim[](1); claims[0] = _parseProofData("src/test/test-data/rewardsCoordinator/processClaimProofs_SingleEarnerLeaf.json");