Skip to content

Vaults & ERC4626 Mechanics

Morpho Vaults V1.x are fully compliant with the ERC4626 standard, providing a standardized interface for yield-bearing tokens. Understanding these mechanics is essential for building robust earn integrations. Morpho vaults v2 are not fully ERC4626 compliant due to the nature of the interest calculation, but the same functions are used from a user point of view.

ERC4626 Standard

The ERC4626 standard defines four core functions that enable seamless interaction with yield-bearing vaults:

Core Functions

Deposit Functions

// Deposit a specific amount of assets
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
 
// Mint a specific amount of shares  
function mint(uint256 shares, address receiver) external returns (uint256 assets);

Withdrawal Functions

// Withdraw a specific amount of assets
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
 
// Redeem a specific amount of shares
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);

Assets vs. Shares

Understanding the distinction between assets and shares is crucial for proper integration:

Assets

  • Definition: The underlying token (e.g., USDC, WETH) deposited into the vault
  • Value: Constant nominal value (1 USDC = 1 USDC)
  • Use Case: When users want to deposit/withdraw a specific dollar amount

Shares

  • Definition: Vault tokens representing proportional ownership
  • Value: Appreciates over time as yield accrues
  • Use Case: When users want to maintain their percentage ownership of the vault

Conversion Between Assets and Shares

// Convert assets to shares (before deposit)
const shares = await vault.previewDeposit(assetAmount);
 
// Convert shares to assets (current value)
const assets = await vault.convertToAssets(shareAmount);
 
// Convert assets to shares (for withdrawal)
const sharesNeeded = await vault.previewWithdraw(assetAmount);
 
// Convert shares to assets (for redemption)
const assetsReceived = await vault.previewRedeem(shareAmount);

Share Price Appreciation

The key to Morpho Vault yield generation is share price appreciation:

// Share price calculation
const sharePrice = totalAssets / totalSupply;
 
// Example: Vault grows from $1M to $1.1M with 1M shares
// Initial: $1,000,000 / 1,000,000 = $1.00 per share
// After yield: $1,100,000 / 1,000,000 = $1.10 per share
// User return: 10% APY

Practical Implementation

Deposit Flow

async function depositToVault(vaultAddress: string, assetAmount: BigNumber, userAddress: string) {
  const vault = new Contract(vaultAddress, ERC4626_ABI, signer);
  const asset = new Contract(await vault.asset(), ERC20_ABI, signer);
  
  // 1. Check user's asset balance
  const balance = await asset.balanceOf(userAddress);
  if (balance.lt(assetAmount)) {
    throw new Error('Insufficient balance');
  }
  
  // 2. Preview shares to be received
  const expectedShares = await vault.previewDeposit(assetAmount);
  
  // 3. Approve vault to spend assets
  await asset.approve(vaultAddress, assetAmount);
  
  // 4. Execute deposit
  const tx = await vault.deposit(assetAmount, userAddress);
  
  return {
    transaction: tx,
    expectedShares,
    sharePrice: await getSharePrice(vault)
  };
}

Withdrawal Flow

async function withdrawFromVault(vaultAddress: string, assetAmount: BigNumber, userAddress: string) {
  const vault = new Contract(vaultAddress, ERC4626_ABI, signer);
  
  // 1. Check user's share balance
  const userShares = await vault.balanceOf(userAddress);
  const requiredShares = await vault.previewWithdraw(assetAmount);
  
  if (userShares.lt(requiredShares)) {
    throw new Error('Insufficient shares for withdrawal');
  }
  
  // 2. Execute withdrawal
  const tx = await vault.withdraw(assetAmount, userAddress, userAddress);
  
  return {
    transaction: tx,
    sharesRedeemed: requiredShares,
    assetsReceived: assetAmount
  };
}

Risk Considerations

When building earn products, you must communicate these key risks to users:

Smart Contract Risk

  • Vault Contract Risk: Bugs in vault implementation could lead to loss of funds
  • Underlying Protocol Risk: Morpho Markets that the vault allocates to may have vulnerabilities
  • Upgradeability Risk: Changes to vault or protocol contracts

Market Risk

  • Asset Price Risk: Value of underlying asset may decline
  • Interest Rate Risk: Yield rates can fluctuate based on market conditions
  • Liquidity Risk: Temporary inability to withdraw during high utilization periods

Curator Risk

  • Strategy Risk: Poor allocation decisions by vault curators
  • Concentration Risk: Over-allocation to high-risk markets
  • Governance Risk: Malicious or incompetent curator actions

Operational Risk

  • Oracle Risk: Price feed manipulation or failure
  • Liquidation Risk: In underlying markets (for leveraged strategies)
  • Regulatory Risk: Changing regulations affecting DeFi protocols

Best Practices

Transaction Safety

  • Always use previewDeposit and previewWithdraw before transactions
  • Implement slippage protection for share price changes
  • Use multicall for atomic operations when possible

User Experience

  • Show both asset and share amounts for transparency
  • Display current share price and historical performance
  • Provide clear explanations of vault mechanics

Error Handling

  • Distinguish between user errors and system errors
  • Provide actionable error messages
  • Implement retry logic for network issues