- Documentation: Comprehensive guides, architecture overview, and API references.
- Interactive Demo: A live dApp to configure, mine, and deploy hooks composed of multiple configurable modules.
- Pitch Deck: High-level presentation of the project vision and features.
MODL is a Uniswap v4 hook aggregator that lets a single pool coordinate multiple pieces of custom logic. Instead of writing a monolithic hook, developers compose reusable modules that implement the IMODLModule interface. The aggregator enforces ordering, error handling, and hook-data routing so each module stays isolated.
MODLAggregator.sol: ExtendsBaseHookand fans out every lifecycle callback to registered modules. Each module declares which hooks it cares about plus a per-module gas budget, failure policy (critical), and priority. Hook data is ABI-encoded asIMODLModule.ModuleCallData[], allowing callers to send per-module payloads in a single bytes blob. The aggregator also exposes a deterministic routing table that forwards arbitrary function selectors (likeplaceOrder) through its fallback to one or more modules.IMODLModule: Shared interface covering every pool lifecycle callback plus return-value structs for hooks that produce deltas or fee overrides. Modules receive theIPoolManager, the hook caller, and hook-specific data.- Modules:
WhitelistModule: Reusable access control for swaps, liquidity updates, and donations. Owners manage the whitelist and can toggle enforcement per action.DynamicFeeModule: Computes a dynamic LP fee override based on configurable volatility parameters or per-swap instructions embedded in hook data.
MODL includes modules that leverage Fhenix Fully Homomorphic Encryption (FHE) for privacy-preserving hook logic:
FhenixCredentialsModule: Abstract base for modules that validate user credentials using encrypted data. Callers submit encrypted credentials which are verified without revealing the underlying values.FhenixWhitelistModule: Production-ready allow-list that defers credential validation to an off-chain Fhenix verifier. The module gates swaps, liquidity updates, and donations based on privacy-preserving proofs.FhenixAsyncModule: Base helper for modules that outsource private computation to a Fhenix co-processor. Handles task context storage and result callback routing.
Use the CLI to scaffold a new Fhenix-enabled module:
modl module:new MyPrivateWhitelist -t fhenix-credentialsMODL provides modules that integrate with EigenLayer Actively Validated Services (AVS) and oracles:
EigenOracleModule: Lightweight helper to consume EigenLayer-backed oracles with built-in freshness checks. Reverts if data is stale beyond a configurable threshold.EigenDynamicFeeModule: Dynamic-fee calculator that pulls a volatility index from an EigenLayer oracle and adjusts LP fees within configurable bounds.EigenTaskModule: Base helper for modules that dispatch async work to an EigenLayer AVS. Manages task posting, context persistence, and result callbacks.
Use the CLI to scaffold a new EigenLayer-powered module:
modl module:new MyVolatilityFee -t eigen-oracle-
Install dependencies and compile
forge build
-
Run the full test suite
forge test -
Add new modules
- Implement
IMODLModule, ensuring only the aggregator can invoke the hook entrypoints. - Deploy the module and register it through
MODLAggregator.setModules, providing hook flags, execution priority, per-callgasLimit(set to0for unlimited), and whether the module iscritical(reverting the whole hook on failure).
- Implement
- Optional: map extra function selectors (e.g.,
placeOrder(bytes calldata)) withsetRoute(bytes4 selector, uint16[] moduleIndices, ExecMode mode)so that users can call those functions directly on the aggregator. The fallback forwards the original calldata to the routed modules, either stopping at the first module or executing every module in order depending onExecMode.
-
Hook data format
Calling contracts should encode hook data as
abi.encode(IMODLModule.ModuleCallData[] memory). Each entry contains the module address and the payload that the module expects. The aggregator extracts the relevant payload for each module automatically. -
Function routing
Routes are configured via
setRoute(bytes4 selector, uint16[] moduleIndices, ExecMode mode). The mapping is deterministic: selectors resolve to an ordered list of module indices stored inside the aggregator, so every call takes the exact same path. Routes can be cleared withclearRoute. When a user calls an unknown function on the aggregator, the fallback looks up the selector and forwards the original calldata with the configured gas budget of each module.ExecMode.FIRSTstops after the first module, whileExecMode.ALLexecutes every module and returns the last module's returndata.
Generate modules and tests from templates:
npm install -g @modl-dev/cli # or npm install --save-dev @modl-dev/cli
modl init # writes modl.config.json and creates module/test folders
modl template:list # discover available templates
modl module:new MyModule # uses default template (basic)
modl module:new EigenDynamicFee -t eigen-oracle
modl module:new FhenixWhitelist -t fhenix-credentialsYou can also use it directly with npx:
npx @modl-dev/cli init
npx @modl-dev/cli module:new MyModuleTemplates are stored in cli/templates and rendered with simple placeholders ({{MODULE_NAME}}). Fhenix templates expect @fhenixprotocol/cofhe-contracts to be installed and remapped in Foundry.
Uniswap v4 assigns hook permissions via contract address bits. For local development the aggregator skips the address validation, but production deployments must use a HookMiner-style deployer to land at an address compatible with the permissions returned by getHookPermissions.
src/
MODLAggregator.sol # Core hook aggregator
interfaces/IMODLModule.sol # Shared module interface
modules/
DynamicFeeModule.sol
WhitelistModule.sol
fhenix/
FhenixAsyncModule.sol # Async FHE computation base
FhenixCredentialsModule.sol
FhenixWhitelistModule.sol # Privacy-preserving whitelist
eigen/
EigenOracleModule.sol # Oracle consumer with freshness checks
EigenDynamicFeeModule.sol # Volatility-based dynamic fees
EigenTaskModule.sol # AVS task dispatch base
test/
MODLAggregator.t.sol # Aggregator integration tests
modules/
DynamicFeeModule.t.sol
WhitelistModule.t.sol
FhenixWhitelistModule.t.sol