Skip to main content

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.

tip

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.

MethodBehavior on OllaNotes
asset()Returns the Aztec token addressStandard
share()Returns the stAztec token addressERC-7575: share and asset are separate contracts
totalAssets()Returns total assets attributable to shareholdersProxied from OllaCore
convertToShares(assets)Standard conversion at current rateStandard
convertToAssets(shares)Standard conversion at current rateStandard
maxDeposit(address)Remaining headroom under the deposit cap, or 0 if pausedStandard-compatible
previewDeposit(assets)Shares that would be minted for assetsUse to quote minSharesOut
deposit(assets, receiver)Works, but has no slippage protectionCompatibility alias. Avoid in production
deposit(assets, recipient, minSharesOut)Preferred entry point, reverts on slippageNot part of standard ERC-4626
maxMint(address)Remaining headroom expressed in shares, or 0 if pausedStandard-compatible
previewMint(shares)Assets needed to mint sharesStandard
mint(shares, receiver)Works, but has no slippage protectionCompatibility alias. Avoid in production
⚠️maxWithdraw(address)Always returns 0Withdraw is async; use requestRedeem
previewWithdraw(assets)Reverts with OllaVault__NotSupportedAsync path has no synchronous quote
withdraw(assets, receiver, owner)Reverts with OllaVault__NotSupportedUse requestRedeem instead
⚠️maxRedeem(controller)Returns claimable shares for controller, or 0 if pausedSee note below
previewRedeem(shares)Reverts with OllaVault__NotSupportedAsync 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 redeemSee 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 with convertToShares, and remember that the instant fee is deducted on the way out (use previewInstantRedeem to get the net).
  • Queued path: there is no upper bound. Anyone can call requestRedeem at 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:

FunctionPurpose
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).interfaceId
  • type(IERC7540Operator).interfaceId
  • type(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.