For the complete documentation index, see llms.txt. This page is also available as Markdown.

Synchronous flow

Deposit and redeem in a single transaction when the curator enables it, with the conditions, balance changes and gotchas of each.

When the curator enables it, a vault can skip the epoch cycle of the async flow: syncDeposit mints shares and syncRedeem pays out assets in the same transaction, priced at the current totalAssets / totalSupply. This page describes v0.6.0; where v0.5.x behaves differently, a tab shows both.

When sync is available

A sync call needs all three conditions. Read them live: the curator can change the mode and the valuation expires over time.

Condition
Read with
Sync deposit
Sync redeem

Sync mode allows it

Both or SyncDeposit

Both or SyncRedeem

Valuation still valid

true

true

Vault open

—

Open

Open

Async requests stay available alongside sync. A request made while the valuation is valid waits for the next settlement, which can only start once the valuation has expired: at the end of its lifespan, or earlier if the curator calls expireTotalAssets. A new valuation cannot be proposed while the current one is valid.

A vault where isAsyncOnly() is true has permanently given up sync: its valuation is always treated as expired.

Only deposits can be synchronous: there is no sync mode and no sync redeem. A sync deposit needs the vault to be Open and the valuation to be valid: while isTotalAssetsValid() is true deposits must be synchronous, and once it expires they must be asynchronous.

Sync deposit

Contract
Method
Balance change

Underlying asset

approve(vault, amount)

none

Vault

Asset: user → curator address (safe()). Shares minted to receiver (Transfer from address(0))

Vault

Same, with native value (msg.value != 0)

Native balance leaves the user with no ERC-20 Transfer. The pendingSilo wraps it and forwards it: Transfer pendingSilo → curator address. Shares minted to receiver

Reverts when

Condition
Error

Sync mode does not allow sync deposits

SyncOperationNotAllowed

Valuation expired

TotalAssetsExpired

Vault not Open

NotOpen(state)

msg.sender or receiver fails isAllowed (not whitelisted, blacklisted or sanctioned)

AddressNotAllowed

totalAssets() + pending deposits (underlying held by the pendingSilo) + assets > maxCap()

MaxCapReached

Native value sent but the underlying is not the wrapped native token

CantDepositNativeToken

Vault paused

EnforcedPause

Notes

  • Pass address(0) as referral when there is none. The call always emits a Referral event.

  • An entry fee (feeRates().entryRate, in bps) is taken in shares. previewSyncDeposit(assets) returns the net shares.

  • There is no slippage parameter. The price is the current valuation, and the valuation lifespan is the protection against a stale price.

  • With native value, assets is ignored and replaced by msg.value, and no approval is needed.

Reverts when

Condition
Error

Valuation expired: use requestDeposit

OnlyAsyncDepositAllowed

Vault not Open

NotOpen(state)

Whitelist enabled and an involved address not whitelisted

NotWhitelisted

Native value sent but the underlying is not the wrapped native token

CantDepositNativeToken

Vault paused

EnforcedPause

Notes

  • Pass address(0) as referral when there is none. The call always emits a Referral event.

  • There is no entry fee and no deposit cap.

  • There is no slippage parameter. The price is the current valuation, and the valuation lifespan is the protection against a stale price.

  • With native value, assets is ignored and replaced by msg.value, and no approval is needed.

Sync redeem

syncRedeem is new in v0.6.0. On v0.5.x, redemptions go through the async request flow, except the synchronous exit from a closed vault.

Contract
Method
Balance change

Vault

Shares of the caller burnt (Transfer to address(0)). Asset: curator address → receiver

Reverts when

Condition
Error

Sync mode does not allow sync redeems

SyncOperationNotAllowed

Valuation expired

TotalAssetsExpired

Vault not Open

NotOpen(state)

msg.sender or receiver fails isAllowed (not whitelisted, blacklisted or sanctioned)

AddressNotAllowed

receiver is address(0)

InvalidReceiver

Net assets below minimumAssets

BelowMinimumAssets(assets, minimumAssets)

Curator address balance or allowance to the vault too low

Underlying token's transfer error

Vault paused

EnforcedPause

Notes

  • The shares are always the caller's own: there is no owner or controller argument.

  • Two fees apply: the exit fee, then a haircut (haircutRate, 0 to 20%) on the remaining shares. When the haircut is above 0, a sync redeem costs more than an async one. previewSyncRedeem(shares) returns the net assets.

  • Use minimumAssets as a slippage guard, e.g. the previewSyncRedeem result: it protects against a haircut or fee change between the preview and the execution.

  • A HaircutTaken event is emitted when a haircut applies.

Choosing the deposit path with viem

The vault state has no on-chain getter, so these snippets assume an Open vault. Read state from the Lagoon API and only deposit when it is Open.

Choosing the deposit path with the Lagoon API

The Lagoon API returns the same inputs in one query. On v0.5.x vaults it reports syncMode as Both and totalAssetsExpiration as 0 even while the valuation is valid, so for them read isTotalAssetsValid() on-chain, as in the v0.5.x tab above. Send it to https://api.lagoon.finance/query:

Try in Apollo Sandbox →

Field
Meaning
On-chain equivalent

version

Implementation version, e.g. v0.6.0

version()

syncMode

Both, SyncDeposit, SyncRedeem or None

syncMode()

totalAssetsExpiration

Unix timestamp after which the valuation is stale. 0 on v0.5.x vaults

isTotalAssetsValid() is true while it is in the future

state

Open, Closing or Closed

—

The valuation expires with time, so compare totalAssetsExpiration to the current time when sending the transaction, not when the query was made. A Closed vault still accepts requestDeposit, but the request can never be settled: the assets stay in the pendingSilo until the user cancels.

Checking a sync redeem with the Lagoon API

syncRedeem only exists from v0.6.0, and the API reports syncMode as Both for v0.5.x vaults, so check version as well. The query also returns the curator address's balance of the underlying. Its allowance to the vault and the net output are not in the API: read them on-chain.

Try in Apollo Sandbox →

Field
Meaning
On-chain equivalent

version

Implementation version, e.g. v0.6.0

version()

syncMode

Both, SyncDeposit, SyncRedeem or None

syncMode()

totalAssetsExpiration

Unix timestamp after which the valuation is stale

isTotalAssetsValid() is true while it is in the future

state

Open, Closing or Closed

—

safeAssetBalance

Underlying held by the curator address, in asset units

asset.balanceOf(safe)

roles.safe

Curator address

safe()

When canSyncRedeem is false or the curator address cannot cover assetsOut, fall back to the async redemption with claimSharesAndRequestRedeem(shares) while the vault is Open. Redemption requests revert with NotOpen once the vault is Closing; once it is Closed, exit with redeem as in Exit a closed vault.

Last updated