Aqua0
Developers

Async redeem semantics

Sync vs. async vault withdrawals, the settlement guard, and the never-trapped invariant.

Aqua0's vaults are per-asset, per-chain ERC-4626 vaults (e.g. Base aqUSDC and Unichain aqUSDC are separate vaults with independent share prices) that additionally implement ERC-7540 for the case where your shares represent capital currently deployed rather than idle. This page explains when you get an instant redemption versus a request/claim flow, and the guarantee that backs the async path.

The vault API reference endpoints referenced below (prepare-redeem, prepare-request-redeem, claim, withdrawability, pending-requests) are not yet published. The API reference tab auto-generates from the live OpenAPI spec once the backend ships these routes; this page describes the on-chain/protocol semantics you should expect ahead of that. Check API overview for current endpoint availability.

Overview

Every deposit mints vault shares against totalAssets() = idle + deployedAssets. Which redemption path applies depends only on whether the assets backing your redemption are currently idle in the vault or out working at a venue via an adapter — you don't choose the path, the vault determines it.

Sync vs async paths

Sync (free balance)Async (deployed capital)
Applies whenThe vault has enough idle balance to cover the redemptionThe redemption requires unwinding/settling deployed capital
CallStandard ERC-4626 redeemERC-7540 requestRedeem → wait → claim
LatencyImmediate, same transactionRequest now, claim once claimable (see below)
Share price usedCurrent, at time of redeemLocked in at request time per ERC-7540 semantics

If you don't know in advance which path a given redemption will take, call the withdrawability check first (see Status & errors for the general polling pattern this follows).

Requesting a redemption

For deployed capital, requestRedeem starts the async flow. The vault does not immediately move assets — it records the request and begins freeing the underlying position (e.g. unwinding an adapter position, waiting for a cross-chain settlement to land). This is not a delay imposed for its own sake; it reflects that the capital is genuinely in use elsewhere at request time.

The settlement guard

A pending request becomes claimable when either:

  1. Attested-free — the protocol's signer attests that the underlying capital backing the request has actually been freed (adapter unwound, settlement landed), or
  2. Timeout backstopnow >= requestTime + timeout[route] elapses, regardless of attestation.

Every route's timeout is itself bounded: timeout[route] <= GLOBAL_MAX_TIMEOUT, an immutable 7-day ceiling that no owner, governance, or upgrade path can raise. Beta ships tighter defaults — same-chain routes at 1 hour, cross-chain routes at 12 hours — chosen conservatively above measured settlement latency, with room to tighten further as real production data comes in. They can only ever be tuned down toward the observed latency, never up past the 7-day ceiling.

Never-trapped invariant

This two-path guard is what makes the design never-trapped: even in a worst case where the attestation path fails entirely (e.g. the attesting signer is offline), every request still becomes claimable on its own once its timeout elapses — at most 7 days after the request, by construction. There is no scenario in which a valid redemption request can be withheld indefinitely.

Claiming

Once a request is claimable, call claim to receive the underlying assets. Claiming does not require the original attestation to still be valid — the guard condition is evaluated at claim time using the same attested-free OR timeout-elapsed logic, so a request that only clears via the timeout backstop claims exactly the same way as one that clears via attestation.

Per-chain share isolation and the cross-chain filler caveat

Shares are not fungible across chains: Base aqUSDC and Unichain aqUSDC are separate vaults with independent share prices, each reflecting only that chain's realized and reported PnL.

This does not mean capital deposited on one chain can only ever be used on that same chain. Chain-A vault capital can still back a strategy or filler that executes on Chain-B — that's a deliberate, first-class case, not a contradiction of per-chain isolation. It's precisely why the hybrid PnL model (see Non-custodial design) needs a bounded cross-chain reporter in the first place: the Chain-A vault needs a way to value capital that is currently working on Chain-B, before the cross-chain settlement lands and becomes an on-chain fact.

Status & error states

Track a pending redemption the same way you'd track a swap (see Status & errors for the general pattern):

  • requestedrequestRedeem succeeded, capital-freeing in progress
  • claimable (attested) — signer attested the capital is free; claim now for the fastest path
  • claimable (timeout) — the per-route timeout elapsed; claim now
  • claimed (terminal, success)

Treat "requested" as expected/normal for deployed-capital redemptions on any route, especially cross-chain ones — it is not an error state. Only escalate if a request is not claimable well past its route's timeout, which should not be possible by design.

FAQ

Can a redemption ever be permanently stuck? No — by design every request is claimable within its route's timeout, and every route's timeout is capped by the immutable 7-day GLOBAL_MAX_TIMEOUT. See "Never-trapped invariant" above.

Does requesting a redemption lock in my share price immediately? Yes, per ERC-7540 semantics — the exchange rate is fixed at request time, not at claim time.

Why would my redemption go through the async path instead of instantly? Only when the vault doesn't have enough idle balance to cover it — i.e. your shares represent capital currently deployed via an adapter rather than sitting idle in the vault.

On this page