Vault withdraw
GET/v1/actions/vaults/withdraw
Build calldata for an ERC-4626 vault withdraw. When the user wants the underlying back (no native unwrap), the dispatcher calls vault.withdraw / vault.redeem directly with no approval needed. When the receiver wants native ETH, falls back to the composer (unwraps WETH).
This endpoint targets passive ERC-4626 vaults. For Fluid's NFT-position margin vaults use /v1/actions/lending/withdraw.
Execution mode (mode query param)
auto(default) — direct whenreceiveAsset === underlyingand not native, otherwise composer.direct— force direct; returns 400 when not eligible.proxy— force the composer (legacy behavior).
Direct withdraw skips the share-token approval entirely — the user calls vault.withdraw(assets, receiver, owner=operator) themselves and the vault uses its own balance check (msg.sender == owner).
Assets vs shares
isShares=false(default):amountis assets — issuesvault.withdraw(assets, receiver, owner).isShares=true:amountis shares — issuesvault.redeem(shares, receiver, owner).
Withdraw all (isAll=true)
Two ways to drive a full-balance withdraw — both resolve the operator's vault-share balance and encode vault.redeem(shares, …). They differ only in where the share balance is read:
- GET +
isAll=true— worker readsbalanceOf(vault, operator)against its own configured RPC. Simple but only works when the worker can see the state (i.e. live mainnet, not fork). ReturnsBALANCE_READ_FAILEDon RPC failure. - POST +
isAll=true+ body{ "sharesRaw": "<uint string>" }— caller pre-reads the balance against any RPC (fork, custom, premium) and supplies it. The worker just trusts and encodes. Mirrors the lending simulation pattern (SimulationBody).
The POST body's amount query param is ignored when isAll=true.
Request
Responses
- 200
- 400
Transaction calldata + any approval(s) needed for the vault withdraw
Validation error