Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.x402r.org/llms.txt

Use this file to discover all available pages before exploring further.

What are hooks

Hooks are pluggable contracts that update state after an action successfully executes on a PaymentOperator. Each operator has 5 hook slots, one per action:
SlotRecords after
AUTHORIZE_POST_ACTION_HOOKAuthorization (for example, timestamp)
CHARGE_POST_ACTION_HOOKCharge event
CAPTURE_POST_ACTION_HOOKCapture from escrow
VOID_POST_ACTION_HOOKVoid
REFUND_POST_ACTION_HOOKRefund (after capture)
These are the hook half of the operator’s 10 slots. For the full slot layout alongside the pre-action conditions, see PaymentOperator: 10-slot configuration.

IHook Interface

interface IHook {
    function run(
        AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
        uint256 amount,
        address caller,
        bytes calldata data
    ) external;
}
Parameters:
  • paymentInfo, The payment information struct
  • amount, The amount involved in the action
  • caller, The address that executed the action (msg.sender on operator)
  • data, Arbitrary data forwarded from the caller (signatures, proofs, attestations)

Default behavior

Hook slot = address(0): no-op (does nothing). The operator records no state for that slot. Set hooks only on the slots where you want state tracking. Leave the rest as address(0).

BaseHook

All built-in hooks extend BaseHook, which verifies that the caller is an authorized operator. This prevents unauthorized contracts from writing state.

Choosing a recording strategy

Not every payment needs on-chain hooks. Choose based on your use case:

Events only (~0 extra gas)

The operator already emits an event for every action (AuthorizeExecuted, CaptureExecuted, and the same shape for the rest). If you only need payment history for analytics or display, skip hooks entirely and index events off-chain. Best for: micropayments, high-volume payments where gas overhead matters, simple UIs.

Events plus subgraph (richest queries)

Index operator events with a subgraph for rich queries (payment history by payer, receiver, status, date range). No on-chain hook gas cost. Best for: analytics dashboards, payment history, cross-payment queries. Trade-off: requires subgraph infrastructure (semi-centralized).

On-chain hooks (~20k gas per write)

Use hooks when you need on-chain reads: other contracts or conditions that depend on recorded state. EscrowPeriod is the most common example. It records authorization time so the capture condition can check if the escrow window has passed. Best for: escrow enforcement, dispute evidence, decentralized frontends, on-chain composability. Trade-off: ~20k gas per SSTORE operation.

Decision table

NeedStrategyHook slots
Payment history for UIEvents onlyaddress(0)
Rich queries, analyticsEvents + Subgraphaddress(0)
Time-locked releasesOn-chainEscrowPeriod on AUTHORIZE_POST_ACTION_HOOK
On-chain payment indexOn-chainPaymentIndexRecorderHook
Many data pointsOn-chainHookCombinator
For most configurations, you only need a hook on the AUTHORIZE_POST_ACTION_HOOK slot (for EscrowPeriod). Leave other hook slots as address(0).

Next Steps

AuthorizationTimeRecorderHook

Record authorization timestamps.

PaymentIndexRecorderHook

Index payments for on-chain queries.

HookCombinator

Chain hooks into one slot.

Custom Hooks

Build your own hook.