diff --git a/src/misc/PauseController.sol b/src/misc/PauseController.sol index 29e3815f..54192918 100644 --- a/src/misc/PauseController.sol +++ b/src/misc/PauseController.sol @@ -23,6 +23,10 @@ contract PauseController is OwnableUpgradeable { /// @param component The component that is unpaused. event Unpause(address indexed component); + /// @notice Emitted when the pause cooldown period of a component is reset. + /// @param component The component that has its pause cooldown period reset. + event ResetPauseCooldownPeriod(address indexed component); + /// @notice Emitted when the pause cooldown period is updated. /// @param oldPauseCooldownPeriod The old pause cooldown period. /// @param newPauseCooldownPeriod The new pause cooldown period. @@ -150,6 +154,14 @@ contract PauseController is OwnableUpgradeable { emit Unpause(address(component)); } + /// @notice Reset the pause cooldown period of a component. + /// @param component The component to reset the pause cooldown period. + function resetPauseCooldownPeriod(IPausable component) external onlyOwner { + lastUnpauseTime[address(component)] = 0; + + emit ResetPauseCooldownPeriod(address(component)); + } + /// @notice Set the pause cooldown period. /// @param newPauseCooldownPeriod The new pause cooldown period. function updatePauseCooldownPeriod(uint256 newPauseCooldownPeriod) external onlyOwner { diff --git a/src/test/misc/PauseController.t.sol b/src/test/misc/PauseController.t.sol index 19077537..e7a018b6 100644 --- a/src/test/misc/PauseController.t.sol +++ b/src/test/misc/PauseController.t.sol @@ -25,6 +25,7 @@ contract MockPausable is IPausable { contract PauseControllerTest is Test { event Pause(address indexed component); event Unpause(address indexed component); + event ResetPauseCooldownPeriod(address indexed component); event UpdatePauseCooldownPeriod(uint256 oldPauseCooldownPeriod, uint256 newPauseCooldownPeriod); uint256 public constant PAUSE_COOLDOWN_PERIOD = 1 days; @@ -117,8 +118,22 @@ contract PauseControllerTest is Test { emit Unpause(address(mockPausable)); pauseController.unpause(mockPausable); assertEq(pauseController.getLastUnpauseTime(mockPausable), block.timestamp); + assertFalse(mockPausable.paused()); + // cannot pause before cooldown period + vm.expectRevert(PauseController.ErrorCooldownPeriodNotPassed.selector); + pauseController.pause(mockPausable); + + // reset pause cooldown period + vm.expectEmit(true, false, false, true); + emit ResetPauseCooldownPeriod(address(mockPausable)); + pauseController.resetPauseCooldownPeriod(mockPausable); + assertEq(pauseController.getLastUnpauseTime(mockPausable), 0); + + // can pause after reset assertFalse(mockPausable.paused()); + pauseController.pause(mockPausable); + assertTrue(mockPausable.paused()); vm.stopPrank(); }