ERC6900ExecutorLib
Title: ERC6900ExecutorLib
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from ERC-6900 reference implementation (https://github.com/erc6900/reference-implementation)
The ERC-6900 RUNTIME executor + dispatch pipeline: the ModularAccount6900 fallback dispatch for
installed execution-module selectors, the native execute / executeBatch, and the explicit-auth
executeWithRuntimeValidation, plus the runtime-validation pipeline and the execution-hook engine.
Re-implemented FRESH from the ERC-6900 reference (erc6900/reference-implementation @ 65892c2). Reads the
registries owned by ERC6900ModuleManagerLib. Key semantics carried over: execution modules are invoked
by CALL (own storage context), NOT delegatecall; exec hooks come from two never-merged sources
(validation-associated + selector-associated); pre hooks snapshot their post set before running, post
hooks run LIFO and ONLY on success; runtime auth bypasses on EntryPoint / self / skipRuntimeValidation
and otherwise routes through a direct-call validation. No reentrancy mutex — self-recursion is capped at
one level. Lattice deviation: native validation-gated selectors are just execute/executeBatch (Lattice
installs/uninstalls are admin-gated in ERC6900ModuleManagerLib, not validation-gated).
Functions
dispatch
Dispatches a call to an installed execution module: auth + pre hooks → CALL module → post hooks.
Reverts UnrecognizedFunction if no module owns the selector.
function dispatch() internal returns (bytes memory);Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes |
execute
execute(target, value, data) — a native execution function: validates the caller + runs the
active validation's exec hooks, then CALLs target with value.
function execute(address target, uint256 value, bytes calldata data) internal returns (bytes memory result);Parameters
| Name | Type | Description |
|---|---|---|
| target | address | |
| value | uint256 | |
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| result | bytes |
executeBatch
executeBatch(calls) — atomic; reverts the whole batch on any sub-call failure. No
Σ value == msg.value check — per-call value draws on the account's balance.
function executeBatch(Call[] calldata calls) internal returns (bytes[] memory results);Parameters
| Name | Type | Description |
|---|---|---|
| calls | Call[] |
Returns
| Name | Type | Description |
|---|---|---|
| results | bytes[] |
executeWithRuntimeValidation
executeWithRuntimeValidation(data, authorization) — runs the supplied validation (pre-validation
hooks + validateRuntime) + its exec hooks, then self-CALLs data.
function executeWithRuntimeValidation(bytes calldata data, bytes calldata authorization)
internal
returns (bytes memory);Parameters
| Name | Type | Description |
|---|---|---|
| data | bytes | |
| authorization | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes |
_checkPermittedCallerAndAssociatedHooks
Runtime authorization for a native/module selector + collection of its pre exec hooks. Returns the cached post hooks for the validator set and the selector set (run in reverse on the way out).
function _checkPermittedCallerAndAssociatedHooks(bytes calldata callData)
private
returns (PostExecToRun[] memory postValidator, PostExecToRun[] memory postSelector);Parameters
| Name | Type | Description |
|---|---|---|
| callData | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| postValidator | PostExecToRun[] | |
| postSelector | PostExecToRun[] |
checkValidationAppliesCallData
Validation applicability for callData's selector + the self-call recursion guard (depth 1).
Shared with the userOp validation path (#74 sub-task 4), which decodes the selector from the
userOp callData and passes GLOBAL or SELECTOR (never EITHER).
function checkValidationAppliesCallData(bytes calldata callData, ModuleEntity vf, ValidationCheckType t)
internal
view;Parameters
| Name | Type | Description |
|---|---|---|
| callData | bytes | |
| vf | ModuleEntity | |
| t | ValidationCheckType |
_checkIfValidationApplies
function _checkIfValidationApplies(bytes4 selector, ModuleEntity vf, ValidationCheckType t) private view;Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 | |
| vf | ModuleEntity | |
| t | ValidationCheckType |
_globalValidationApplies
function _globalValidationApplies(bytes4 selector, ModuleEntity vf) private view returns (bool);Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 | |
| vf | ModuleEntity |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_selectorValidationApplies
function _selectorValidationApplies(bytes4 selector, ModuleEntity vf) private view returns (bool);Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 | |
| vf | ModuleEntity |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_globalValidationAllowed
execute/executeBatch are the native validation-gated selectors (Lattice installs/uninstalls are
admin-gated in ERC6900ModuleManagerLib, not validation-gated); any other selector opts into global
validation via its own allowGlobalValidation flag.
function _globalValidationAllowed(bytes4 selector) private view returns (bool);Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
_doRuntimeValidation
Runs vf's pre-runtime-validation hooks then its validateRuntime (the explicit-auth path, unlike
the direct-call path which only runs the hooks).
function _doRuntimeValidation(ModuleEntity vf, bytes calldata data, bytes calldata authData) private;Parameters
| Name | Type | Description |
|---|---|---|
| vf | ModuleEntity | |
| data | bytes | |
| authData | bytes |
_moduleEntityOf
function _moduleEntityOf(bytes calldata auth) private pure returns (ModuleEntity me);Parameters
| Name | Type | Description |
|---|---|---|
| auth | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| me | ModuleEntity |
_doPreRuntimeValidationHooks
function _doPreRuntimeValidationHooks(ModuleEntity vf, bytes calldata data) private;Parameters
| Name | Type | Description |
|---|---|---|
| vf | ModuleEntity | |
| data | bytes |
_doPreHooks
Snapshot the post-hook set BEFORE running any pre hook (so a hook that mutates the set cannot change which post hooks fire), then run pre hooks, caching each pre's return data for its matching post hook.
function _doPreHooks(EnumerableSet.Bytes32Set storage hooks, bytes calldata data)
private
returns (PostExecToRun[] memory toRun);Parameters
| Name | Type | Description |
|---|---|---|
| hooks | EnumerableSet.Bytes32Set | |
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| toRun | PostExecToRun[] |
_runPreExecHook
function _runPreExecHook(ModuleEntity hookEntity, bytes calldata data) private returns (bytes memory);Parameters
| Name | Type | Description |
|---|---|---|
| hookEntity | ModuleEntity | |
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes |
_doCachedPostExecHooks
Run cached post hooks LIFO; pre-only entries (empty postExecHook) are skipped. Post hooks run only on
the success path — a reverting body bubbles before this is reached.
function _doCachedPostExecHooks(PostExecToRun[] memory toRun) private;Parameters
| Name | Type | Description |
|---|---|---|
| toRun | PostExecToRun[] |
_exec
Raw target CALL with value; bubbles the target's revert data verbatim. The executor NEVER self-calls
the account — a self-call would bridge a validation-authorized execute/executeBatch into the
admin-gated config functions (msg.sender == address(this) satisfies _authorizeConfig). This is the
backstop for the privileged bypass paths (EntryPoint / self / skipRuntimeValidation), which skip the
applicability guard entirely.
function _exec(address target, uint256 value, bytes calldata data) private returns (bytes memory);Parameters
| Name | Type | Description |
|---|---|---|
| target | address | |
| value | uint256 | |
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes |
_selectorOf
function _selectorOf(bytes calldata data) private pure returns (bytes4 s);Parameters
| Name | Type | Description |
|---|---|---|
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| s | bytes4 |