GovernedDiamondCutStorage
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
| Name | Type | Description |
|---|---|---|
| _cutCount | uint256 | |
| _cutRegistry | mapping(uint256 version => IUpgradeRegistry.CutRecord record) | |
| _frozenSelectors | EnumerableSet.Bytes4Set |