Skip to content
Lattice

IFrozenSelectors

Git Source

Title: IFrozenSelectors

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

Protection layer for the GovernedDiamondCut facet: a governance-curated, append-only set of "frozen" function selectors that can never be Replaced or Removed by a subsequent governed cut, plus a pre-flight simulator and an ERC-165 verification helper for upgrade workflows. Freezing prevents the executor from accidentally replacing or removing a frozen selector, and bounds emergencyRemoveCut. It does not constrain _init or added facets: the defence against a hostile proposal is the delay and cancel.

This interface is intentionally SEPARATE from IGovernedDiamondCut: that interface exposes only diamondCut, so type(IGovernedDiamondCut).interfaceId == 0x1f931c1c (identical to IDiamondCut), which is load-bearing — the governed facet must occupy the canonical cut selector. The freeze/preview/verify surface therefore lives here so it cannot perturb that pinned id. None of these functions are advertised as a distinct ERC-165 interface: they are plain facet admin/view functions, so no new ERC-165 map slot is registered for them.

Functions

freezeSelectors

Permanently marks selectors as frozen: once frozen, a selector can never be the target of a Replace or Remove in any future governed cut. Append-only — there is deliberately no unfreeze. Gated like the facet's cut: on GovernedDiamondCut, behind UPGRADE_EXECUTOR_ROLE (the single-holder role that gates diamondCut), so in its recipes only a timelock-relayed governance proposal can freeze (a co-cut self-call relay such as AccessManager execute would also reach it); on SafeDiamondCut and GovernedSafeDiamondCut, by the pinned Safe.

function freezeSelectors(bytes4[] calldata selectors) external;

Parameters

NameTypeDescription
selectorsbytes4[]The function selectors to freeze. Already-frozen selectors are idempotent.

isSelectorFrozen

Returns whether selector is in the frozen set.

function isSelectorFrozen(bytes4 selector) external view returns (bool frozen);

Parameters

NameTypeDescription
selectorbytes4The function selector to query.

Returns

NameTypeDescription
frozenbooltrue if the selector is frozen (protected from Replace/Remove).

frozenSelectors

Returns the full set of frozen selectors.

function frozenSelectors() external view returns (bytes4[] memory selectors);

Returns

NameTypeDescription
selectorsbytes4[]The frozen selectors, in insertion order (subject to swap-and-pop reordering
on internal set mechanics, though the set is append-only so order is stable here).

previewCut

Pre-flight simulation of the frozen-selector guard against the CURRENT frozen set, with no state change and no broadcast. Lets an upgrade workflow fail fast — before proposing — if a cut would touch a frozen selector. Mirrors exactly the check the guarded diamondCut performs before applying: only Replace/Remove actions are inspected.

This is a pure read of the frozen set; it does NOT re-implement diamond-lib's collision / immutable-function / bytecode-existence checks, which fire at execution time.

function previewCut(FacetCut[] calldata cuts) external 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.

A thin wrapper over the shared ERC-165 support read, so an upgrade workflow can confirm an expected interface is still (or now) advertised after a cut. Equivalent to calling supportsInterface(interfaceId) on the diamond.

function verifyInterfaceRegistered(bytes4 interfaceId) external view returns (bool registered);

Parameters

NameTypeDescription
interfaceIdbytes4The ERC-165 interface identifier to check.

Returns

NameTypeDescription
registeredbooltrue if the interface is advertised.

Events

SelectorsFrozen

Emitted once per freezeSelectors call that adds at least one new selector. Carries the full argument array as passed (including any selectors that were already frozen, which are idempotent no-ops in the set).

event SelectorsFrozen(address indexed caller, bytes4[] selectors);

Parameters

NameTypeDescription
calleraddressThe UPGRADE_EXECUTOR_ROLE holder that froze the selectors (the timelock relay).
selectorsbytes4[]The selectors supplied to freezeSelectors.

Errors

FrozenSelectorProtected

Thrown by the guarded diamondCut (and surfaced via previewCut) when a Replace or Remove cut targets a frozen selector. Add actions are never affected.

error FrozenSelectorProtected(bytes4 selector);

Parameters

NameTypeDescription
selectorbytes4The frozen selector a cut attempted to replace or remove.