Instant Withdrawals | Tesseract Documentation

For the complete documentation index, see llms.txt. This page is also available as Markdown.

For amounts that fit within the vault's available liquidity, withdrawal is a single transaction. Call withdraw (specifying an asset amount) or redeem (specifying a share amount) and receive the underlying asset in the same block.

There is no reliable on-chain view for "how much can clear instantly right now" — the vault's standard ERC‑4626 maxWithdraw / maxRedeem don't reflect the real instant-withdrawal capacity. The correct pattern is to try the instant call (or simulate it first) and fall back to the scheduled flow if it reverts.

Withdraw

const vaultAbi = [{
  type: 'function', stateMutability: 'nonpayable', name: 'withdraw',
  inputs: [
    {name: 'assets',   type: 'uint256'},
    {name: 'receiver', type: 'address'},
    {name: 'owner',    type: 'address'},
  ],
  outputs: [{name: 'shares', type: 'uint256'}],
}] as const

await walletClient.writeContract({
  address: vault,
  abi: vaultAbi,
  functionName: 'withdraw',
  args: [assets, receiver, owner],
})

receiver gets the asset; owner is the wallet whose shares are burned. For a straightforward own-withdrawal, receiver === owner === msg.sender.

Redeem (by share count)

await walletClient.writeContract({
  address: vault, abi: vaultAbi, functionName: 'redeem',
  args: [shares, receiver, owner],
})

Use redeem when you want to burn a specific share count (e.g. "withdraw half of my position"). Use withdraw when you want a precise asset amount out.

Falling back to scheduled

If the requested amount exceeds what the vault can free instantly, the call reverts. Detect this and fall back. Two patterns:

Simulate first, then send. Cleaner for production — you learn whether the call will succeed before asking the user to sign:

try {
  await client.simulateContract({
    address: vault, abi: vaultAbi, functionName: 'withdraw',
    args: [assets, receiver, owner],
    account: owner,
  })
  // Simulation succeeded — send the real transaction
  await walletClient.writeContract({
    address: vault, abi: vaultAbi, functionName: 'withdraw',
    args: [assets, receiver, owner],
  })
} catch (err) {
  // Instant path can't satisfy — request a scheduled withdrawal
  await requestScheduledWithdrawal(shares)
}

Try directly, catch on revert. Simpler, but costs the user a rejected signature / failed tx:

try {
  await walletClient.writeContract({
    address: vault, abi: vaultAbi, functionName: 'withdraw',
    args: [assets, receiver, owner],
  })
} catch (err) {
  await requestScheduledWithdrawal(shares)
}

Continue to Scheduled Withdrawals for the larger-amount flow.