Skip to content

feat(periphery): add module validation hook#318

Open
zhongeric wants to merge 18 commits intodevfrom
feat/periphery/moduleValidationHook
Open

feat(periphery): add module validation hook#318
zhongeric wants to merge 18 commits intodevfrom
feat/periphery/moduleValidationHook

Conversation

@zhongeric
Copy link
Contributor

@zhongeric zhongeric commented Feb 4, 2026

Summary

Adds ModularValidationHook, a periphery validation hook that composes multiple independent IValidationHook modules behind a single hook address. This allows auction deployers to run parallel validation checks (e.g. gating + KYC + rate-limiting) without complex inheritance, while remaining discoverable to offchain integrators via ERC-165 and on-chain getters.

Key features

  • Module composition — Initialize with an array of Module structs, each wrapping an IValidationHook with hasHookData and allowRevert flags
  • Cached hook data — Modules can pre-set signed/trusted hook data on behalf of users (setHookData), which takes priority over user-provided calldata to prevent relay tampering
  • Hook data lifecycle — Cached data supports requireSenderIsOwner, isReplayable, and validUntilBlock expiry; non-replayable data is consumed on use
  • Graceful degradation — Modules with allowRevert = true are skipped on failure; others bubble up wrapped revert reasons via CustomRevert
  • Simulationsimulate() dry-runs validation and returns the revert reason (if any) without reverting the caller
  • RenameModuleValidationHookModularValidationHook, ValidationModuleLibModuleLib

Interaction flow

sequenceDiagram
    participant Auction as ContinuousClearingAuction
    participant MVH as ModularValidationHook
    participant HookA as ValidationHook A
    participant HookB as ValidationHook B

    Note over MVH: Initialized with Module[]<br/>(HookA: hasHookData=true, HookB: hasHookData=false)

    Auction->>MVH: validate(maxPrice, amount, owner, sender, hookData)
    MVH->>MVH: Decode hookData as bytes[]<br/>Load moduleIds from storage

    loop For each module
        alt Module has cached hookData
            MVH->>MVH: Load cached ModuleHookData<br/>(check sender/expiry/replay)
        else Module needs provided hookData
            MVH->>MVH: Search provided bytes[] for matching moduleId
        end
        MVH->>HookA: validate(maxPrice, amount, owner, sender, moduleHookData)
        HookA-->>MVH: success / revert
        MVH->>HookB: validate(maxPrice, amount, owner, sender, "")
        HookB-->>MVH: success / revert
    end

    MVH-->>Auction: success / revert (ValidateReverted)

    Note over HookA,MVH: Modules can also write cached data:
    HookA->>MVH: setHookData(moduleId, owner, ModuleHookData)
    HookA->>MVH: deleteHookData(moduleId, owner)
Loading

Test plan

  • Unit tests in ModuleValidationHook.t.sol covering initialization, hook data lifecycle, revert bubbling, simulation, and gas snapshots

🤖 Generated with Claude Code

@zhongeric zhongeric changed the base branch from main to dev February 19, 2026 15:34
@zhongeric zhongeric marked this pull request as ready for review February 19, 2026 15:34
@zhongeric zhongeric requested a review from a team as a code owner February 19, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant