Guard Functions and Modifiers
Access control logic resides in Repos. Modifiers are thin delegation wrappers.
Guard Functions
Repos implement _onlyXxx functions that perform the check and revert with the appropriate custom error.
function _onlyOperator(Storage storage layoutStruct) internal view {
if (!_isOperator(layout, msg.sender) &&
!_isFunctionOperator(layout, msg.sig, msg.sender)) {
revert IOperable.NotOperator(msg.sender);
}
}
function _onlyOperator() internal view {
_onlyOperator(_layoutStruct());
}
All policy lives in the guard. There is a single source of truth for the condition.
Modifiers
abstract contract OperableModifiers {
modifier onlyOperator() {
OperableRepo._onlyOperator();
_;
}
}
Modifiers contain no logic. They exist only to provide the modifier syntax for contracts that inherit them.
Direct Calls
Because the guard is a regular internal function, other Repo functions or Targets can call _onlyOperator() directly without going through a modifier. This is the preferred pattern inside library code.
Function-Level Operators
The operable pattern supports both global operators and per-function operators. The guard checks both. Packages and facets that install operable logic automatically receive this granularity.
Reentrancy Guards
Reentrancy protection uses transient storage (EIP-1153). The lock is acquired and released within the same transaction and does not require storage writes that persist.
See the reentrancy module for the concrete ReentrancyLockRepo and ReentrancyLockModifiers implementation.