ERC6900ModuleManagerLib
Title: ERC6900ModuleManagerLib
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from ERC-6900 reference implementation (https://github.com/erc6900/reference-implementation)
Logic + ERC-7201 storage for the ERC-6900 module registry: the execution registry (selector →
module + exec hooks) and the validation registry (ModuleEntity → flags + selectors + validation
/exec hooks). Backs the ERC6900ModuleManager config facet and (via the read helpers) the
IERC6900AccountView loupe.
Re-implemented FRESH from the ERC-6900 reference semantics (erc6900/reference-implementation @ 65892c2;
reference is MIT — not a dependency). Lattice-native deviations: ERC-7201 namespaced storage (not the
reference's plain-keccak slot); a Diamond facet-map shadow check in place of the reference's static
KnownSelectorsLib.isNativeFunction list (diamondCut is the sole selector authority); and the
account-or-admin _authorizeConfig model shared with the ERC-7579 flavor. Module callbacks are
data-gated (called only when their bytes arg is non-empty) and state is written BEFORE every callback;
onInstall failure reverts the whole install, onUninstall failure is swallowed into the event's
onUninstallSucceeded flag — matching the reference.
Constants
_ACCOUNT_ID
ERC-6900 account identifier (vendorname.accountname.semver; names contain no period).
string private constant _ACCOUNT_ID = "lattice.modular-account-6900.0.1.0";Functions
erc6900ModuleManagerStorage
function erc6900ModuleManagerStorage() internal pure returns (ERC6900ModuleManagerStorage storage $);Returns
| Name | Type | Description |
|---|---|---|
| $ | ERC6900ModuleManagerStorage |
accountId
function accountId() internal pure returns (string memory);Returns
| Name | Type | Description |
|---|---|---|
| <none> | string |
getExecutionData
The execution-function install state for selector (module, validation flags, exec hooks). A
native function — one the Diamond dispatches to a facet — reports the account itself as the module
(per IERC6900AccountView); execute/executeBatch additionally report allowGlobalValidation
(matching the executor's native validation-gated set). An unowned selector reports all zero.
function getExecutionData(bytes4 selector) internal view returns (ExecutionDataView memory data);Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 |
Returns
| Name | Type | Description |
|---|---|---|
| data | ExecutionDataView |
getValidationData
The validation-function install state for validationFunction (flags, hooks, selectors).
function getValidationData(ModuleEntity validationFunction) internal view returns (ValidationDataView memory data);Parameters
| Name | Type | Description |
|---|---|---|
| validationFunction | ModuleEntity |
Returns
| Name | Type | Description |
|---|---|---|
| data | ValidationDataView |
interfaceRefCount
How many installed modules advertise interfaceId via their manifest (ERC-165 refcount).
function interfaceRefCount(bytes4 interfaceId) internal view returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| interfaceId | bytes4 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
installExecution
Installs an execution module from its manifest. Order (matching the reference): execution
functions → execution hooks → interface ids → onInstall. State is written before the callback;
a reverting onInstall reverts the whole install (ModuleInstallCallbackFailed).
function installExecution(address module, ExecutionManifest calldata manifest, bytes calldata installData)
internal;Parameters
| Name | Type | Description |
|---|---|---|
| module | address | |
| manifest | ExecutionManifest | |
| installData | bytes |
uninstallExecution
Uninstalls an execution module. Reverse-by-type of install (hooks → functions → interface ids),
then onUninstall. No ownership/installed checks (auth-gated); a reverting onUninstall is
SWALLOWED into the event's onUninstallSucceeded flag, never reverting the uninstall.
function uninstallExecution(address module, ExecutionManifest calldata manifest, bytes calldata uninstallData)
internal;Parameters
| Name | Type | Description |
|---|---|---|
| module | address | |
| manifest | ExecutionManifest | |
| uninstallData | bytes |
installValidation
Installs (or updates) a validation function. Order (matching the reference): per hook
(store → onInstall) → selectors → flags → the validation module's own onInstall. Flags are
OVERWRITTEN wholesale (this is also the update path); selectors/hooks are only ever added.
Validation (pre-validation) hooks go to an ordered array (duplicates allowed, capped at
MAX_VALIDATION_ASSOC_HOOKS); execution hooks go to a deduped set.
function installValidation(
ValidationConfig validationConfig,
bytes4[] calldata selectors,
bytes calldata installData,
bytes[] calldata hooks
) internal;Parameters
| Name | Type | Description |
|---|---|---|
| validationConfig | ValidationConfig | |
| selectors | bytes4[] | |
| installData | bytes | |
| hooks | bytes[] |
uninstallValidation
Uninstalls a validation function. Order: clear flags → (if hookUninstallData non-empty) run hook
onUninstalls [validation hooks, then execution hooks] → wipe hooks/selectors → the validation
module's own onUninstall. Every onUninstall revert is swallowed into onUninstallSucceeded.
Passing empty hookUninstallData clears all state but skips every hook callback.
function uninstallValidation(
ModuleEntity validationFunction,
bytes calldata uninstallData,
bytes[] calldata hookUninstallData
) internal;Parameters
| Name | Type | Description |
|---|---|---|
| validationFunction | ModuleEntity | |
| uninstallData | bytes | |
| hookUninstallData | bytes[] |
_toHookConfigs
function _toHookConfigs(EnumerableSet.Bytes32Set storage set) private view returns (HookConfig[] memory out);Parameters
| Name | Type | Description |
|---|---|---|
| set | EnumerableSet.Bytes32Set |
Returns
| Name | Type | Description |
|---|---|---|
| out | HookConfig[] |
_hookKey
Set key for a HookConfig: the bytes25 left-aligned in a bytes32 (low 7 bytes zero).
function _hookKey(HookConfig hookConfig) private pure returns (bytes32);Parameters
| Name | Type | Description |
|---|---|---|
| hookConfig | HookConfig |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes32 |
_addInterface
Refcount a manifest interface id; advertise it via the Diamond's ERC-165 map on the first claim. The refcount and the Diamond's native ERC-165 bits share one bool map, so a module may not refcount an id the account already owns natively (bit set, refcount 0) — a later uninstall would clear that native bit and desync the ERC-165 view. The ERC-165 invalid sentinel must always read false, so it too is rejected. (Native ids are registered at construction, before any module install.)
function _addInterface(ERC6900ModuleManagerStorage storage $, bytes4 interfaceId) private;Parameters
| Name | Type | Description |
|---|---|---|
| $ | ERC6900ModuleManagerStorage | |
| interfaceId | bytes4 |
_removeInterface
Drop one manifest interface-id reference; retract from ERC-165 when the last module drops it. The checked decrement panics on over-uninstall — matching the reference's refcount underflow.
function _removeInterface(ERC6900ModuleManagerStorage storage $, bytes4 interfaceId) private;Parameters
| Name | Type | Description |
|---|---|---|
| $ | ERC6900ModuleManagerStorage | |
| interfaceId | bytes4 |
_onInstall
Data-gated onInstall: skipped when data is empty; a revert is re-thrown as
ModuleInstallCallbackFailed (reverting the whole install).
function _onInstall(address module, bytes calldata data) private;Parameters
| Name | Type | Description |
|---|---|---|
| module | address | |
| data | bytes |
_onUninstall
Data-gated onUninstall: skipped (treated as success) when data is empty; a revert is SWALLOWED
and reported as false so a malicious module cannot brick uninstallation.
function _onUninstall(address module, bytes calldata data) private returns (bool);Parameters
| Name | Type | Description |
|---|---|---|
| module | address | |
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_decodeHook
Splits an installValidation hook entry abi.encodePacked(bytes25 HookConfig, bytes hookData) at the
fixed 25-byte boundary. h[25:] bounds-checks the length (reverts if < 25); the calldataload reads
the leading 25 bytes (low 7 of the 32-byte word are masked off by the bytes25 cast).
function _decodeHook(bytes calldata h) private pure returns (HookConfig hookConfig, bytes calldata hookData);Parameters
| Name | Type | Description |
|---|---|---|
| h | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| hookConfig | HookConfig | |
| hookData | bytes |
_drainBytes32
function _drainBytes32(EnumerableSet.Bytes32Set storage set) private;Parameters
| Name | Type | Description |
|---|---|---|
| set | EnumerableSet.Bytes32Set |
_drainBytes4
function _drainBytes4(EnumerableSet.Bytes4Set storage set) private;Parameters
| Name | Type | Description |
|---|---|---|
| set | EnumerableSet.Bytes4Set |
_authorizeConfig
function _authorizeConfig() private view;