Skip to content
Lattice

GovernedDiamondCutStorage

Git Source

Role required to fire the zero-delay, REMOVAL-ONLY emergency cut (emergencyRemoveCut). This is DELIBERATELY the very same role that arms the EmergencyStop panic button — the operator who can halt the diamond is the operator who can amputate a compromised facet — so the literal is imported from EmergencyStopLib (single source of truth) rather than re-declared here. keccak256("EMERGENCY_GUARDIAN_ROLE") == 0x93a9ea60add98726fcd12f31bd91d98faf4378bac52abb4f48e807756ced77a1 (verify: cast keccak "EMERGENCY_GUARDIAN_ROLE"). It is intentionally DISTINCT from UPGRADE_EXECUTOR_ROLE: a guardian can ONLY remove code (never add/replace — those still require a full governance round), can never remove diamondCut itself or the admin's stop-recovery selectors (emergencyResume, removeGuardian, revokeRole; see EmergencyStopLib.isRecoverySelector), and can never remove a frozen selector. Consumers/tests import the constant from EmergencyStopLib. TRUST: nothing is frozen at init, so a guardian can remove any OTHER unfrozen selector, including the Governor/Timelock functions a proposal travels through (propose, castVote*, queue, execute, scheduleBatch, executeBatch, ...). diamondCut then stays bound but unreachable, so the guardian is TRUSTED for governance liveness until governance freezes that path (recommended list: DeployGovernedVault.recommendedFreezeSelectors). Removal of the recovery selectors is refused outright, so a guardian that trips the stop cannot also keep governance from resuming once that path is frozen. The admin can also appoint itself guardian. This role is intentionally left admin-managed (its admin stays DEFAULT_ADMIN_ROLE) BY DESIGN so the admin can grant/rotate it; pinning it is out of scope.

ERC-7201 namespaced storage for the GovernedDiamondCut module.

Authority itself lives in AccessControl + EmergencyStop storage; this slot holds the module's own append-only upgrade audit trail. APPEND-ONLY: fields are only ever added at the end — never reordered, retyped, or removed — so the ERC-7201 slot stays stable across upgrades. The slot constant is unchanged because the namespace string is unchanged.

Note:

  • storage-location: erc7201:lattice.storage.GovernedDiamondCut
struct GovernedDiamondCutStorage {
    /// @dev Monotonic counter of governed cuts applied; doubles as the latest registry version.
    ///      The value assigned to a cut (post-increment) IS that cut's `version`.
    uint256 _cutCount;
    /// @dev Append-only registry: version (1-indexed) => immutable {IUpgradeRegistry.CutRecord}.
    ///      Written once per successful cut and never mutated thereafter.
    mapping(uint256 version => IUpgradeRegistry.CutRecord record) _cutRegistry;
    /// @dev Append-only set of frozen function selectors. A selector in this set can never be the
    ///      target of a `Replace` or `Remove` in any future governed cut (the guard checks this set
    ///      BEFORE delegating to diamond-lib). There is deliberately no unfreeze. APPENDED at the end
    ///      of this struct — the ERC-7201 slot is unchanged because the namespace string is unchanged.
    EnumerableSet.Bytes4Set _frozenSelectors;
}

Properties

NameTypeDescription
_cutCountuint256
_cutRegistrymapping(uint256 version => IUpgradeRegistry.CutRecord record)
_frozenSelectorsEnumerableSet.Bytes4Set