Architecture
Mellow Core Vaults
Abstract
The DeFi market continues to expand with an increasing number of yield opportunities and protocols, each with its own level of decentralization, permissionlessness, and risk. Navigating this landscape is becoming challenging – even for advanced users.
Meanwhile, the latest wave of adoption is bringing thousands of new participants from traditional markets into crypto. These users aren’t looking for raw protocols – they expect structured, accessible, and compliant financial products.
To meet this demand, the onchain financial stack must evolve. It needs to be productized, abstracted and made composable.
Mellow’s response is our Core Vaults – infrastructure purpose-built for curators and asset managers to design, deploy, and scale structured products onchain.
Vaults Architecture
Core Vaults are built around a modular architecture that orchestrates interactions across both DeFi protocols and centralized exchanges. It enables trustless execution of complex, institutional-grade strategies while maintaining full composability and transparency.
No matter how diverse or sophisticated the underlying strategies become, the vault framework remains stable and predictable – providing a unified, programmable setup for managing assets, risks, and logic.
The result is infrastructure that supports scalable, curated access to onchain yield – secure, standardized, and ready for real users.
Core Vaults Features & Functionality
Deposits & Withdrawals for the Liquidity Providers
Valuation Oracle
Strategy performance analytics for Liquidity Providers
Fee management
Vault management tools & Curation UI
Reward distribution engine
Receipt token distribution infrastructure
Smart contract safeguards
Granular role-based control
Access to external apps and protocols
Vault system architecture overview

📥 Deposit Queue
Manages user deposits through a time-buffered queuing system. This delay helps prevent front-running and price manipulation by ensuring deposits are not executed based on stale or externally influenced oracle price data.
The deposit queue is also responsible for issuing receipt tokens.
Technical Details`
Deposit flow:
Step 1: User Deposits
A user submits a deposit request via
deposit(assets, referral, merkleProof)
.Deposits are validated via optional Merkle whitelist logic (using
merkleProof
) or onchain mapping (ifhasWhitelist
flag is set).If a previous request exists, it must be claimed or canceled before creating a new one.
The deposited amount and timestamp is stored in the
DepositQueue
contract
Step 2: Oracle Report
Oracle report is propagated via the
handleReport(priceD18, timestamp)
method.The queue validates the report:
It must be called by the
Vault
.Provided
timestamp
must be in the past (usuallyrequest.timestamp - depositInterval
).priceD18
must be non-zero.
The queue handles deposit requests that are pending for at least
depositInterval
seconds (the interval is specified in the oracle’s security parameters).The contract stores a
(timestamp, reducedByDepositFeePriceD18)
pair in theprices
array. This value is used to convert accumulated assets into shares based on the user’s request timestamp. ThereducedByDepositFeePriceD18
is derived by applying the deposit fee to the actual reportedpriceD18
.The corresponding shares are allocated but not yet minted.
Emits the
ReportHandled
event.
Step 3: User Claims
A user calls
claim(account)
(orclaimShares(account)
in theVault
) to mint and receive previously allocated shares.The number of shares is computed as:
uint256 shares = (request.assets * reducedByDepositFeePriceD18) / 1e18;
Shares are minted to the user via
mintAllocatedShares
.
Assumptions & PropertiesSingle Active Request
Each user may have at most one unprocessed deposit request. New deposits are blocked until the previous request is claimed. If the pending request is already claimable, the claim will be automatically processed during the next deposit.
Delayed Execution
Deposit processing requires an Oracle report submitted after a configured
depositInterval
.Lazy Claiming Deposits are converted into shares during oracle processing, but users must call the claim function (in
ShareModule
,ShareManager
or in eachDepositQueue
separately) to receive them. However, even without explicitly claiming, the user's full share balance — including all claimable shares across all deposit queues — is accurately reflected inshareManager.sharesOf(user)
.Whitelist Enforcement
Deposits may require Merkle proof for depositor whitelisting.
📤 Redeem Queue
Serving as the counterpart to the Deposit Queue, it manages withdrawal requests.
Redemptions are processed in two phases:
Oracle pricing – reports are processed in batches, with each batch assigned a specific conversion price derived from its corresponding Oracle report.
Liquidity settlement — Vault liquidity is pulled asynchronously, allowing the curator to finalize withdrawals and perform asset swaps before processing user redemption requests.
This separation allows asynchronous liquidity management, gas efficiency, and protection against griefing. Unlike deposit requests, withdrawal requests in the Redeem Queue cannot be canceled to prevent yield-griefing.
Technical Details
Redeem flow:
Step 1: User redeems
User submits
redeem
request, vault shares are immediately burned.The vault curator monitors and manages liquidity across connected Subvaults, pulling funds and swapping assets as needed to fulfill redemption requests.
Step 2: Oracle report
Valid and non-suspicious
Oracle
report
arrives.The vault curator invokes
handleBatches(n)
on theRedeemQueue
.This triggers the movement of required assets from the vault (and associated subvaults) to process redemption requests.
Step 3: User claims
Users call
claim(receiver, timestamps)
to withdraw assets.
Assumptions & PropertiesNon-Cancellable Requests Prevents griefing where a user requests redemption, causing curator to pull liquidity, then cancels.
Time-sensitive request handling Oracle reports can only process a redemption request if at least
redeemInterval
seconds have passed since the request was submitted — i.e.,report.timestamp
must be greater than or equal torequest.timestamp + redeemInterval
.Asynchronous Fulfillment Liquidity can be managed independently of oracle report submission.
🔏 Signature Deposit and Redeem Queues
Signature Queues allow deposits and redemptions to be processed instantly, bypassing the standard time-buffered flow. That happens when a trusted consensus group issues offchain-signed approvals.
Key Features:
Instant execution without waiting for Oracle price reports
Nonce-based signature protection to prevent replay attacks
EIP-712/EIP-1271 compatible signed orders
Oracle price validation enforced onchain
Stateless and removable (does not accumulate shares or process claims)
Fee-bypass: No Deposit Fee or Redeem Fee is charged for actions via this queue
Technical Details
Signature Queue flow:
Step 1: Offchain signing
Offchain consensus actors (operators, curators, admins) generate signed
Order
messages.
Step 2: Onchain execution
A user submits this order to the
SignatureQueue
contract for execution.The queue:
Verifies the order signature
Validates nonce, queue address, asset match, deadline, and caller
Computes the implied asset/share price and checks it against the vault's oracle
If all checks pass, the order is executed atomically.
Assumptions & PropertiesOnly trusted offchain actors (consensus group) are authorized to sign orders.
Price quotes must be valid and non-suspicious.
Users cannot reuse old signatures due to nonce tracking.
Orders must be executed before
deadline
.
💼 Vault
The Vault contract serves as the central entry point into the Core Vault system. It is configured by four internal modules:
BaseModule: Implements different auxiliary interfaces such as
onERC721Received
,getStorageAt
andreceive
callbackACLModule: Role-based access control for system components
ShareModule: Management of shares, fees, deposit and redeem queues lifecycle,
Oracle
report handlingVaultModule: Subvaults management, pushing and pulling of assets in subvaults
🗃️ Subvault
The Subvault contract is a vault component designed to manage delegated asset strategies, acting as a controlled execution unit within a system. Like the Vault contract, it is configured by modules:
BaseModule: Implements different auxiliary interfaces such as
onERC721Received
,getStorageAt
andreceive
callback.SubvaultModule: Represents an isolated child vault within a modular vault system, responsible for securely holding and releasing assets upon authenticated requests.
VerifierModule: is an abstract extension of the Base Module designed to provide standardized access to a Verifier contract.
CallModule: Enables arbitrary low-level calls to external contracts (used by curator of the vault), and verification through a verifier module.
👁️ Verifier
Each Subvault is paired with a Verifier contract, which validates function calls and ensures only pre-approved actions from valid actors are permitted across vault-connected modules.
While each Subvault is expected to have its own dedicated Verifier contract, it is still possible for the same Verifier to be shared across multiple Subvaults.
Technical Details
Verifier allows multiple types of verification:
ONCHAIN_COMPACT: Checks
CompactCall
(who | where | selector) hash against internal admin-controlled setMERKLE_COMPACT: Verifies Merkle proof of
CompactCall
(who | where | selector) hashMERKLE_EXTENDED: Verifies Merkle proof of
ExtendedCall
(who | where | value | callData) hashCUSTOM_VERIFIER: Delegates full verification to an external verifier
Two admin-owned parameters are saved in the state of the Verifier contract:
compactCallHashes
that defines all allowed calls for ONCHAIN_COMPACT verification typecompactCalls
is an optional mapping for reverse lookup of call metadata by hashmerkleRoot
that defines all allowed calls for MERKLE_COMPACT, MERKLE_EXTENDED and CUSTOM_VERIFIER
🔮 Oracle
The Oracle contract handles secure and configurable price reporting for supported assets. Closely integrated with the ShareModule
, it provides price validation, deviation monitoring, and time-restricted report submissions.
It enforces strict guarantees around report timing and trust minimization using role permissions and deviation thresholds. This oracle ensures consistent pricing across all queue, share, and limit-related calculations.
Key considerations:
Only authorized roles can submit price updates
Suspicious reports require explicit approval before acceptance
Price validation is performed locally without relying on external oracle feeds
Manipulation is prevented through absolute and relative deviation limits
Technical Details
Oracle Configurable Security Parameters:
Absolute Deviation: Hard limits on price delta in price units
Relative Deviation: Tolerance as a percentage (e.g., 5% = 0.05e18)
Timeout: Minimum time between valid reports (ignored if the previous report is suspicious)
depositInterval: Minimum age required for a deposit to be processed
redeemInterval: Same, but for redemptions
Reporting flow:
Step 1: Report is submitted:
Each asset is checked for support
The previous report state is evaluated:
If
timeout
has not passed, and the report is not suspicious → revertTooEarly
Price is compared against previous:
maxAbsolute
→ revertInvalidPrice
maxRelative
→ flaggedisSuspicious
If the report is valid and non-suspicious (deviation < suspicious && deviation < max), it is immediately accepted
If the report is suspicious it will be accepted only after validation from the Admin (ACCEPT_REPORT_ROLE holder)
Step 2: Accepted report propagation:
Triggers
vault.handleReport(...)
, processing deposit requests and pending redeem requestsEmits
ReportsSubmitted
Validation Logic:
Reports are validated by:
Calculating absolute deviation (
maxAbsolute
)Calculating relative deviation (
maxRelative
)Comparing against
max
andsuspicious
thresholds
A report is:
Rejected if either deviation exceeds max
Accepted but marked as suspicious if above the suspicious threshold, flagging the report
Accepted as normal if within all limits
Used by:
SignatureDepositQueue
,SignatureRedeemQueue
,DepositQueue
andRedeemQueue
contractsVault's limit accounting (
RiskManager
)
📊 Share Manager
The Share Manager is an upgradeable contract responsible for managing vault share issuance, allocation, whitelisting, permissions, and lockups within a modular vault system.
Key responsibilities include:
Tracking total and active share supply
Managing global and targeted account lockups
Verifying whitelist status and transfer permissions
Enforcing mint, burn, and transfer pauses
Handling share allocation and claims through queues
Whitelisting for implementing KYC & compliance features
Technical Details
Share Manager relies on a compact bitmask (flags
) for enabling/disabling features and supports configurable per-account permissions. Controlled via ShareManagerFlagLibrary
:
hasMintPause
hasBurnPause
hasTransferPause
hasWhitelist
hasTransferWhitelist
globalLockup
targetedLockup
Lockups are enforced in updateChecks
.
Share Manager operates under the control of defined roles:
SET_FLAGS_ROLE
: Allows changing global flags (e.g., mint pause, whitelist enforcement).SET_ACCOUNT_INFO_ROLE
: Grants permission to set per-account configuration.SET_WHITELIST_MERKLE_ROOT_ROLE
: Grants permission to set new whitelist merkle root.
💰 Fee Manager
The Fee Manager oversees the calculation and management of multiple fee types within the vault system. Currently, it supports four fee-acquiring methods:
Deposit Fee: Charged on asset deposits
Redeem Fee: Applied on share redemptions
Performance Fee: Based on decreases in share price (assets × price = shares)
Protocol Fee: Time-based fee accrued per vault
All fees are paid in vault shares rather than the underlying assets.
Admin can update recipient and fee parameters.
Technical Details
Fee Manager will require identifying the base asset of the vault. setBaseAsset
: Called once per vault to register its performance reference token.
updateState(asset, price)
: Vaults call this to refresh timestamp and minimum price.
Performance and Protocol fees are activated by a fresh Oracle report on the base asset.
Fee Calculation Logic:
Deposit fee – applied linearly and calculated as
shares * depositFeeD6 / 1e6
, deducted during the oracle report handling process.Redeem fee – applied linearly and calculated as
shares * redeemFeeD6 / 1e6
, deducted when shares are requested for redemption.Performance fee – due to the use of a non-standard pricing mechanism (
price = shares / assets
), delegation yield will result in a lower reported price by the oracle; ifpriceD18
falls belowminPriceD18
, the fee is charged as(minPriceD18 - priceD18) * performanceFeeD6 * totalShares / 1e24
to capture the implied yield.Protocol fee – a continuously accruing time-based fee calculated as
totalShares * protocolFee * (block.timestamp - timestamps[vault]) / (365 * 24 * 3600 * 1e6)
, proportional to both share supply and elapsed time since the last timestamp update.
🎯 Risk Manager
The Risk Manager contract defines and enforces asset deposit limits across the Vault and its associated Subvaults. It maintains internal accounting of balances, limits, and approved assets for each subvault.
This module is responsible for:
Setting and enforcing share limits (practically representing approximate deposit limits) at both vault and subvault levels
Permitting or restricting specific assets to be pulled into the Subvaults
Tracking pending balances for Deposits that are not yet finalized
Validating limits using Oracle price reports
Technical Details
Vault Limit: Global cap across all assets managed by the vault (in shares).
Subvault Limit: Individual cap per subvault, enforced independently (in shares).
Allowed Assets: Only explicitly allowlisted assets are permitted for push / pull operations in a given subvault.
Pending Assets: Temporarily tracked assets, e.g., during deposit queueing
Shares Conversion: All balances are internally tracked in shares, calculated using latest report in the
Oracle
contract.
All vault and subvault-level limits are treated as approximate and computed using the most recent Oracle report available at the time of the state update (on Subvault pull/push event or Deposit/Redeem operations).
If actual balances deviate significantly from the stored balance
values due to oracle drift, delayed execution, or protocol-side changes, a trusted actor can apply a ‘corrections’ to mitigate the difference:
modifyVaultBalance
for the Vault, ormodifySubvaultBalance
for individual Subvaults.
Since the system is expected to hold only correlated assets, such manual adjustments are assumed to be rare under normal operating conditions.
🔐Access Control
Granular Access Control (MellowACL) is a lightweight yet extensible layer built on an OpenZeppelin contract. It adds automatic tracking and enumeration of active roles to enhance governance transparency and enable dynamic role management.
Responsibilities include:
Granting and revoking access control roles to addresses
Maintaining a dedicated set of all active (assigned) roles
Providing enumerable functions for external auditing of granted roles
Emitting events when roles are assigned or fully revoked
Supported protocols and integrations
Core Vaults architecture supports integration with a wide range of apps, including both DeFi protocols and centralized exchanges. Most of the protocol integrations can work out of the box. Below is a brief example of potential connections to subvaults.
Major protocols:
Aave (leverage & supply side LPing)
Gearbox (leverage & supply side LPing)
Curve, Uniswap (DEX liquidity provisioning)
Cowswap (limit orders)
Symbiotic, EigenLayer (provide liquidity for restaking rewards)
Pendle (splitting and selling future yield or holding for boosted returns)
Morpho (leverage & supply side LPing)
Euler (leverage & supply side LPing)
Fluid (leverage & supply side LPing)
Hyperliquid
CEXes via custodial off-exchange solutions (Copper and Ceffu)
Deribit
ByBit
Binance
Most of tier 1 and 2 CEXes
Case Study
Prerequisites:
The flow occurs within a Core Vault under the following conditions:
Two subvaults representing different yield sources: a delta-neutral trading strategy and restaking
Liquidity is evenly allocated 50%-50% between the subvaults
1% management fee and 15% performance fee
Annual Percentage Rate (APR) of 10%
Initial Action:
A Liquidity Provider (LP) deposits 1,000,000 USDC into the Mellow Core Vault.
Process Flow:
Deposits are processed and transferred into the vault after passing through the time-buffered Deposit Queue.
The LP receives receipt tokens representing the 1,000,000 USDC position.
The LP can use these receipt tokens as collateral in various DeFi protocols to generate additional yield, such as leverage looping on Gearbox.
Liquidity is allocated from the Vault to the Subvaults according to the limit-based rules.
50% of unallocated funds are pulled into a Subvault 1 by a Curator.
50% of unallocated funds are pulled into a Subvault 2 by a Curator.
The Curator allocates funds from Subvault 1 to the delta-neutral strategy through integrated centralized exchanges.
Funds from Subvault 2 are allocated to the restaking strategy via Symbiotic.
After 12 months, the LP requests a full withdrawal.
Throughout the holding period, Protocol and Performance Fees are automatically accrued with each Oracle update, resulting in a management fee of 10,000 USDC and a performance fee of 15,000 USDC - both paid in vault receipt tokens.
The withdrawal request is queued and detected onchain.
At the end of the withdrawal interval, the Curator transfers 1,075,000 USDC (principal plus accrued yield) from the Subvaults back to the Core Vault Contract.
The LP redeems the full amount directly from the Redeem Queue.
Process Flow for Curator Allocation:
Curator asks Admin to add 2 subvaults with correct verifier configs:
First one allowing liquidity transfer into a Copper or Ceffu account
Second one allowing deposits, withdrawals, withdrawal claims and reward claims & swaps from Symbiotic
Curator pushes unallocated funds:
Vault.pushAssets(USDC, *500000*)
.Allocates assets in Subvault 1 (Delta-Neutral strategy on ByBit via Copper ClearLoop).
In UI, Curator clicks New Call → sets target to Copper Subvault → selects USDC asset and Bybit Clearloop as destination.
Generate
VerificationPayload
via Mellow API.Executes call:
subvault1.call( asset, // address of the asset (USDC) to be sent to the Copper account 0, // eth value abi.encodeCall( IERC20.tranfer, // transfer call encoding (copperAccountAddress, 5e11) // (recipient, amount) ), verificationPayload // extra data for Verifer contract )
Inside Bybit UI, strategy is realized by the Curator, with settlements occurring every few hours in the Copper Clearloop.
Allocate to Subvault 2 (Symbiotic Restaking).
Pushes unallocated funds to the second subvault:
vault.pushAssets(subvault2, asset, 5e11)
.Clicks New Call → target = Restaking Subvault → calls
deposit(subvault, 5e11)
Gets the verification result and
VerificationPayload
from the Mellow API for this call.Executes call:
subvault2.call( symbioticVault, // address of the symbiotic vault 0, // eth value abi.encodeCall( ISymbioticVault.deposit, // deposit call encoding (subvault, 5e11) // (onBehalfOf, amount) ), verificationPayload // extra data for Verifer contract )
Curator regularly claims rewards from Symbiotic Restaking and swaps them into assets before depositing them using
subvault2.call
Curator monitors Performance & Exit upon user request by repeating New Call steps to withdraw according to net returns.
Last updated