Concrete — Complete GuideIndependent guide, unofficial

03

Async (queued) withdrawals - deep dive

Level: Advanced

State machine (per epoch, simplified)

OPEN ── closeEpoch() (cutoff) ──► CLOSED ── processing ──► PROCESSED ── claim ──► CLAIMED
  │                                  │
  └ user may cancel                  └ user locked in; WITHDRAWAL_MANAGER may
                                       moveRequestToNextEpoch(...)
  • Request: shares are transferred into vault custody; the request is recorded (QueuedWithdrawal).
  • Cutoff: closeEpoch() freezes the epoch. After this the user cannot cancel.
  • Processing: share price locked, shares burned, assets reserved from unallocated balance first, then the Allocator deallocates from strategies along the deallocation order.
  • Claim: user calls claim; assets leave the vault (RequestClaimed).
  • Rollover: if a cap or delay leaves a request unprocessed, it moves to the next epoch (RequestMovedToNextEpoch), preserving FIFO order.

Roles

RolePower
WITHDRAWAL_MANAGERAdvances epochs (close → process → claim); can move requests to next epoch; can process a partial epoch request for a closed-but-unprocessed epoch (epochID == latestEpochID − 1) at the current exchange rate.
PRIORITY_WITHDRAWAL_EXECUTORFast-path: settle a user's queued shares against the active epoch immediately, paying grossAssets − unwindCost.

Priority withdrawal cost bound

unwindCost is supplied by the executor at call time but must be ≤ the admin cap unwindCostCapBP (default 500 bps, ceiling 10,000 bps, set via setUnwindCostCap); above the cap the call reverts. unwindCost is debited from the strategy's reported allocation (via async accounting), and the next accrual reconciles. This is a trusted operational role, not automatic.

Invariants enforced on allocation

Postconditions after allocate(...): idle balance must cover locked assets and, on async vaults, past-epoch unclaimed assets. This protects claims that are already reserved.

Caps (per epoch)

Cap = % of vault TVL processed per epoch. If requests ≤ cap: process normally. If > cap: process up to cap in FIFO, roll the rest. Waiting users keep earning (their shares are not burned until processed) but their final price is set at processing.

Cooldown/lock interplay

DepositLockHook / DepositLockWithFeeHook prevent locked shares from being withdrawn, redeemed or transferred until unlock. Early unlock costs a decaying fee in shares.

Failure modes to understand

ScenarioEffect
Strategy accounting push lateVault halts (incl. epoch processing) until fixed
Strategy missing from deallocation orderAssets counted but unavailable for withdrawals
Cap binds in a run on the vaultMulti-epoch queue; FIFO
Vault pausedCan't be upgraded until unpaused

Reading queue state programmatically

Use the subgraph: Vault.isQueueActive, currentEpoch, latestProcessedEpoch, pastEpochUnclaimedAssets, currentEpochRequestedShares, and the WithdrawalQueue / PriorityWithdrawalClaimed / PartialEpochRequestProcessed entities. See Subgraph guide.