// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import { GovernanceControlsV3 } from "./GovernanceControlsV3.sol"; /// @notice Guardian can only pause and veto a pending governance handoff; governance unpauses after a delay. abstract contract EmergencyControlsV3 is GovernanceControlsV3 { uint64 public immutable minimumPauseDuration; bool public paused; uint64 public pausedAt; error EmergencyUnauthorized(); error Paused(); error NotPaused(); error UnpauseTooEarly(); error ZeroAddress(); event PausedV3(address indexed caller, uint64 at); event UnpausedV3(address indexed caller, uint64 at); constructor(address governance_, address guardian_, uint64 minimumPauseDuration_) GovernanceControlsV3(governance_, guardian_) { if (guardian_ == address(0)) revert ZeroAddress(); minimumPauseDuration = minimumPauseDuration_; } modifier whenNotPaused() { if (paused) revert Paused(); _; } function pause() external { if (msg.sender != governance && msg.sender != governanceGuardian) revert EmergencyUnauthorized(); if (!paused) { paused = true; pausedAt = uint64(block.timestamp); emit PausedV3(msg.sender, pausedAt); } } function unpause() external { if (msg.sender != governance) revert EmergencyUnauthorized(); if (!paused) revert NotPaused(); if (block.timestamp < uint256(pausedAt) + minimumPauseDuration) revert UnpauseTooEarly(); paused = false; emit UnpausedV3(msg.sender, uint64(block.timestamp)); } function guardian() external view returns (address) { return governanceGuardian; } }