Overview
SyncRedeemQueue extends SyncQueue to provide instant redemptions. The user’s shares are burned and the underlying asset is sent to a receiver in the same transaction, priced at the latest oracle report for the asset.
There is no request, no batch processing and no claim step. To protect the vault, every redemption must fit within three limits:
- Oracle freshness: the latest report must be non-suspicious and no older than
maxAge. - Liquidity: the vault and its subvaults must hold enough liquid assets.
- Daily limit: a rate limit on how many shares can be redeemed over time, shared by all users of the queue.
Key features
- Assets paid out in the same transaction as the redemption
- Pricing from the latest non-suspicious oracle report, no older than
maxAge - Optional
penaltyD6haircut on redeemed shares, kept by remaining holders - Vault redeem fee applied to every redemption
- Liquidity pulled from subvaults through the queue’s redeem hook
- Leaky-bucket daily limit, denominated in shares
Parameters
dailyLimit must divide evenly by 86400 so that usage decays at an exact whole-share rate per second. A dailyLimit of 0 blocks all redemptions through the queue.
Parameters are set at creation and can be updated with setSyncRedeemParams(penaltyD6, maxAge, dailyLimit). The caller must hold SET_SYNC_REDEEM_PARAMS_ROLE on the vault:
dailyLimit, then stores the new values.
Creation
Create the queue through the vault with the redeem queue factory version registered forSyncRedeemQueue (version 2 in the standard deployment):
Function: redeem
- Reverts with
ZeroValueifsharesis zero orreceiveris the zero address. - Reverts with
QueuePausedif the vault has paused the queue. - Reads the latest report with
oracle.getReport(asset):- Reverts with
InvalidReportif the report is suspicious or its price is zero. - Reverts with
StaleReportifreport.timestamp + maxAge < block.timestamp.
- Reverts with
- Applies the penalty:
sharesToRedeem = shares * (1e6 - penaltyD6) / 1e6. - Computes
feeShares = feeManager.calculateRedeemFee(sharesToRedeem)and subtracts them fromsharesToRedeem. - Converts to assets:
assets = sharesToRedeem * 1e18 / priceD18. Reverts withZeroValueifassetsis zero. - Reverts with
InsufficientAssets(assets, available)ifassetsexceedsvault.getLiquidAssets(). - Synchronizes the bucket and reverts with
DailyLimitOverflowifsharesexceeds the remaining capacity. Otherwise addssharestousage. - Burns the full
sharesamount from the caller. Share manager restrictions apply, including global lockup, blacklist and burn pause. - Mints
feeSharesto the fee recipient. - Calls
vault.callHook(assets). The redeem hook pulls any missing liquidity from subvaults into the vault, then the vault transfersassetsto the queue. - Sends
assetstoreceiver. - Calls
riskManager.modifyVaultBalance(asset, -assets). - Emits
Redeemed(account, shares, assets, feeShares).
Liquidity
getLiquidAssets() returns the result of vault.getLiquidAssets() for this queue. The vault resolves the queue’s redeem hook (custom or default):
- With a hook such as
BasicRedeemHook, liquidity is the vault’s balance plus the balances of subvaults where the asset is allowed. - Without a hook, liquidity is the vault’s own balance only.
Daily limit
The daily limit is a leaky bucket measured in shares, before the penalty and fee:- Each redemption adds its
sharestousage. usagedecays linearly atdailyLimit / 86400shares per second.- Remaining capacity is
dailyLimit - usage, after decay.
2 * dailyLimit shares can be redeemed within some 24-hour windows: the full bucket at the start, plus a full refill over the following 24 hours. Size risk limits with this burst in mind.
The bucket is shared by all users of the queue. One holder can use the whole remaining capacity, and other users then wait for it to refill.
Estimating assets
To preview a redemption, read the same values the contract uses:View functions
Events
shares in Redeemed is the total amount burned from the account. assets is the amount sent to the receiver.
Errors
Differences from RedeemQueue
Design considerations
These points come from the MixBytes audit ofSyncRedeemQueue (July 2026). The findings were acknowledged as intended behavior.
- Stale-price window. Redemptions are priced at a report that can be up to
maxAgeold. KeepmaxAgeclose to the oracletimeout, which is about one day in Mellow’s deployments. AmaxAgeshorter than the reporting cadence makes the queue revert withStaleReportbetween reports.penaltyD6is expected to stay at0in normal operation. - Priority over async redemptions. The liquidity check does not reserve assets already owed to priced but unsettled
RedeemQueuebatches. When both queue types are active, sync redemptions take priority, and the curator must keep enough liquidity buffer for both. - Protocol fee. Shares burned between reports are not in the supply at the next report, so the time-based protocol fee for that interval is not charged on them.
- Oracle outage. If reports stop or are flagged suspicious, sync redemptions revert until a valid report is available. The async
RedeemQueueremains available if the vault has one. - Native ETH. The queue accepts ETH from the vault during payout. Do not send ETH to the queue directly, and do not set the queue as
receiver: those funds cannot be recovered.
Audit
SyncRedeemQueue was audited by MixBytes in July 2026. See Security.