This describes a pre-release version of LBAMM. Interfaces and behavior may change.
Verify the exact repository commit before building production integrations.
Custom Transfer Handlers
Custom transfer handlers let developers extend how swap input tokens are supplied to LBAMM during swap finalization.
A transfer handler is not a router. It is a settlement module invoked by the AMM core to obtain the swap’s input tokens, while receiving full context about the swap that just executed.
This page describes the interface, the transferData encoding used by LBAMM, callback behavior, and the most important safety constraints for building handlers that are compatible with hooks and integrators.
Required interface
Custom handlers must implement ILimitBreakAMMTransferHandler.
Call timing and callback flow
ammHandleTransfer is called by the AMM core during swap finalization.
Handlers may return callbackData. If non-empty, the AMM will execute that callback on the handler after the swap finalizes.
Key points:
- The callback is a normal call to the handler (not a delegatecall).
- The AMM does not (and cannot) enforce any handler-internal authorization checks; handlers should validate
msg.sender == AMMif they require that property.
If your handler does not need a post-finalization callback, return empty bytes.
Relationship to token hooks
Token hooks can observe which handler is used via SwapContext.transferHandler.
Important implications:
- Tokens may restrict which handlers they allow.
- If your handler changes which party is effectively “on the other side” of settlement (e.g., masking the maker/taker), some tokens may require additional validation.
validateHandlerOrder is handler-controlled
Token hooks define:
validateHandlerOrder(...)
This function is not called by the AMM core. A custom handler may choose to call it (e.g., during order creation) if the token expects handler-level validation.
This decision is part of the handler’s compatibility contract with token hooks and integrators.
Safety and correctness requirements
Restrict who can call ammHandleTransfer
Handlers should generally require:
msg.sender == AMM
The AMM cannot enforce handler-internal access control; this is part of the handler’s responsibility.
Don’t trust transferExtraData
- Validate length and decoding
- Validate any embedded addresses (e.g., recipient / maker)
- Validate any slippage bounds encoded in extra data
Settlement invariants
At minimum, the handler must ensure:
- the AMM receives the required
amountInofswapOrder.tokenInby the end of handler execution - no party can cause the handler to overpay relative to its authorization model
Executor identity matters
LBAMM treats executor as the authoritative identity for the swap. If your handler introduces a separate authorization layer (permits, signatures, whitelists), bind it to executor explicitly if required.
Handle non-standard ERC-20 behavior
If your handler maintains internal balances, be aware that non-standard tokens (rebasing, fee-on-transfer, external balance adjustments) can cause drift between internal accounting and onchain balances.
Minimal integration checklist
When shipping a custom transfer handler, make sure you can answer:
- What bytes format does my handler expect in
transferExtraData? - Does my handler ever require
swapOrder.recipient == address(this)? - What authorization model is used (signature, deposit, allowlist, hook)?
- How does it bind or validate
executor? - Does it need a post-finalization callback? If so, what does it do?
- Does it call token hook
validateHandlerOrderat any point? If yes, what is the schema ofhandlerOrderParams?
