Skip to content
Lattice

GovernedSafeDiamondCutLib

Git Source

Title: GovernedSafeDiamondCut Library

Author: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80)

Library that gates EIP-2535 diamond cuts behind EmergencyStop + a pinned Gnosis Safe multisig AND a self-contained timelock: cuts must be scheduled, mature past minDelay, and only then be executed. No external Governor/TimelockController is required. Delegates the actual cut to DiamondLib.diamondCut; introduces no new cut logic.

Three-layer pattern: this library holds all logic and the namespaced storage. The stateless GovernedSafeDiamondCut facet delegates its external calls here. AUTHORITY MODEL: a Safe collects M-of-N owner signatures off-chain, verifies the threshold on-chain in execTransaction, then calls the diamond with operation = Call, so the diamond sees msg.sender == theSafe. This module does NOT re-verify signatures — it only trusts msg.sender == $._safe. The Safe MUST call with operation = Call (NEVER DelegateCall). Unlike SafeDiamondCutLib this module does NOT expose a synchronous cut at 0x1f931c1c; every cut travels schedule -> delay -> execute, so its scheduling surface is a NEW ERC-165 interface (0xacb1aeb6) registered at init.

Constants

DONE_TIMESTAMP

_scheduledAt marker for an executed operation (OpenZeppelin's _DONE_TIMESTAMP). It keeps an executed id distinct from a never-scheduled or cancelled one (0) and blocks its replay. As in OpenZeppelin, an eta that lands on a marker is misread: with a zero delay, scheduling at timestamp 1 reads as Done (cannot execute or cancel; use another salt) and at timestamp 0 as Unset. Neither timestamp occurs on a live chain.

uint256 internal constant DONE_TIMESTAMP = 1;

Functions

governedSafeDiamondCutStorage

Returns a storage reference to the GovernedSafeDiamondCutStorage struct.

function governedSafeDiamondCutStorage() internal pure returns (GovernedSafeDiamondCutStorage storage $);

Returns

NameTypeDescription
$GovernedSafeDiamondCutStorage

registerInterface

Registers support for the IGovernedSafeDiamondCut interface via ERC-165.

Writes true to the precomputed ERC-165 map slot (see ERC165_MAP_IGOVERNEDSAFEDIAMONDCUT_SLOT).

function registerInterface() internal;

__GovernedSafeDiamondCut_init

Initializes the GovernedSafeDiamondCut module by pinning the Safe authority and timelock.

Validates _safe is non-zero and a real Safe whose getThreshold() meets _minThreshold (which must itself be > 0). _minDelay MAY be 0, but a zero delay makes the timelock a no-op (a scheduled cut is immediately executable) — set a meaningful delay in production so the multisig's intent is publicly observable before it takes effect. There is no floor or ceiling: a delay so large that block.timestamp + delay overflows makes every scheduleCut and setMinDelay revert, permanently. Must be called inside the preInitializer/postInitializer window. Registers the IGovernedSafeDiamondCut ERC-165 id.

function __GovernedSafeDiamondCut_init(address _safe, uint256 _minThreshold, uint256 _minDelay) internal;

Parameters

NameTypeDescription
_safeaddressThe Safe multisig to pin as the cut authority.
_minThresholduint256The minimum signature threshold the pinned Safe must enforce.
_minDelayuint256The minimum timelock delay (seconds) between schedule and execute.

_checkSafe

Reverts ISafeAuthority.SafeDiamondCutUnauthorized unless the caller is the pinned Safe.

function _checkSafe(GovernedSafeDiamondCutStorage storage $) private view;

Parameters

NameTypeDescription
$GovernedSafeDiamondCutStorage

_validateSafe

Validates a candidate Safe authority: non-zero, real Safe, threshold >= minimum (> 0).

function _validateSafe(address _safe, uint256 _minThreshold) private view;

Parameters

NameTypeDescription
_safeaddress
_minThresholduint256

setSafe

Rotates the pinned Safe authority to _newSafe. Self-administered: callable ONLY by the current pinned Safe. _newSafe is validated like the init Safe (threshold >= 1). Emits ISafeAuthority.SafeRotated.

function setSafe(address _newSafe) internal;

Parameters

NameTypeDescription
_newSafeaddressThe new Safe to pin as the cut authority.

setMinDelay

Requests a new minimum timelock delay (seconds). Self-administered: callable ONLY by the pinned Safe. The change is NOT immediate: it applies to operations scheduled from effectAt = block.timestamp + max(current, _newDelay), so lowering the delay waits out the delay it replaces and the Safe cannot zero the delay and push a cut through in one transaction. A new request replaces any pending one (re-requesting the current delay withdraws it). Emits IGovernedSafeDiamondCut.MinDelayChangeScheduled.

Pending-delay pattern after OpenZeppelin's AccessManager. Not gated on msg.sender == address(this) like OpenZeppelin's TimelockController updateDelay: in a composed diamond address(this) can be reachable through other facets. Reverts on overflow of effectAt.

function setMinDelay(uint256 _newDelay) internal;

Parameters

NameTypeDescription
_newDelayuint256The new minimum delay (seconds); may be 0 (see init NatSpec on the risk).

_minDelayInForce

The delay in force now: the requested delay once its effectAt has passed, else the last committed one.

function _minDelayInForce(GovernedSafeDiamondCutStorage storage $) private view returns (uint256);

Parameters

NameTypeDescription
$GovernedSafeDiamondCutStorage

Returns

NameTypeDescription
<none>uint256

safe

Returns the currently pinned Safe authority.

function safe() internal view returns (address);

Returns

NameTypeDescription
<none>address

minDelay

Returns the minimum timelock delay (seconds) in force now. A change requested through setMinDelay is reflected only from its effectAt.

function minDelay() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256

_operationId

Computes the operation id binding the full cut payload plus a disambiguating salt.

function _operationId(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata, bytes32 _salt)
        private
        pure
        returns (bytes32);

Parameters

NameTypeDescription
_diamondCutFacetCut[]
_initaddress
_calldatabytes
_saltbytes32

Returns

NameTypeDescription
<none>bytes32

_state

Classifies a stored _scheduledAt value: 0 is Unset (never scheduled or cancelled), DONE_TIMESTAMP is Done, and any other value is Waiting until its eta, then Ready.

function _state(uint256 _eta) private view returns (ITimelockController.OperationState);

Parameters

NameTypeDescription
_etauint256

Returns

NameTypeDescription
<none>ITimelockController.OperationState

scheduleCut

Schedules a cut for later execution. Reverts if emergency-stopped, then requires the caller to be the pinned Safe, then stores eta = block.timestamp + minDelay under the operation id (checked: a delay that would overflow reverts rather than wrap eta into the past). Reverts IGovernedSafeDiamondCut.CutAlreadyScheduled if the id is already scheduled or was executed; re-running an executed cut takes a new salt. Does NOT validate frozen selectors here — that check fires at execution time (against the then-current frozen set), matching the synchronous path's ordering.

function scheduleCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata, bytes32 _salt)
        internal
        returns (bytes32 id);

Parameters

NameTypeDescription
_diamondCutFacetCut[]The facet addresses, cut actions, and function selectors.
_initaddressThe address delegatecalled after the cut (address(0) to skip).
_calldatabytesThe calldata passed to _init.
_saltbytes32A caller-chosen salt disambiguating otherwise-identical payloads.

Returns

NameTypeDescription
idbytes32The operation id.

executeCut

Executes a previously-scheduled, matured cut. Reverts if emergency-stopped, requires the caller to be the pinned Safe, re-derives the id and requires it scheduled and matured (an executed id reverts IGovernedSafeDiamondCut.CutNotScheduled), marks it done, enforces the frozen-selector guard, applies the cut, and records it in the append-only registry. Emits IGovernedSafeDiamondCut.CutExecuted.

function executeCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata, bytes32 _salt)
        internal;

Parameters

NameTypeDescription
_diamondCutFacetCut[]The facet addresses, cut actions, and function selectors (must match schedule).
_initaddressThe address delegatecalled after the cut (must match schedule).
_calldatabytesThe calldata passed to _init (must match schedule).
_saltbytes32The salt used at schedule time.

cancelCut

Cancels a scheduled, not-yet-executed operation (pending or ready). Requires the caller to be the pinned Safe. Reverts IGovernedSafeDiamondCut.CutNotScheduled if the id is not currently scheduled, including an executed id. Emits IGovernedSafeDiamondCut.CutCancelled.

function cancelCut(bytes32 _id) internal;

Parameters

NameTypeDescription
_idbytes32The operation id to cancel.

emergencyRemoveCut

Zero-delay, REMOVAL-ONLY escape hatch: lets a guardian instantly unbind a compromised or buggy facet's selectors WITHOUT scheduling and WITHOUT the Safe — and, by design, even while the normal cut path is halted by EmergencyStop. Removal-only, frozen-protected, no init delegatecall, and never scheduleCut/executeCut or a stop-recovery selector (emergencyResume, removeGuardian, revokeRole; reverts IEmergencyCut.EmergencyCutEntrypointProtected even with an empty frozen set). Recorded in the SAME append-only registry and emits IEmergencyCut.EmergencyCutExecuted. Mirrors GovernedDiamondCutLib.emergencyRemoveCut.

Liveness: a guardian can still trip the stop, which blocks scheduleCut and executeCut, and can trip it again between the two. A stop only delays: a ready operation never expires, and since the recovery selectors cannot be removed, the DEFAULT_ADMIN_ROLE holder can always revoke a hostile guardian, resume, and let the Safe cut again to restore anything removed. This assumes a live admin; with the admin role renounced a stop is permanent.

function emergencyRemoveCut(FacetCut[] calldata _cuts) internal;

Parameters

NameTypeDescription
_cutsFacetCut[]The facet cuts to apply; every entry MUST be a Remove (facetAddress == address(0)).

freezeSelectors

Permanently freezes _selectors. Gated to the pinned Safe. Append-only; no unfreeze.

function freezeSelectors(bytes4[] calldata _selectors) internal;

Parameters

NameTypeDescription
_selectorsbytes4[]The function selectors to freeze.

_enforceNotFrozen

Reverts IFrozenSelectors.FrozenSelectorProtected if any Replace/Remove action in _diamondCut targets a frozen selector. Add actions are never inspected.

function _enforceNotFrozen(GovernedSafeDiamondCutStorage storage $, FacetCut[] calldata _diamondCut) private view;

Parameters

NameTypeDescription
$GovernedSafeDiamondCutStorage
_diamondCutFacetCut[]

getTimestamp

Returns the ready timestamp (eta) of an operation: 0 if never scheduled or cancelled, and DONE_TIMESTAMP (1) once executed.

function getTimestamp(bytes32 _id) internal view returns (uint256);

Parameters

NameTypeDescription
_idbytes32The operation id to query.

Returns

NameTypeDescription
<none>uint256

isOperationPending

Returns whether _id is scheduled but not yet matured (eta in the future).

function isOperationPending(bytes32 _id) internal view returns (bool);

Parameters

NameTypeDescription
_idbytes32The operation id to query.

Returns

NameTypeDescription
<none>bool

isOperationReady

Returns whether _id is scheduled and matured (eta reached, not yet executed).

function isOperationReady(bytes32 _id) internal view returns (bool);

Parameters

NameTypeDescription
_idbytes32The operation id to query.

Returns

NameTypeDescription
<none>bool

isOperationDone

Returns whether _id has been executed. Never-scheduled and cancelled ids report false, matching OpenZeppelin's TimelockController Done state.

function isOperationDone(bytes32 _id) internal view returns (bool);

Parameters

NameTypeDescription
_idbytes32The operation id to query.

Returns

NameTypeDescription
<none>bool

cutCount

Returns the number of cuts applied so far (also the latest registry version).

function cutCount() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256

getCutRecord

Returns the immutable audit record for a given registry version.

function getCutRecord(uint256 _version) internal view returns (IUpgradeRegistry.CutRecord memory);

Parameters

NameTypeDescription
_versionuint256The registry version to look up.

Returns

NameTypeDescription
<none>IUpgradeRegistry.CutRecord

isSelectorFrozen

Returns whether _selector is in the frozen set (protected from Replace/Remove).

function isSelectorFrozen(bytes4 _selector) internal view returns (bool);

Parameters

NameTypeDescription
_selectorbytes4The function selector to query.

Returns

NameTypeDescription
<none>bool

frozenSelectors

Returns the full set of frozen selectors.

function frozenSelectors() internal view returns (bytes4[] memory);

Returns

NameTypeDescription
<none>bytes4[]

previewCut

Pre-flight simulation of the frozen-selector guard against the current set, no mutation.

function previewCut(FacetCut[] calldata _cuts) internal view returns (bool ok, bytes4 offendingSelector);

Parameters

NameTypeDescription
_cutsFacetCut[]The candidate facet cuts to simulate.

Returns

NameTypeDescription
okbooltrue if no Replace/Remove in _cuts targets a frozen selector.
offendingSelectorbytes4The first frozen selector a Replace/Remove would touch (zero if ok).

verifyInterfaceRegistered

Verifies whether _interfaceId is currently advertised in the diamond's ERC-165 map.

function verifyInterfaceRegistered(bytes4 _interfaceId) internal view returns (bool);

Parameters

NameTypeDescription
_interfaceIdbytes4The ERC-165 interface identifier to check.

Returns

NameTypeDescription
<none>bool