Skip to main contentA-REX Foundation

تصميم النظام · AREX-HOOK

Writing an A-REX hook

A hook is the only extension point of an A REX Core token. If you can express a rule as "given this operation on this batch between these accounts, allow or return a code", it is a hook.

Current
معرّف المستند
AREX-HOOK
الإصدار
2.0
التاريخ
2026-09-21
متوفر بالإنجليزية فقط
هذه الصفحة بالإنجليزية. فصول الورقة البيضاء والمخططات مترجمة. يبقى المعيار المعياري في المستودع؛ استخدم طلب وصول مبكر لذلك النص. وتبقى أدلة تصميم النظام وسجلات القرارات بالإنجليزية.
FieldValue
Document IDAREX-HOOK
Version2.0
Date2026-09-21
StatusCurrent
RelatedAREX-SDD-001, AREX-SPEC

A hook is the only extension point of an A-REX Core token. If you can express a rule as "given this operation on this batch between these accounts, allow or return a code", it is a hook.

1. Contract skeleton

Source: contracts/examples/MaxLotPerBuyerHook.sol, compiled and tested in CI. It imports IERC1155 from OpenZeppelin and ARexHookBase from contracts/reference/hooks/.

ARexHookBase gives you ERC-165 registration (supportsInterface(0x332afcbb)) and no-op defaults for check, onExecuted, canSend, canReceive.

2. The callback contract

CallbackCalled whenFlagConstraints
check(op, operator, from, to, id, amount, data) → bytes32before balances change, for each affected id, hooks in registration order, stops at first non-zeroHOOK_CHECKview; MUST NOT revert for policy; bytes32(0) = allowed
onExecuted(op, operator, from, to, id, amount, data)after balances changed, for each id, in orderHOOK_EXECUTEDMUST NOT call balance-changing functions of the token (the token is locked; the call reverts)
canSend(account) / canReceive(account)eligibility, per transfer and for the token's ERC-7943 viewsHOOK_ELIGIBILITYview

op values: OP_MINT = 1, OP_TRANSFER = 2, OP_BURN = 3, OP_FORCED_TRANSFER = 4, OP_TRANSFORM = 5 (for transform, inputs arrive with to == address(0) and outputs with from == address(0)).

data: the ERC-1155 data argument (or createBatch's), abi.encode(processRef) for transforms, empty for forced transfers.

3. Rules of thumb

  • Return OK for OP_FORCED_TRANSFER unless your hook exists to govern enforcement (for example, requiring a court-order reference in data). Seizures must not be blocked by expiry or eligibility rules.
  • Do not block burns unless you really mean it. Burns are write-offs and deliveries.
  • Read the batch through IARexBatch(msg.sender).batchOf(id). Do not store the token address; one hook can serve many tokens.
  • Use namespaced codes: ARexCodes.code("MYNS", "NAME") = keccak256("MYNS:NAME"). Reuse the standard codes in ARexCodes when the meaning matches; front-ends already know them.
  • Keep check cheap. It runs on every transfer of every id. Avoid unbounded loops over history; DeliveryHook keeps an O(1) lock counter for exactly this reason.
  • Constant flags. The token caches hookFlags() at registration. Changing it later has no effect until re-registration.
  • Prefer stateless hooks. If you need state (quotas, counters), write it in onExecuted, never in check.

3a. Reference hooks to copy from

HookFlagsPattern it demonstrates
EligibilityHookCHECK, ELIGIBILITYaccount lists; sanctions with source and TTL
ExpiryHookCHECKstateless rule from the batch record
AttestationHookCHECKrule that consults IARexAttest
PerishabilityHookCHECKper-commodity config with per-batch override; value views
SeasonalHookCHECKbounded configuration (≤ 16 windows per key)
DeliveryHookCHECK, EXECUTEDstate machine; unit locks; settlement via transfer data; O(1) check
TraceabilityHookEXECUTEDobserver with emit-only vs persist modes

4. Testing a hook

Use the fixtures in test/standard/helpers.js:

RecordingHook (records every callback, can be told to reject) and ReentrantHook (tries to re-enter) in contracts/reference/hooks/mocks/ are useful for pipeline tests.

5. Wrapping an ERC-3643 compliance module

An ERC-3643 IModule exposes moduleCheck(from, to, value, compliance). A thin hook can call it for OP_TRANSFER and map false to a code, so existing compliance logic (country restrictions, max balance, time locks) is reusable on batch tokens. The reverse direction — an A-REX hook as an ERC-3643 module — is equally mechanical.

6. Registering on a token

Order matters: put cheap, high-rejection hooks first (sanctions, pause-like rules), expensive ones last.