Skip to content

Commit f939ead

Browse files
committed
test: roundup slashed magnitudes
1 parent f04556a commit f939ead

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

src/test/unit/AllocationManagerUnit.t.sol

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,130 @@ contract AllocationManagerUnitTests_SlashOperator is AllocationManagerUnitTests
767767
assertEq(0, mInfos[0].effectTimestamp, "effectTimestamp should be 0");
768768
}
769769

770+
/**
771+
* Allocates 100% magnitude for a single strategy to an operatorSet.
772+
* First slashes 99% from the operatorSet, slashes 99.99% a second time, and on the third slash, slashes
773+
* 99.9999999999999% which should get rounded up to 100% or 1e18 wadSlashed leaving the operator with no magnitude
774+
* in the operatorSet, 0 encumbered magnitude, and 0 max magnitude.
775+
*
776+
* Asserts that:
777+
* 1. Events are emitted
778+
* 2. Encumbered mag is updated
779+
* 3. Max mag is updated
780+
* 4. Calculations for `getAllocatableMagnitude` and `getAllocationInfo` are correct
781+
* 5. Slashed amounts are rounded up to ensure magnitude is always slashed
782+
*/
783+
function test_slashTwoOperatorSets() public {
784+
// Generate allocation for `strategyMock`, we allocate 100% to opSet 0
785+
IAllocationManagerTypes.MagnitudeAllocation[] memory allocations = _generateMagnitudeAllocationCalldataForOpSet({
786+
avsToSet: defaultAVS,
787+
operatorSetId: 0,
788+
magnitudeToSet: 1e18,
789+
expectedMaxMagnitude: 1e18
790+
});
791+
792+
cheats.prank(defaultOperator);
793+
allocationManager.modifyAllocations(allocations);
794+
cheats.warp(block.timestamp + DEFAULT_OPERATOR_ALLOCATION_DELAY);
795+
796+
// 1. Slash operator for 99% in opSet 0 bringing their magnitude to 1e16
797+
SlashingParams memory slashingParams = SlashingParams({
798+
operator: defaultOperator,
799+
operatorSetId: allocations[0].operatorSets[0].operatorSetId,
800+
strategies: _strategyMockArray(),
801+
wadToSlash: 99e16,
802+
description: "test"
803+
});
804+
avsDirectoryMock.setIsOperatorSlashable(slashingParams.operator, defaultAVS, slashingParams.operatorSetId, true);
805+
uint64 expectedEncumberedMagnitude = 1e16; // After slashing 99%, only 1% expected encumberedMagnitude
806+
uint64 magnitudeAfterSlash = 1e16;
807+
uint64 maxMagnitudeAfterSlash = 1e16; // 1e15 is maxMagnitude
808+
uint256[] memory wadSlashed = new uint256[](1);
809+
wadSlashed[0] = 99e16;
810+
811+
// Slash Operator
812+
cheats.expectEmit(true, true, true, true, address(allocationManager));
813+
emit EncumberedMagnitudeUpdated(defaultOperator, strategyMock, expectedEncumberedMagnitude);
814+
cheats.expectEmit(true, true, true, true, address(allocationManager));
815+
emit OperatorSetMagnitudeUpdated(defaultOperator, allocations[0].operatorSets[0], strategyMock, magnitudeAfterSlash, uint32(block.timestamp));
816+
cheats.expectEmit(true, true, true, true, address(allocationManager));
817+
emit MaxMagnitudeUpdated(defaultOperator, strategyMock, maxMagnitudeAfterSlash);
818+
cheats.expectEmit(true, true, true, true, address(allocationManager));
819+
emit OperatorSlashed(slashingParams.operator, _operatorSet(defaultAVS, slashingParams.operatorSetId), slashingParams.strategies, wadSlashed, slashingParams.description);
820+
cheats.prank(defaultAVS);
821+
allocationManager.slashOperator(slashingParams);
822+
823+
// Check storage
824+
assertEq(expectedEncumberedMagnitude, allocationManager.encumberedMagnitude(defaultOperator, strategyMock), "encumberedMagnitude not updated");
825+
assertEq(maxMagnitudeAfterSlash, allocationManager.getMaxMagnitudes(defaultOperator, _strategyMockArray())[0], "maxMagnitude not updated");
826+
MagnitudeInfo[] memory mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, allocations[0].operatorSets);
827+
assertEq(magnitudeAfterSlash, mInfos[0].currentMagnitude, "currentMagnitude not updated");
828+
829+
// 2. Slash operator again for 99.99% in opSet 0 bringing their magnitude to 1e14
830+
slashingParams = SlashingParams({
831+
operator: defaultOperator,
832+
operatorSetId: allocations[0].operatorSets[0].operatorSetId,
833+
strategies: _strategyMockArray(),
834+
wadToSlash: 9999e14,
835+
description: "test"
836+
});
837+
expectedEncumberedMagnitude = 1e12; // After slashing 99.99%, only 0.01% expected encumberedMagnitude
838+
magnitudeAfterSlash = 1e12;
839+
maxMagnitudeAfterSlash = 1e12;
840+
wadSlashed[0] = 9999e14;
841+
842+
cheats.expectEmit(true, true, true, true, address(allocationManager));
843+
emit EncumberedMagnitudeUpdated(defaultOperator, strategyMock, expectedEncumberedMagnitude);
844+
cheats.expectEmit(true, true, true, true, address(allocationManager));
845+
emit OperatorSetMagnitudeUpdated(defaultOperator, allocations[0].operatorSets[0], strategyMock, magnitudeAfterSlash, uint32(block.timestamp));
846+
cheats.expectEmit(true, true, true, true, address(allocationManager));
847+
emit MaxMagnitudeUpdated(defaultOperator, strategyMock, maxMagnitudeAfterSlash);
848+
cheats.expectEmit(true, true, true, true, address(allocationManager));
849+
emit OperatorSlashed(slashingParams.operator, _operatorSet(defaultAVS, slashingParams.operatorSetId), slashingParams.strategies, wadSlashed, slashingParams.description);
850+
cheats.prank(defaultAVS);
851+
allocationManager.slashOperator(slashingParams);
852+
853+
// Check storage
854+
assertEq(expectedEncumberedMagnitude, allocationManager.encumberedMagnitude(defaultOperator, strategyMock), "encumberedMagnitude not updated");
855+
assertEq(maxMagnitudeAfterSlash, allocationManager.getMaxMagnitudes(defaultOperator, _strategyMockArray())[0], "maxMagnitude not updated");
856+
mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, allocations[0].operatorSets);
857+
assertEq(magnitudeAfterSlash, mInfos[0].currentMagnitude, "currentMagnitude not updated");
858+
859+
// 3. Slash operator again for 99.9999999999999% in opSet 0
860+
slashingParams = SlashingParams({
861+
operator: defaultOperator,
862+
operatorSetId: allocations[0].operatorSets[0].operatorSetId,
863+
strategies: _strategyMockArray(),
864+
wadToSlash: 1e18 - 1e3,
865+
description: "test"
866+
});
867+
// Should technically be 1e3 remaining but with rounding error and rounding up slashed amounts
868+
// the remaining magnitude is 0
869+
expectedEncumberedMagnitude = 0; // Should technically be 1e3 remaining but with rounding error and rounding up slashed amounts.
870+
magnitudeAfterSlash = 0;
871+
maxMagnitudeAfterSlash = 0;
872+
// wadSlashed is rounded up from the 1e18 - 1e3 amount
873+
wadSlashed[0] = 1e18;
874+
875+
// Slash Operator
876+
cheats.expectEmit(true, true, true, true, address(allocationManager));
877+
emit EncumberedMagnitudeUpdated(defaultOperator, strategyMock, expectedEncumberedMagnitude);
878+
cheats.expectEmit(true, true, true, true, address(allocationManager));
879+
emit OperatorSetMagnitudeUpdated(defaultOperator, allocations[0].operatorSets[0], strategyMock, magnitudeAfterSlash, uint32(block.timestamp));
880+
cheats.expectEmit(true, true, true, true, address(allocationManager));
881+
emit MaxMagnitudeUpdated(defaultOperator, strategyMock, maxMagnitudeAfterSlash);
882+
cheats.expectEmit(true, true, true, true, address(allocationManager));
883+
emit OperatorSlashed(slashingParams.operator, _operatorSet(defaultAVS, slashingParams.operatorSetId), slashingParams.strategies, wadSlashed, slashingParams.description);
884+
cheats.prank(defaultAVS);
885+
allocationManager.slashOperator(slashingParams);
886+
887+
// Check storage
888+
assertEq(expectedEncumberedMagnitude, allocationManager.encumberedMagnitude(defaultOperator, strategyMock), "encumberedMagnitude not updated");
889+
assertEq(maxMagnitudeAfterSlash, allocationManager.getMaxMagnitudes(defaultOperator, _strategyMockArray())[0], "maxMagnitude not updated");
890+
mInfos = allocationManager.getAllocationInfo(defaultOperator, strategyMock, allocations[0].operatorSets);
891+
assertEq(magnitudeAfterSlash, mInfos[0].currentMagnitude, "currentMagnitude not updated");
892+
}
893+
770894
/**
771895
* Allocates all of magnitude to a single strategy to an operatorSet. Deallocate half. Finally, slash while deallocation is pending
772896
* Asserts that:

0 commit comments

Comments
 (0)