Withdraw Flow
How Aquifer handles withdrawals when funds are deployed across protocols, and why you never see an insufficient reserves error.
The problem
When the AI deploys capital to protocols, most of the vault's USDC is not sitting in the vault contract itself. It is deployed to external adapters earning yield. If a user tries to withdraw 1,000 USDC but the vault only holds 200 USDC in reserves, a naive contract would reject the transaction with an "insufficient reserves" error.
This creates terrible UX. The user would need to wait for the agent to manually pull funds back, or the vault would need to keep a large uninvested reserve at all times, reducing yield.
The solution: auto-pull
Aquifer solves this with a public function on the vault contract called pull_from_adapter. This function moves funds from an adapter back into the vault reserves. It is public, meaning anyone can call it.
When you withdraw, the frontend detects the shortfall automatically:
shortfall = withdrawal_amount - vault_reservesIf the shortfall is greater than zero, the transaction includes a series of pull_from_adapter calls before the actual withdraw call. These pull exactly enough USDC from protocol adapters to cover your withdrawal, then the withdrawal executes normally.
Everything happens in a single Programmable Transaction Block (PTB): either all steps succeed and you receive your USDC, or the entire transaction reverts and nothing changes. There is no partial state.
Why pull_from_adapter is safe
Making this function public might seem risky, but it cannot extract money from the vault. It only moves funds from an adapter back into vault reserves. Funds stay inside the vault at all times. Nobody can use it to drain the vault or redirect funds to themselves. You still need to hold shares and call withdraw to actually receive USDC.
The withdraw button in the app shows "Pulling funds + withdrawing..." during the transaction when an auto-pull is needed. This is normal and expected.
What you see in the UI
On the Withdraw tab, the balance card shows two numbers side by side:
Your vault value: the total USDC your shares are worth right now.
Withdrawable now: how much is sitting in reserves and available without pulling from adapters.
If these numbers differ, a note explains that funds are deployed earning yield and will be pulled automatically. The withdraw button handles everything.
Transaction flow step by step
- You enter a withdrawal amount and click Withdraw USDC.
- The app fetches current vault reserves and adapter balances.
- If reserves are insufficient, it adds
pull_from_adaptercalls to the transaction, one per adapter, until the shortfall is covered. - It adds the
withdrawcall, which burns your shares and returns USDC. - It adds a
transferObjectscall to send the USDC coin to your wallet. - The entire PTB is signed and submitted in one transaction.