What an adaptor must do
The interface:
AdaptorBase gives you the pool lookups. getAsset(assetId) and getAssetId(address) revert if the asset is not active, so you do not need to check that yourself. It also defines the errors ZeroValue, UnsupportedAsset and InvalidInputAssetLength.
Write the adaptor
This example deposits into an ERC-4626 vault and redeems from it. It compiles against the protocol repo. It has not been run against a pool, so treat it as a starting point and not as an audited adaptor.- Slippage. Put a minimum output in the payload and revert below it, as
minOutdoes here. The Uniswap adaptor does the same. Nobody else will protect the user. - Recipient. Return outputs to
address(this), the handler, so the pool turns them into notes for the user. The Uniswap adaptor also accepts abeneficiaryaddress. If it is set, the swap pays that public address and the adaptor returns no outputs. That sends the result outside the pool and shows the destination. - Payload. Keep it small and make it decode in one
abi.decode. The payload is public. - One input asset is the common case. The handler can pass several, but each extra input asset needs its own check in your code.
- Anything that cannot finish in one call leaks. The Lido unstake path asks for a
withdrawAddressbecause Lido queues the withdrawal and pays later. Say so in your adaptor’s notes.
Register it
Only the pool owner can register an adaptor, withaddAdaptorSupport. The pool checks the adaptor address named in the transaction against that list and rejects any other. Output tokens must already be active assets in the pool, and the owner adds them with the pool’s asset functions. How to ask for both: [ADAPTOR_ONBOARDING_PROCESS].
Adaptors are stateless, so registering a new one does not need an upgrade of the pool.
Call it from the SDK
An adaptor call is aCALL_ADAPTER transaction. to is the adaptor address. assetIds and values are the tokens you send in. payload is what your handleAssets decodes.
- Gas. An adaptor call runs your code and the protocol’s code in one transaction. On the bundler path, pass a larger
callGasLimitthan a plain transfer needs. A vault deposit needs more than a swap. The app sets this per adaptor. - Public data. The input tokens, the amounts, the adaptor and the payload are public. The output amounts are public too, because the pool builds the output notes from what the adaptor returns.
Test it
The protocol repo tests each adaptor against a fork of the network it targets. A test deploys the adaptor at the fixed address that a recorded proof names, sends that shielded transaction through a pool fixture and checks the result. The proof binds the adaptor address, so a new adaptor needs a new recorded proof. Add a test in the same style undertest/adaptors/.
Next
- SDK reference for
TransactionRequestandTransactionOptions. - Troubleshooting for adaptor errors.