Use cases
- Trade assets you don’t hold. Mint or wrap an asset just-in-time as a pre-hook so the PMM can pull it. Examples: RWA tokens, liquid-staking and wrapped tokens, Aave aTokens.
- Source liquidity from lending protocols. Borrow or redeem from Aave, Morpho, and similar as a pre-hook to free up the token you’re about to sell, then re-supply leftovers as a post-hook.
- Transform the output. Wrap or convert the token you receive as a post-hook.
Returning a hook
In your WebSocket quote response, add ahooks array alongside the quote. Each entry is:
| Field | Description |
|---|---|
target_contract | The contract the router calls. |
data | The payload: ABI-encoded arguments for bebopHook, or raw calldata. |
post_hook | false runs the hook before the swap (for example JIT-mint inventory), true runs it after (for example wrap the output). |
revert_on_fail | true reverts the whole swap if the hook reverts. |
use_bebop_hook | true calls IBebopHook.bebopHook, false makes a raw call with data. |
needs_approval | true makes the router approve target_contract before calling it (pre-hook: the from-token; post-hook: the PMM to-token). Set false if your hook pulls funds via the maker’s own pre-approval. |
hook_signature | The maker’s EIP-712 signature over the hook. Omit, or send null or "0x", to skip signature verification. |
flags value for you.
Signing a hook
If your hook acts on behalf of you (the maker), for example pulling your funds or minting to you, sign it. EIP-712-sign this struct:- Domain:
name = "BebopRouter",version = "1", the chain id, andverifyingContractset to the router address0xBeb0009ACa35087ce7cCF11637E24dd1Aad3bf2A. dataHash = keccak256(data).makerNonceis the same nonce as your PMM order for this quote. Issue a unique maker nonce per order, as you already do for PMM orders, and reuse it here.flagsis the same packedflagsvalue the router uses for the hook (see Flags).
BebopSettlement v2). Signing binds the hook both ways:
- The swap can’t run without your hook, or with a different one. The router folds the set of hooks into a
hooksHashthat is part of the order EIP-712 hash you sign, so the swap executes only with exactly the hooks you authorized. - The hook can’t run without the swap, and can’t be replayed. The hook signature is over your maker nonce, which the PMM settlement consumes atomically with the swap. Your authorization is used at most once, and only as part of the swap you signed.
Contract side
A hook is one entry in theHook[] array the router executes:
Flags
Theflags field packs the hook’s configuration. You compute the same value when signing.
| Bits | Field | Meaning |
|---|---|---|
0-159 | makerAddress | The maker that signed this hook. address(0) means no signature verification. |
160 | postHook | 1 runs after the swap, 0 runs before. |
161 | revertOnFail | 1 reverts the whole swap if the hook reverts. |
162 | useBebopHook | 1 calls IBebopHook.bebopHook, 0 makes a raw call with data. |
163 | needsApproval | 1 approves targetContract before calling it. |
Implementing the target
You have two ways to implement the target contract. Option A: implementIBebopHook (useBebopHook = 1). Deploy a contract the router calls with the maker address and the scaled swap legs:
makerAddress itself from the signed hook, so a malicious data can’t redirect it.
Option B: raw call (useBebopHook = 0). The router does targetContract.call(data). Use this to call an existing contract that doesn’t implement IBebopHook. The router blocks raw-call payloads whose first 4 bytes equal the bebopHook selector, to prevent bypassing the signed path.
For the full contracts, see the bebop-rfqa repository.
Example: JIT-mint an Aave aToken
Source:MakerAaveHelperHook.sol.
Suppose you want to stream and trade an Aave aToken (for example aWETH or aPOL) that you don’t actually hold. Instead of pre-minting and holding inventory, mint it just-in-time as a pre-hook:
Router calls the hook
Before the PMM swap, the router calls the hook with your maker address and the scaled swap legs.
Pull the underlying
The hook pulls the underlying (for example WETH) from your wallet, which you pre-approved.
makerAddress, so the hook only ever touches your funds for your legs.
One-time approvals (not per swap):
underlyingtoMakerAaveHelperHook, so the hook can pull the underlying from you.aTokento the settlement contract, so the PMM can pull the minted aToken from you.
bebopHook payload is just the three addresses; the router prepends your maker address when it calls: