1. Architecture Overview
A Mellow Core Vault is a programmable, modular asset management contract. It serves as the central hub for capital management, risk control, and composable logic. Depositors provide capital; Curators manage that capital within guardrails set by the vault configuration. All deposit and redemption flows are time-buffered through an off-chain oracle — protecting depositors against flash-loan attacks and front-running by design.Core Components
Deposit Lifecycle
Async queue
Time-buffered. Oracle prices the batch; Curator settles liquidity. Claim is a separate transaction after processing.Sync queue
Shares issued or assets returned in the same transaction. No separate claim step.Redemption Lifecycle
2. Supported Networks
3. Vault Discovery
Fetch the list of all vaults from the Mellow REST API. No authentication is required.4. TypeScript Interfaces & Constants
5. ABIs
Only the functions and events relevant to integrations are shown here.5.1 Deposit Queue ABI
5.2 Redeem Queue ABI
5.3 ERC20 ABI (subset — for approval)
5.4 Vault ABI (subset — for share balance lookup)
shareManager address is itself an ERC20-compatible contract. Use ERC20_ABI with balanceOf, or use the richer SHARE_MANAGER_ABI below for more precise balance reads.
5.5 ShareManager ABI (subset)
6. Deposit
Overview
Depositing submits tokens to aDepositQueue contract. For async queues the shares are not immediately available — an oracle processes the batch and sets a price, after which the user calls claim to receive their shares.
Steps
Pick a deposit queue
vault.deposit_queues. You can match by queue.asset address and queue.type deposit type ("sync" | "async").Check whether the queue is paused
queue.is_paused === false. Throw early if paused.Check whitelist requirements
shareManager.flags(). If flags.hasWhitelist === true, call shareManager.isDepositorWhitelisted(userAddress, merkleProof). If it returns false, the deposit will revert with DepositNotAllowed. For public vaults (hasWhitelist === false), pass [] as the proof.Resolve token metadata
Token in vault.deposit_tokens for queue.asset.Parse and validate the amount
parseUnits(amount, token.decimals).Validate that:parsedAmount > 0nparsedAmount <= UINT224_MAX
Check for an existing pending request
requestOf(userAddress) and check timestamp === 0n before depositing.Handle native ETH deposits
queue.asset === NATIVE_ETH_ADDRESS), check the user’s ETH balance, then call deposit() with value = parsedAmount.Handle ERC20 deposits
- Read
allowance(userAddress, queueAddress). - If
currentAllowance > 0n, sendapprove(queueAddress, 0n)first. This is required for tokens like USDT that revert if you set a non-zero allowance on top of an existing one. - Send
approve(queueAddress, parsedAmount). - Then call
deposit(parsedAmount, zeroAddress, merkleProof)withvalue = 0n.
Wait for async claimability
claimableOf or listen for DepositRequestClaimed events, then call claim.Code Example
zeroAddress (0x0000000000000000000000000000000000000000) unless you have been issued a referral address by the Mellow team.7. Cancel Deposit
Overview
A pending async deposit request can be cancelled before the oracle processes it. Cancelling returns the deposited tokens to the user. You cannot cancel once the request is claimable — callclaim instead.
Steps
Check for a pending request
requestOf(userAddress) on the deposit queue. Check timestamp > 0n — if zero, there is no pending request.Check whether it is already claimable
claimableOf(userAddress). If > 0n, the oracle has already processed the request — you must claim it, not cancel it.Cancel the request
cancelDepositRequest(). This function takes no arguments — it cancels the caller’s own request.Code Example
8. Claim Deposit
Overview
After the oracle processes an async deposit request, vault shares are held in the queue contract ready for collection. Callclaim to transfer them to the user.
Steps
Check whether there is anything to claim
claimableOf(userAddress). If > 0n, shares are ready to claim.Check whether the request is still pending
claimableOf returns 0n, call requestOf(userAddress). If timestamp > 0n, the oracle has not yet processed the request — wait and retry later.Claim the shares
claim(userAddress). Returns true when shares are successfully transferred.Code Example
9. Redeem
Overview
Redemption burns vault shares and, after oracle processing, returns the underlying asset to the user. Redeem queues are always async — there is always a separate claim step.Steps
Pick a redeem queue
vault.redeem_queues.Check whether the queue is paused
queue.is_paused === false.Fetch the user's redeemable share balance
- Call
vault.shareManager()to get the share manager address. - Call
shareManager.activeSharesOf(userAddress)— this returns only shares that are not currently locked in a pending redeem request. UsesharesOfif you want the total including locked shares.
Parse the share amount with vault decimals
vault.decimals), not the token’s decimals. This is a common mistake — the share token uses the vault’s decimal precision.Validate the amount
parsedShares > 0n and parsedShares <= activeShareBalance.Submit the redeem request
redeem(parsedShares). No ETH value, no ERC20 approval — the vault contract locks shares directly from the caller.Wait for settlement and claim later
handleBatches(), then call claimRedeem (see Section 10).redeem() call creates a new request with its own timestamp.redeem(), two off-chain steps must happen before you can claim: (1) the oracle calls handleReport() to price the batch, then (2) the Curator calls handleBatches() on the RedeemQueue to pull the required liquidity from subvaults. Listen for the RedeemRequestsHandled event — it fires when handleBatches() settles one or more batches and requests become claimable. The timing depends on vault configuration (redeemInterval) and curator activity, typically ranging from minutes to hours.Code Example
approve. The vault contract has the authority to lock and burn shares on behalf of the caller.10. Claim Redeem
Overview
A user may accumulate multiple redemption requests over time. TherequestsOf function returns all requests paginated. Once the oracle marks a request isClaimable, the user can batch-claim them by passing the corresponding timestamps to claim.
Steps
Paginate redemption requests
requestsOf(userAddress, offset, 100):- Start with
offset = 0. - Increment by
100each iteration. - Stop when a page returns fewer than
100items.
Filter claimable requests
isClaimable === true.Extract timestamps
timestamp field from each claimable request. Cast to number — timestamps are uint32 values, safely representable as JavaScript numbers until year 2106.Batch-claim the requests
claim(userAddress, timestamps). Returns the total assets transferred.claim() is idempotent. Non-claimable or already-claimed timestamps are silently skipped — the contract does not revert. You may safely pass all known timestamps and let the contract filter them.Code Example
11. Fees
Fees in Mellow Core Vaults are paid in vault shares, not in underlying assets. TheFeeManager contract calculates and deducts fees automatically during oracle report handling — integrators do not call fee functions directly.
Fees are vault-specific and set by Curators. Check the vault configuration or the Mellow API for exact fee parameters before displaying estimated returns to users.