Metavaults

Metavaults is a feature of the Yelay Protocol that enables a "managed fund"-like experience for end-users.

Metavaults is a feature of the Yelay Protocol that enables a "managed fund"-like experience for end-users. By aggregating user deposits and allocating them across various curated Smart vaults, Metavaults offer a streamlined and efficient way to manage investments within the Yelay ecosystem.

Important: Creating and managing Metavaults is currently only available to white-listed partners. Please contact Yelay team to get it enabled.

Overview

A Metavault is a single-asset vault that manages funds for multiple Smart vaults of the same asset (up to 8 Smart vaults). The Metavault owner curates the underlying Smart vault list and the allocation percentages. Based on those parameters, users' deposits get allocated to different Smart vaults under the hood.

Key Characteristics:

  • Single Asset: A Metavault manages funds for Smart vaults of the same single asset (multi asset vaults are currently not supported).

  • flush->DHW->sync workflow: Deposits and withdrawals are processed in batches for gas efficiency

  • No Fast Withdrawal: Fast withdrawals are not supported in Metavaults.

  • Managed Allocations: The Metavault owner can adjust allocations to Smart vaults and add or remove Smart vaults.

  • Performance Fees Only: Metavaults can only have performance fees; deposit and management fees are not allowed.

  • No Guards or Actions: Smart vaults with guards and actions are not allowed within a Metavault.

Owners and users

Metavault Owner

  • Whitelisted: Only addresses, whitelisted by Yelay can manage Metavaults.

  • Curating Smart vaults: Adds or removes Smart vaults within the Metavault.

  • Setting Allocations: Defines how funds are allocated across the Smart vaults.

  • Slippage Settings: Adjusts the maximum reallocation slippage (default is 1%).

Different roles, Metavault owners can have

  • ROLE_META_VAULT_OPERATOR: enables to perform flush, sync, reallocate, reallocateSync.

  • ROLE_META_VAULT_REALLOCATOR: enables to perform reallocate

  • ROLE_DO_HARD_WORKER: enables to initiate DHW.

  • Environment differences: on Sepolia, every address that is whitelisted for creating Metavaults is also a DHWer but on Mainnet that is not the case

Metavault users

  • Deposits: Users deposit funds into a Metavault and receive Metavault Tokens (MVTs), representing their share in the Metavault, after processing.

  • Withdrawals: Users redeem MVTs to initiate a withdrawal request.

  • Claiming withdrawals: Users withdraw their assets after the withdrawal request has been processed.

Metavault flows

Visual representations of all the flows can be found in the Miro Board.

Deposit Flow

  1. User Deposit: Users deposit the asset (e.g., USDC) into the Metavault, creating a deposit request for the current flush index.

  2. Accumulation: Multiple deposits are accumulated for batch processing.

  3. Flush: The DHWer calls flush on the Metavault to distribute funds to the underlying Smart vaults according to the owner's allocations.

  4. Do-Hard-Work (DHW): The DHW process optimizes and processes the deposits.

  5. Sync: The DHWer calls sync to claim Smart vault Tokens (SVTs) from the Smart vaults and mints MVTs for users.

  6. Claim MVTs: Users can now claim their MVTs representing their share in the Metavault.

Withdrawal Flow

  1. Redeem MVTs: Users redeem their MVTs to create a withdrawal request for the current flush index.

  2. Accumulation: Multiple withdrawal requests are batched.

  3. Flush: The DHWer calls flush to redeem SVTs proportional to the redeemed MVTs.

  4. Do-Hard-Work (DHW): The DHW process optimizes and processes the withdrawals.

  5. Sync: The DHWer calls sync to finalize withdrawals from the Smart vaults.

  6. Withdraw Assets: Users can now withdraw their assets from the Metavault.

Reallocation Flow

  1. Update Allocations: The Metavault owner adjusts allocations or adds/removes Smart vaults.

  2. Block Flushes: Flushing of deposits/withdrawals is temporarily blocked until reallocation is complete (sync is allowed).

  3. Reallocate: The DHWer calls reallocate to withdraw (using fast withdraw) and redeposit (normal deposit) funds according to the new allocations.

  4. Do-Hard-Work (DHW): The DHW process optimizes the deposits.

  5. Reallocate Sync: The DHWer calls reallocateSync to claim SVTs from SmartVaults to which deposits were made and finalize the reallocation.

  6. Resume Operations: Flushing of deposits and withdrawals is then allowed again.

SDK Functions

The Yelay SDK provides a set of functions to interact with Metavaults from SDK version 2.0.9 onwards. Below are the examples of the most common Metavault-related workflows and description of used methods.

Creating a Metavault

To create a Metavault, first a decision must be made about which single asset vaults the new Metavault will include (USDC is used in our example). Then all Smart vaults that meet the criteria for being included in a Metavault can be fetched and filtered out all but those with only USDC as their asset.

For the sake of this example, first 4 vaults from the filtered list are used. The allocation percentages for each vault must also be set. In this case, 40% was set for the first vault, 30% for the second, 20% for the third, and 10% for the fourth. Allocations are defined as base points, where 1% is equal to 100. The sum of all allocations must be equal to 10000. Allocation percentages are defined in a separate array in the same order as listed the vaults' addresses array.

Finally, the Metavault name is chosen along with the custom MVT symbol, and the Metavault can be created by calling the createMetaVault method.

const eligibleVaults = await yelaySDK.views.metaVault.getCreateMetaVaultVaults()

const filteredVaults = eligibleVaults.filter((vault) =>vault.assetGroup.assetGroupTokens[0].address === "0xaddressUSDC")

const vaults = filteredVaults.slice(0, 4).map((vault) => vault.address)
const allocations = [4000, 3000, 2000, 1000]

const createMetaVault = async () => {
  const tx = await yelaySDK.views.metaVaults.createMetaVault(
      "0xaddressUSDC",
      "My Metavault",
      "MMV",
      {
        vaults,
        allocations,
      }
    )
  await tx.wait();
};

Managing a Metavault

Metavault managers can add or remove SmartVaults from a Metavault, as well as adjust the allocation percentages for each Smart vault.

Setting Allocations

To set new allocation percentages for the SmartVaults within a Metavault, use the setMetaVaultAllocations method. All the changes step into effect after the DHWer triggers the Metavault flush->DHW->sync process.

const setAllocations = async () => {
  const tx = await yelaySDK.views.metaVaults.setMetaVaultAllocations(
    "0xMetavaultAddress",
    [2500, 2500, 2500, 2500]
  );
  await tx.wait();
};

Managing Smart vaults

To add or remove SmartVaults from a Metavault, use the manageMetaVaultSmartVaults method. Vaults are added by appending their addresses to the vaults array and their corresponding allocations to the allocations array. Vaults are removed from the Metavault by setting their allocation to 0, but they must remain in the vaults array. After the reallocation process in done, the vault will be removed and will not appear in the list of Smart vaults anymore. In this example the third Smart vault is removed from the Metavault by setting its allocation to 0 and a new Smart vault is added with a 25% allocation.

Important: Smart vaults cannot be removed from the Metavault if the Metavault TVR is 0.

const newVault = "0xNewSmartVault"
const vaults = yelaySDK.views.metaVaults.getMetaVaultSmartVaults("0xMetavaultAddress")

const manageSmartVaults = async () => {
  const tx = await yelaySDK.views.metaVaults.manageMetaVaultSmartVaults(
    "0xMetavaultAddress",
    {
      vaults: [...vaults, newVault],
      allocations: [2500, 2500, 0, 2500, 2500]
    }
  );
  await tx.wait();
};

Managing Allocation Slippage

To set the maximum reallocation slippage for a Metavault, use the setMetaVaultMaxReallocationSlippage method. Specify the Metavault address and the maximum reallocation slippage percentage, where 1% equals 100.

const setMaxReallocationSlippage = async () => {
  const tx = await yelaySDK.views.metaVaults.setMetaVaultMaxReallocationSlippage(
    "0xMetavaultAddress",
    200 // 2%
  );
  await tx.wait();
};

Depositing into a Metavault

Users can deposit assets into a Metavault by making a direct deposit or by swapping assets and depositing them in a single transaction. The deposit is processed during the next flush->DHW->sync cycle.

Standard Deposit

To deposit 1000 USDC into a Metavault, use the metaVaultDeposit method. Specify the Metavault address and the amount to deposit.

const depositIntoMetaVault = async () => {
  const tx = await yelaySDK.metaVaults.metaVaultDeposit(
    "0xMetaVaultAddress",
    ethers.utils.parseUnits("1000", 6) // 6 decimals for USDC
  );
  await tx.wait();
};

Swap and Deposit

To swap assets and deposit them into a Metavault in a single transaction, use the metaVaultSwapAndDeposit method. Specify the Metavault address, input tokens, input amounts, and swap details.

await yelaySDK.metaVaults.metaVaultSwapAndDeposit({
  metaVault: "0xMetaVaultAddress",
    inTokens: ["0xTokenAddress"],
    inAmounts: [ethers.utils.parseUnits("1", 18)],
    swapInfo: {
    swapTarget: "0xSwapTarget",
      token: "0xTokenAddress",
      swapCallData: "0xEncodedSwapCallData",
  },
});

Optional: Claiming MVTs (MetaVault Tokens)

Important: If this step has not been completed by calling the method below, it will automatically be done when calling the metaVaultRedeem method.

After the flush->DHW->sync cycle has been completed, users can claim their MVTs, which they need to later redeem assets from the Metavault. Call the metaVaultClaimMVTs method to claim MVTs from the Metavault. Specify the Metavault address and the array of Metavault's flush indexes where MVTs are available.

const claimMVTs = async () => {

  const tx = await yelaySDK.metaVaults.metaVaultClaimMVTs(
    "0xMetaVaultAddress",
    ["1", "2", "3"]
  );
  await tx.wait();
};

Withdrawing from a MetaVault

To initiate a withdrawal from a Metavault, users first need to redeem their MVTs to initiate a withdrawal request and then claim their assets after the flush->DHW->sync cycle has been completed.

Redeeming MVTs

To redeem MVTs from a Metavault, use the metaVaultRedeem method. Specify the Metavault address and the amount of MVTs to redeem, along with the array of Metavault's flush indexes where there are shares to be redeemed.

const redeemFromMetaVault = async () => {
  const tx = await yelaySDK.metaVaults.metaVaultRedeem(
    "0xMetaVaultAddress",
    ethers.utils.parseUnits("500", 18) // Redeem 500 MVTs
  );
  await tx.wait();
};

Claiming withdrawal from a Metavault

After the flush->DHW->sync cycle has been completed, users can withdraw their assets.

To claim the redeemed assets from a Metavault, use the metaVaultWithdraw method. Specify the Metavault address and the array of flush indexes where there are assets to be claimed.

const withdrawFromMetaVault = async () => {

  const tx = await yelaySDK.metaVaults.metaVaultWithdraw(
    "0xMetaVaultAddress",
    ["1", "2", "3"]
  );
  await tx.wait();
};

MetaVault Multicall

Execute multiple Metavault transactions in a single call for efficiency. Specify the Metavault address and an array of Metavault transactions to execute.

const metavaultMulticall = async () => {
  const data: BytesLike[] = [
    // Example encoded function data
    "0xEncodedFunctionData1",
    "0xEncodedFunctionData2",
  ];
  const tx = await yelaySDK.metaVaults.metaVaultMulticall(
    "0xMetaVaultAddress",
    data
  );
  await tx.wait();
};

Metavault details

The following methods are available to retrieve various details about Metavaults:

  • getAllMetaVaults()

    • Retrieves all MetaVaults that have been created.

  • getUserMetaVaults("0xUserAddress", false)

    • Retrieves all MetaVaults that the user has deposited in.

  • getMetaVaults("0xOwnerAddress1", true)

    • Retrieves all MetaVaults where the owner is an address from the array of owners.

  • getMetaVaultSmartVaults(metaVaultAddress)

    • Retrieves the list of SmartVaults within a MetaVault.

  • getMetaVaultSmartVaultAllocation(metaVaultAddress, smartVaultAddress)

    • Retrieves the allocation percentage of a specific SmartVault within a MetaVault.

  • getMetaVaultsUsers(metaVaultAddresses)

    • Retrieves the users of specified MetaVaults.

  • getIsMetaVaultDeployer(address)

    • Checks if an address is authorized to deploy MetaVaults.


Last updated