Skip to content

Commit

Permalink
slashing: allocation delay happy path tests (#822)
Browse files Browse the repository at this point in the history
  • Loading branch information
ypatil12 authored Oct 15, 2024
1 parent e45a6ad commit 06e852f
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 55 deletions.
2 changes: 2 additions & 0 deletions src/contracts/core/AllocationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ contract AllocationManager is
* @param delay The allocation delay in seconds.
*/
function _setAllocationDelay(address operator, uint32 delay) internal {
require(delay != 0, InvalidAllocationDelay());

AllocationDelayInfo memory info = _allocationDelayInfo[operator];

if (info.pendingDelay != 0 && block.timestamp >= info.effectTimestamp) {
Expand Down
2 changes: 2 additions & 0 deletions src/contracts/interfaces/IAllocationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ interface IAllocationManagerErrors {
error AlreadySlashedForTimestamp();
/// @dev Thrown when calling a view function that requires a valid timestamp.
error InvalidTimestamp();
/// @dev Thrown when an invalid allocation delay is set
error InvalidAllocationDelay();
}

interface IAllocationManagerTypes {
Expand Down
174 changes: 119 additions & 55 deletions src/test/unit/AllocationManagerUnit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ contract AllocationManagerUnitTests_ModifyAllocations is AllocationManagerUnitTe
}
}

function test_fuzz_allocateMultipleTimes(uint64 firstAlloc, uint64 secondAlloc) public {
function testFuzz_allocateMultipleTimes(uint64 firstAlloc, uint64 secondAlloc) public {
// Assumptions
cheats.assume(firstAlloc > 0);
cheats.assume(firstAlloc < secondAlloc);
Expand Down Expand Up @@ -810,61 +810,125 @@ contract AllocationManagerUnitTests_SetAllocationDelay is AllocationManagerUnitT
/// setAllocationDelay() + getAllocationDelay()
/// -----------------------------------------------------------------------

/// @dev Asserts the following:
/// Calling as the operator:
/// 1. Fn can only be called by registed operators..
/// 2. Fn emits `AllocationDelaySet` event.
/// 3. Fn properly mutates storage such that getAllocationDelay returns the correct value.
/// Calling as the DM:
/// 2. Only the DM can set allocation delay.
/// 3. Fn emits `AllocationDelaySet` event.
/// 4. Fn properly mutates storage such that getAllocationDelay returns the correct value.
function testFuzz_allocationDelay_Checks(uint256 r) public {
// Mock random operator address and delay.
address operator = _randomAddr(r, 0);
uint32 expectedDelay = uint32(bound(r, 1, type(uint32).max));
uint32 effectTimestamp = uint32(block.timestamp + ALLOCATION_CONFIGURATION_DELAY);

// If r is even, pretend to be the operator, else pretend to be the DM.
if (r % 2 == 0) {
// Assert unregister operator cannot set allocation delay.
cheats.prank(operator);
cheats.expectRevert(IAllocationManagerErrors.OperatorNotRegistered.selector);
allocationManager.setAllocationDelay(expectedDelay);

// Mock operator being registered.
delegationManagerMock.setIsOperator(operator, true);

// Assert `AllocationDelaySet` event is emitted.
cheats.expectEmit(true, false, false, false);
emit AllocationDelaySet(operator, expectedDelay, effectTimestamp);

// Set the allocation delay as the operator.
cheats.prank(operator);
allocationManager.setAllocationDelay(expectedDelay);
} else {
// Assert only the DM can set allocation delay.
cheats.expectRevert(IAllocationManagerErrors.OnlyDelegationManager.selector);
allocationManager.setAllocationDelay(operator, expectedDelay);

// Assert `AllocationDelaySet` event is emitted.
cheats.expectEmit(true, false, false, false);
emit AllocationDelaySet(operator, expectedDelay, effectTimestamp);

// Set the allocation delay as the DM.
cheats.prank(address(delegationManagerMock));
allocationManager.setAllocationDelay(operator, expectedDelay);
}
address operatorToSet = address(0x1);

// Assert that the delay does not change until the allocation config delay has elapsed.
(bool isSet, uint32 delay) = allocationManager.getAllocationDelay(operator);
assertEq(delay, 0);
assertTrue(!isSet);
function setUp() public override {
AllocationManagerUnitTests.setUp();

// Assert that the delay does not change until the allocation config delay has elapsed.
cheats.warp(effectTimestamp);
(isSet, delay) = allocationManager.getAllocationDelay(operator);
assertEq(delay, expectedDelay);
assertTrue(isSet);
// Register operator
delegationManagerMock.setIsOperator(operatorToSet, true);
}

function test_revert_callerNotOperator() public {
// Deregister operator
delegationManagerMock.setIsOperator(operatorToSet, false);
cheats.prank(operatorToSet);
cheats.expectRevert(IAllocationManagerErrors.OperatorNotRegistered.selector);
allocationManager.setAllocationDelay(1);
}

function test_revert_zeroAllocationDelay() public {
cheats.expectRevert(IAllocationManagerErrors.InvalidAllocationDelay.selector);
cheats.prank(operatorToSet);
allocationManager.setAllocationDelay(0);
}

function testFuzz_setDelay(uint32 delay) public {
delay = uint32(bound(delay, 1, type(uint32).max));

// Set delay
cheats.expectEmit(true, true, true, true, address(allocationManager));
emit AllocationDelaySet(operatorToSet, delay, uint32(block.timestamp + ALLOCATION_CONFIGURATION_DELAY));
cheats.prank(operatorToSet);
allocationManager.setAllocationDelay(delay);

// Check values after set
(bool isSet, uint32 returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertFalse(isSet, "isSet should not be set");
assertEq(0, returnedDelay, "returned delay should be 0");

// Warp to effect timestamp
cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY);

// Check values after config delay
(isSet, returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertTrue(isSet, "isSet should be set");
assertEq(delay, returnedDelay, "delay not set");
}

function test_fuzz_setDelay_multipleTimesWithinConfigurationDelay(uint32 firstDelay, uint32 secondDelay) public {
firstDelay = uint32(bound(firstDelay, 1, type(uint32).max));
secondDelay = uint32(bound(secondDelay, 1, type(uint32).max));
cheats.assume(firstDelay != secondDelay);

// Set delay
cheats.prank(operatorToSet);
allocationManager.setAllocationDelay(firstDelay);

// Warp just before effect timestamp
cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY - 1);

// Set delay again
cheats.expectEmit(true, true, true, true, address(allocationManager));
emit AllocationDelaySet(operatorToSet, secondDelay, uint32(block.timestamp + ALLOCATION_CONFIGURATION_DELAY));
cheats.prank(operatorToSet);
allocationManager.setAllocationDelay(secondDelay);

// Warp to effect timestamp of first delay
cheats.warp(block.timestamp + 1);

// Assert that the delay is still not set
(bool isSet, uint32 returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertFalse(isSet, "isSet should not be set");
assertEq(0, returnedDelay, "returned delay should be 0");

// Warp to effect timestamp of second delay
cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY);
(isSet, returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertTrue(isSet, "isSet should be set");
assertEq(secondDelay, returnedDelay, "delay not set");
}

function testFuzz_multipleDelays(uint32 firstDelay, uint32 secondDelay) public {
firstDelay = uint32(bound(firstDelay, 1, type(uint32).max));
secondDelay = uint32(bound(secondDelay, 1, type(uint32).max));
cheats.assume(firstDelay != secondDelay);

// Set delay
cheats.prank(operatorToSet);
allocationManager.setAllocationDelay(firstDelay);

// Warp to effect timestamp of first delay
cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY);

// Set delay again
cheats.prank(operatorToSet);
allocationManager.setAllocationDelay(secondDelay);

// Assert that first delay is set
(bool isSet, uint32 returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertTrue(isSet, "isSet should be set");
assertEq(firstDelay, returnedDelay, "delay not set");

// Warp to effect timestamp of second delay
cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY);

// Check values after second delay
(isSet, returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertTrue(isSet, "isSet should be set");
assertEq(secondDelay, returnedDelay, "delay not set");
}

function testFuzz_setDelay_DMCaller(uint32 delay) public {
cheats.assume(delay > 0);

cheats.prank(address(delegationManagerMock));
allocationManager.setAllocationDelay(operatorToSet, delay);

// Warp to effect timestamp
cheats.warp(block.timestamp + ALLOCATION_CONFIGURATION_DELAY);
(bool isSet, uint32 returnedDelay) = allocationManager.getAllocationDelay(operatorToSet);
assertTrue(isSet, "isSet should be set");
assertEq(delay, returnedDelay, "delay not set");
}
}

0 comments on commit 06e852f

Please sign in to comment.