Skip to content

feat: add TokenSafetyHook and ITokenSafetyOracle#20

Open
JhiNResH wants to merge 1 commit intoerc-8183:mainfrom
JhiNResH:feat/token-safety-hook
Open

feat: add TokenSafetyHook and ITokenSafetyOracle#20
JhiNResH wants to merge 1 commit intoerc-8183:mainfrom
JhiNResH:feat/token-safety-hook

Conversation

@JhiNResH
Copy link
Copy Markdown

@JhiNResH JhiNResH commented Mar 27, 2026

TokenSafetyHook v2

Gates job funding when payment token is flagged as unsafe by an external oracle.

Changes from v1

Issue Fix
Wrong FUND_SEL selector Inherit BaseACPHook, override _preFund — no manual selector routing
Token decoded from callback data (wrong field) Read paymentToken from getJob(jobId)
Upgradeable + provider-specific framing Non-upgradeable, aligned with base hook style

How it works

  1. fund(jobId, ...) triggers beforeAction_preFund
  2. Read job.paymentToken from AgenticCommerce.getJob(jobId)
  3. If whitelisted → pass through
  4. Else query ITokenSafetyOracle → if verdict is blocked → revert

Files

File What
contracts/hooks/TokenSafetyHook.sol Hook implementation (~130 lines)
contracts/interfaces/ITokenSafetyOracle.sol Oracle interface (vendor-agnostic)
test/TokenSafetyHook.t.sol 9 tests

Test plan

  • forge test --match-contract TokenSafetyHookTest — 9/9 pass
  • Review: _preFund reads token from job state, not callback data
  • Review: whitelist bypass, blocked verdict bitmask, admin access

@psmiratisu
Copy link
Copy Markdown
Contributor

@JhiNResH before i do some audit on the hook. Could i suggest some key things to fix ?

  • the fund selector needs to match the real current signature
    the token source should come from the actual job state or a clearly defined param path rather than from a decode path that can read the wrong value

it would be better to align this with the shared hook pattern and keep the implementation as close as possible to the base example style, and please remove any remaining provider-specific framing. Once that is cleaned up, happy to review a narrower v2. I would treat this as a standalone policy hook, not something that should be bundled with router or attestation paths.

…job state

v2 rewrite addressing review feedback:
- Inherit BaseACPHook, override _preFund only — no manual selector routing
- Read paymentToken from getJob(jobId) instead of decoding from callback data
- Remove upgradeable pattern — align with non-upgradeable hook style
- Remove provider-specific framing (security@maiat.io → security@erc-8183.org)
- 9 tests: safe/unsafe/whitelist/no-token/admin/batch/verdict-mask
@JhiNResH JhiNResH force-pushed the feat/token-safety-hook branch from bd3a633 to 36f7c1b Compare April 15, 2026 16:10
@JhiNResH
Copy link
Copy Markdown
Author

Rewrote from scratch. All three issues fixed:

  1. Selector — now inherits BaseACPHook, overrides _preFund only. No manual selector routing.
  2. Token source — reads paymentToken from AgenticCommerce.getJob(jobId), not from callback data.
  3. Style — non-upgradeable, removed Maiat-specific framing, standalone policy hook.

9 tests cover: safe token pass, honeypot revert, whitelist bypass, no-token skip, blocked verdict mask, admin access, batch whitelist.

Force-pushed — clean single commit on top of current main.

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