ERC-4626 Compatibility
Olla is an async vault (ERC-7540) that also exposes the ERC-4626 function surface. Some ERC-4626 methods behave differently from a synchronous vault, and a few revert or return zero because they have no meaningful definition in an async model. This page is the reference for what actually happens when you call each method.
If you're writing a generic ERC-4626 adapter, read this page first. Assumptions that hold for a synchronous vault will cause silent failures or reverts on Olla.
Method behavior table
Legend: ✅ safe to use, ⚠️ works but has non-standard semantics (read the notes), ❌ do not use in production.
| Method | Behavior on Olla | Notes | |
|---|---|---|---|
| ✅ | asset() | Returns the Aztec token address | Standard |
| ✅ | share() | Returns the stAztec token address | ERC-7575: share and asset are separate contracts |
| ✅ | totalAssets() | Returns total assets attributable to shareholders | Proxied from OllaCore |
| ✅ | convertToShares(assets) | Standard conversion at current rate | Standard |
| ✅ | convertToAssets(shares) | Standard conversion at current rate | Standard |
| ✅ | maxDeposit(address) | Remaining headroom under the deposit cap, or 0 if paused | Standard-compatible |
| ✅ | previewDeposit(assets) | Shares that would be minted for assets | Use to quote minSharesOut |
| ❌ | deposit(assets, receiver) | Works, but has no slippage protection | Compatibility alias. Avoid in production |
| ✅ | deposit(assets, recipient, minSharesOut) | Preferred entry point, reverts on slippage | Not part of standard ERC-4626 |
| ✅ | maxMint(address) | Remaining headroom expressed in shares, or 0 if paused | Standard-compatible |
| ✅ | previewMint(shares) | Assets needed to mint shares | Standard |
| ❌ | mint(shares, receiver) | Works, but has no slippage protection | Compatibility alias. Avoid in production |
| ⚠️ | maxWithdraw(address) | Always returns 0 | Withdraw is async; use requestRedeem |
| ❌ | previewWithdraw(assets) | Reverts with OllaVault__NotSupported | Async path has no synchronous quote |
| ❌ | withdraw(assets, receiver, owner) | Reverts with OllaVault__NotSupported | Use requestRedeem instead |
| ⚠️ | maxRedeem(controller) | Returns claimable shares for controller, or 0 if paused | See note below |
| ❌ | previewRedeem(shares) | Reverts with OllaVault__NotSupported | Async path has no synchronous quote. Use previewInstantRedeem for the instant path |
| ❌ | redeem(shares, receiver, controller) | Claims a finalized request for controller; does not perform a synchronous redeem | See Redemptions |
maxRedeem is not what you think
On a synchronous ERC-4626 vault, maxRedeem(owner) answers: "how many shares can this address burn for assets right now?". On Olla, it answers: "how many shares has this controller already finalized and not yet claimed?". The gap between these two definitions is usually where integrations break.
If you need the "how much can I exit right now" number, compute it yourself:
- Instant path:
availableForInstantRedemption()gives the asset ceiling. Convert it to shares withconvertToShares, and remember that the instant fee is deducted on the way out (usepreviewInstantRedeemto get the net). - Queued path: there is no upper bound. Anyone can call
requestRedeemat any time for any number of shares they own; the queue will finalize them in order as liquidity becomes available.
Functions that have no ERC-4626 equivalent
These are specific to Olla and do not appear on a standard ERC-4626 vault:
| Function | Purpose |
|---|---|
instantRedeem(shares, recipient, minAssetsOut) | Synchronous exit from the buffer, fee applies |
previewInstantRedeem(shares) | Net assets quote for the instant path |
requestRedeem(shares, controller, owner) | Enqueue an async redemption (ERC-7540) |
claimRequestById(requestId) | Claim a finalized async request by id |
pendingRedeemRequest(requestId, controller) | Shares still pending for a request |
claimableRedeemRequest(requestId, controller) | Assets claimable for a finalized request |
activeRequestIds(owner) | All request ids currently tracked for an owner |
availableForInstantRedemption() | Buffer liquidity usable by instant redemptions |
setOperator(operator, approved) | ERC-7540 operator approval |
isOperator(controller, operator) | ERC-7540 operator check |
Interface detection
supportsInterface returns true for:
type(IERC7540Redeem).interfaceIdtype(IERC7540Operator).interfaceIdtype(IERC7575).interfaceId
It does not advertise type(IERC4626).interfaceId, because several ERC-4626 methods revert or return zero. If your integration checks for ERC-4626 via ERC-165, treat a false result as expected and fall back to direct method calls or to the ERC-7540 interface.