Skip to content

feat: WalletStateHook — condition-based wallet-state gating for _preFund#33

Open
douglasborthwick-crypto wants to merge 4 commits intoerc-8183:mainfrom
douglasborthwick-crypto:feat/wallet-state-hook
Open

feat: WalletStateHook — condition-based wallet-state gating for _preFund#33
douglasborthwick-crypto wants to merge 4 commits intoerc-8183:mainfrom
douglasborthwick-crypto:feat/wallet-state-hook

Conversation

@douglasborthwick-crypto
Copy link
Copy Markdown

Summary

Adds a minimal ERC-8183 hook that gates the fund stage on a condition-based wallet-state verifier. Complements existing score-based gating (TrustGateHook, #9/#32) and content-based verification (ReasoningVerifierHook, #31) with a third shape: does this wallet satisfy a named condition set right now?

  • Score-based (TrustGateHook) — "reputation ≥ N"
  • Content-based (ReasoningVerifierHook) — "output verified, confidence ≥ N"
  • Condition-based (WalletStateHook, this PR) — "wallet passes condition set X (e.g. USDC ≥ 1000 on Base, KYC attested, NFT held)"

What's added

File Purpose
contracts/interfaces/IWalletStateVerifier.sol Minimal (bool verified, uint256 validUntil) interface keyed on (wallet, conditionsHash). Hooks remain stateless views.
contracts/hooks/WalletStateHook.sol Inherits BaseERC8183Hook + IERC8183HookMetadata. Immutable verifier + conditionsHash (deploy one hook per distinct set, mirrors the minConfidence pattern in #31). Overrides _preFund only.
contracts/examples/InsumerWalletStateVerifier.sol Reference IWalletStateVerifier implementation. Relayer-push model with optional RIP-7212 P256VERIFY precompile verification of off-chain ECDSA P-256 (ES256) attestation signatures.
test/WalletStateHook.t.sol 21 tests, all passing.

Design intent

Keep the core hook small, generic, and aligned with the current hook stack:

  • BaseERC8183Hook-native
  • Verifier-agnostic (interface-only dependency)
  • Minimal surface area — overrides _preFund only
  • Product-specific example separated from the core hook under contracts/examples/

Gate stage

_preFund — gates the client wallet before escrow forms. Parallels TrustGateHook's _preFund stage (score threshold) and ReasoningVerifierHook's _preSubmit stage (deliverable hash), so readers see a clean three-way contrast at distinct lifecycle points.

Verification model

The example verifier supports two modes:

  1. Optional RIP-7212 verification — if a P-256 public key is configured at construction, the relayer's submission must carry the off-chain attestation signature components (r, s, messageHash), which are verified via the RIP-7212 precompile before the attestation is stored. Zero trust in the relayer.
  2. Trusted relayer fallback — if pubKeyX = pubKeyY = 0, signature verification is skipped and the relayer is trusted. Useful for testnets or deployments where off-chain signature verification is performed by an independent auditor.

RIP-7212 is live on Base, Optimism, Arbitrum, Polygon, Scroll, ZKsync, Celo — the standard ERC-8183 L2 footprint.

Verification

  • forge build ✅ (only pre-existing lint notes matching current codebase style)
  • forge test --match-path test/WalletStateHook.t.sol ✅ 21/21 pass

Dependency on #30

This branch is stacked on #30 (IACPHook → IERC8183Hook rename) so the new files compile against the post-rename base. Will rebase cleanly once #30 merges.

ariessa and others added 2 commits April 17, 2026 16:17
Adds a minimal ERC-8183 hook that gates the fund stage on a condition-based
wallet-state verifier. Complements existing score-based gating (TrustGateHook,
erc-8183#9/erc-8183#32) and content-based verification (ReasoningVerifierHook, erc-8183#31) with a
third shape: "does this wallet satisfy a named condition set right now?"

- contracts/interfaces/IWalletStateVerifier.sol
    Minimal (bool verified, uint256 validUntil) interface keyed on
    (wallet, conditionsHash). Hooks stay stateless views.

- contracts/hooks/WalletStateHook.sol
    Inherits BaseERC8183Hook + IERC8183HookMetadata. Immutable verifier +
    conditionsHash (deploy one hook per distinct condition set, mirrors the
    minConfidence immutable pattern in ReasoningVerifierHook). Overrides
    _preFund only — verifier.checkWalletState(caller, conditionsHash) →
    pass/fail + freshness, reverts otherwise.

- contracts/examples/InsumerWalletStateVerifier.sol
    Reference IWalletStateVerifier implementation. Relayer-push model with
    optional RIP-7212 P256VERIFY precompile verification of off-chain ECDSA
    P-256 (ES256) attestation signatures. Works on Base, Arbitrum, Optimism,
    Polygon, Scroll, ZKsync, Celo — standard ERC-8183 L2 footprint.

- test/WalletStateHook.t.sol
    21 tests, all passing. Covers constructor guards, _preFund happy path,
    not-verified revert, expired-attestation revert, validUntil boundary,
    selector isolation, ERC-165 interface support, verifier relayer auth,
    and signature-mode flag.

Stacked on top of erc-8183#30 (IACPHook → IERC8183Hook rename). Targets main;
will rebase cleanly once erc-8183#30 merges.
…w, credentials

Follow-ups per CONTRIBUTING.md on PR erc-8183#33:

- WalletStateHook.sol: expand NatSpec to match BiddingHook/FundTransferHook style
  with USE CASE / FLOW / TRUST MODEL sections + Profile A label.

- InsumerWalletStateVerifier.sol: add credentials block covering both paths —
  developers via POST /v1/keys/create (email-based, free tier) and agents via
  POST /v1/keys/buy (wallet-based, no email, USDC/BTC payment proves identity).

- README.md: add WalletStateHook row to the Hook Examples table, Profile A.

No code changes — docs only. forge build clean, forge test 21/21 pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants