On this page

Asynchronous Redemption

Turn a pending vault redemption into private tickets, then claim harvested assets or refund cancelled shares.

Return a ticket while redemption is pending#

Stage 1 needs an ERC-20 output before it can reserve a settlement. A queued redemption cannot deliver its underlying yet, so AsyncRedeemTicketAdapter mints tickets backed by the requested shares. The ticket becomes a private asset. Later, CLAIM exchanges it for harvested underlying and REFUND exchanges it for cancelled shares.

The test fixture uses TestAsyncRedeemVault. Its operator chooses the price and can fulfil or cancel requests. REQUEST, CLAIM and REFUND handle those results; they cannot force immediate payment. An external mainnet ERC-7540 vault needs its own review before it can use this path.

Pending, Active and Settled notes
Pending, Active and Settled notes
OperationRouteWhat the user receives
REQUEST = 0share → ticketOne ticket per native share unit while redemption is pending
CLAIM = 1ticket → underlyingValue of the oldest harvested claimable batches
REFUND = 2ticket → shareOne returned share per refunded ticket unit

Check controller consent at the venue#

The constructor calls requiresControllerConsent() and accepts exactly one canonical ABI true word. Check that the venue enforces this rule: another requester must not be able to name the adapter as controller and mix its requests with the adapter's own. ERC-7540 conformance alone is insufficient for this adapter.

F-06 records the failure when foreign requests enter that aggregate: their fulfilment can change ticket pricing or their cancellation can strand a holder's assets. The constructor now requires the consent declaration. Review the venue's implementation and upgrade authority too, since a contract can return true without enforcing the behavior.

Read the ticket partitions#

lifecycle() returns pending, claimable and refundable ticket amounts for all holders. Your account's ticket balance is a separate value. Anyone can call harvest() to collect available assets or cancelled shares from the venue. A request also harvests; a claim or refund harvests when it needs more backing. Each call collects at most one uint128-sized claimable batch plus cancelled shares.

A claim covered by already harvested assets pays its FIFO preview without reading the venue. A covered refund uses returned shares held by the adapter. Requests above the claimable or refundable partition revert. Owning pending tickets does not let the account claim underlying until the venue has fulfilled them and the backing is available.

typescript
// Read-only lifecycle and FIFO quote; ethers v5.
const tickets = new ethers.Contract(adapterAddress, [
  'function lifecycle() view returns (uint256 pending,uint256 claimable,uint256 refundable)',
  'function previewClaim(uint256) view returns (uint256)',
  'function ticket() view returns (address)',
], provider);
const { pending, claimable, refundable } = await tickets.lifecycle({ blockTag });
if (claimAmount.gt(claimable)) throw new Error('Ticket claim is not ready');
const expectedAssets = await tickets.previewClaim(claimAmount, { blockTag });
// Revalidate identities, partitions and the positive floor before proving.

Explain how batch order affects price#

Tickets from different requests are fungible. Each harvested batch keeps its share and asset amounts, and claims take the oldest remaining batch first. Partial payouts use integer rounding; taking the rest of a batch pays its remaining assets. previewClaim returns the payout for a covered claim in that state.

Two users claiming the same ticket count can receive different amounts if they consume differently priced batches. Show the latest preview and venue-wide partitions. Explain that another claim can change which batch is next before execution. The user's proof still sets the minimum underlying they will accept.

Configure deposit, request, claim and refund#

FUYU_QUEUE_ASYNC_TICKETS=1 deploys the test vault, shares, ticket adapter and deposit adapter. Admit shares and tickets, then register USDC → asyncUSDC, asyncUSDC → fASYNC, fASYNC → USDC and fASYNC → asyncUSDC. Deposit uses the fixed-share adapter; REQUEST, CLAIM and REFUND use the ticket adapter.

queue-async-tickets.cjs checks configuration, deployment blocks, runtimes and immutable addresses. The browser independently checks the Pool, all four runtimes/artifacts, their bindings, route code hash and partitions before proving. REQUEST and REFUND put their one-for-one output in the proof. CLAIM uses a positive minimum supported by the FIFO value. The relay accepts operation 2 only for the configured refund route.

Recover each output and explain what is public#

REQUEST reveals the venue and requested shares. CLAIM reveals tickets spent and underlying paid; REFUND reveals returned shares. Ticket ownership can stay private between actions, while amounts and timing can still connect them. Finalize and scan every output, including operation-2 refunds, through the ordinary action flow.

The test operator controls price, fulfilment and cancellation. A stuck request waits for that operator; harvest only collects results already available. Ticket outputs have no Optional disclosure view. Recover ticket balances and lifecycle activity from history across devices, instead of relying on a local request record.

Check which exit your client supports#

Outside the Pool, a ticket holder can approve the adapter and call claim(tickets, minimum, deadline) or refund(tickets, deadline). Those calls pay that holder from harvested backing. A Pool configuration can admit screened ticket withdrawal, but the ordinary app relay documented here accepts asyncUSDC share exits and has no general ticket-withdrawal fallback. Add and test that client flow before offering it.

NotAvailable means the chosen partition cannot cover the amount. Keep the output floor positive and wait for fulfilment or cancellation. Expired and InsufficientOutput roll back the action. Test partial fulfilment, cancellation, FIFO across batches, preview/payout equality, rollback, controller consent and account recovery. The funded-fork results cover one operator-controlled test venue.