diff --git a/src/test/unit/AllocationManagerUnit.t.sol b/src/test/unit/AllocationManagerUnit.t.sol index 473a02a3c..9fb74a17c 100644 --- a/src/test/unit/AllocationManagerUnit.t.sol +++ b/src/test/unit/AllocationManagerUnit.t.sol @@ -1569,7 +1569,7 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe * Allocates to `firstMod` magnitude and then deallocate to `secondMod` magnitude * Validates the storage * - 1. After deallocation is alled - * - 2. After the deallocationd elay is hit + * - 2. After the deallocationd delay is hit * - 3. After the modification queue is cleared */ function testFuzz_allocate_deallocate(uint256 r) public { @@ -1875,6 +1875,119 @@ contract AllocationManagerUnitTests_ClearModificationQueue is AllocationManagerU assertEq(0, mInfos[0].pendingDiff, "pendingMagnitude should be 0"); assertEq(0, mInfos[0].effectTimestamp, "effectTimestamp should be 0"); } + + /** + * Allocates, deallocates, and then allocates again. Asserts that + * - The deallocation does not block state updates from the second allocation, even though the allocation has an earlier + * effect timestamp, but is on the queue before + */ + function test_allocate_deallocate_allocate() public { + uint32 allocationDelay = 15 days; + // Set allocation delay to be 15 days + cheats.prank(defaultOperator); + allocationManager.setAllocationDelay(allocationDelay); + cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY); + (,uint32 storedDelay) = allocationManager.getAllocationDelay(defaultOperator); + assertEq(allocationDelay, storedDelay, "allocation delay not valid"); + + // Allocate half of mag to opset1 + IAllocationManagerTypes.MagnitudeAllocation[] memory firstAllocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 1, 5e17, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(firstAllocation); + cheats.warp(block.timestamp + 15 days); + + // Deallocate half from opset1. + uint32 t = uint32(block.timestamp); + uint32 deallocationEffectTimestamp = uint32(block.timestamp + DEALLOCATION_DELAY); + IAllocationManagerTypes.MagnitudeAllocation[] memory firstDeallocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 1, 25e16, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(firstDeallocation); + MagnitudeInfo[] memory mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, firstDeallocation[0].operatorSets); + assertEq(deallocationEffectTimestamp, mInfos[0].effectTimestamp, "effect timestamp not correct"); + + // Allocate 33e16 mag to opset2 + uint32 allocationEffectTimestamp = uint32(block.timestamp + allocationDelay); + IAllocationManagerTypes.MagnitudeAllocation[] memory secondAllocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 2, 33e16, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(secondAllocation); + mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, secondAllocation[0].operatorSets); + console.log("deallocation effect timestamp: ", deallocationEffectTimestamp); + console.log("allocation effect timestamp: ", allocationEffectTimestamp); + assertEq(allocationEffectTimestamp, mInfos[0].effectTimestamp, "effect timestamp not correct"); + assertLt(allocationEffectTimestamp, deallocationEffectTimestamp, "invalid test setup"); + + // Warp to allocation effect timestamp & clear the queue + cheats.warp(allocationEffectTimestamp); + allocationManager.clearModificationQueue(defaultOperator, _strategyMockArray(), _maxNumToClear()); + + // Validate `getAllocatableMagnitude`. Allocatable magnitude should be the difference between the total magnitude and the encumbered magnitude + uint64 allocatableMagnitude = allocationManager.getAllocatableMagnitude(defaultOperator, strategyMock); + assertEq(WAD - 33e16 - 5e17, allocatableMagnitude, "allocatableMagnitude not correct"); + + // Validate that we can allocate again for opset2. This should not revert + IAllocationManagerTypes.MagnitudeAllocation[] memory thirdAllocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 2, 10e16, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(thirdAllocation); + } + + /** + * Allocates to opset1, allocates to opset2, deallocates from opset1. Asserts that the allocation, which has a higher + * effect timestamp is not blocking the deallocation. + * The queue looks like (note that the first allocation has been completed): + * 1. (allocation, opSet2, mag: 5e17, effectTimestamp: 50th day) + * 2. (deallocation, opSet1, mag: 0, effectTimestamp: 42.5 day) + */ + function test_regression_allocationBlocksDeallocation() public { + uint32 allocationDelay = 25 days; + // Set allocation delay to be 25 days, greater than the deallocation timestamp + cheats.prank(defaultOperator); + allocationManager.setAllocationDelay(allocationDelay); + cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY); + (,uint32 storedDelay) = allocationManager.getAllocationDelay(defaultOperator); + assertEq(allocationDelay, storedDelay, "allocation delay not valid"); + + // Allocate half of mag to opset1 + IAllocationManagerTypes.MagnitudeAllocation[] memory firstAllocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 1, 5e17, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(firstAllocation); + cheats.warp(block.timestamp + 25 days); + + // Allocate half of mag to opset2 + IAllocationManagerTypes.MagnitudeAllocation[] memory secondAllocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 2, 5e17, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(secondAllocation); + + uint32 allocationEffectTimestamp = uint32(block.timestamp + allocationDelay); + MagnitudeInfo[] memory mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, secondAllocation[0].operatorSets); + assertEq(allocationEffectTimestamp, mInfos[0].effectTimestamp, "effect timestamp not correct"); + + // Deallocate all from opSet1 + uint32 deallocationEffectTimestamp = uint32(block.timestamp + DEALLOCATION_DELAY); + IAllocationManagerTypes.MagnitudeAllocation[] memory firstDeallocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 1, 0, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(firstDeallocation); + mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, firstDeallocation[0].operatorSets); + assertEq(deallocationEffectTimestamp, mInfos[0].effectTimestamp, "effect timestamp not correct"); + assertLt(deallocationEffectTimestamp, allocationEffectTimestamp, "invalid test setup"); + + // Warp to deallocation effect timestamp & clear the queue + cheats.warp(deallocationEffectTimestamp); + allocationManager.clearModificationQueue(defaultOperator, _strategyMockArray(), _maxNumToClear()); + + // At this point, we should be able to allocate again to opSet1 AND have only 5e17 encumbered magnitude + assertEq(5e17, allocationManager.encumberedMagnitude(defaultOperator, strategyMock), "encumbered magnitude not correct"); + IAllocationManagerTypes.MagnitudeAllocation[] memory thirdAllocation = + _generateMagnitudeAllocationCalldataForOpSet(defaultAVS, 1, 5e17, 1e18); + cheats.prank(defaultOperator); + allocationManager.modifyAllocations(thirdAllocation); + } } contract AllocationManagerUnitTests_SetAllocationDelay is AllocationManagerUnitTests {