Skip to content

Morpho Earn Integration Guide - Solidity

Smart Contract Functions

When integrating Morpho Vaults into your application, you'll primarily work with the ERC4626 standard interface functions. This guide focuses on the core deposit and withdrawal functions that your users will need.

Approval

Before any deposit can occur, users must approve the Morpho Vault to use their tokens. A basic allowance or permit function is required.

Basic approval

// First approve the vault to spend your tokens
IERC20(underlyingToken).approve(vaultAddress, amount);

permit approval

All Morpho Vaults implement EIP-2612 permit, allowing for gasless approvals:

// Gasless approval using permit
function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;

Deposit & Mint

Morpho Vaults offer two methods for depositing assets:

Deposit

Use deposit() when you know exactly how many tokens you want to deposit. This can be considered as an "Asset-First Approach"

// Deposit exactly 1000 USDC into the vault
uint256 amountToDeposit = 1000 * 10**6; // 1000 USDC with 6 decimals
uint256 sharesReceived = IMetaMorpho(vaultAddress).deposit(amountToDeposit, receiverAddress);

When to use: Most common scenario - user knows how much they want to deposit.

Mint

Use mint() when you want to receive a specific number of vault shares. This can be considered as a "Shares-First Approach"

// Mint exactly 500 vault shares
uint256 sharesToMint = 500 * 10**18; // 500 shares with 18 decimals
uint256 assetsDeposited = IMetaMorpho(vaultAddress).mint(sharesToMint, receiverAddress);

When to use: User wants to receive a specific number of vault shares.

Withdraw & Redeem

Morpho Vaults also offer two methods for withdrawing assets:

Withdraw

Use withdraw() when you want to receive a specific amount of underlying tokens. This can be considered as an "Asset-First Approach"

// Withdraw exactly 500 USDC from the vault
uint256 amountToWithdraw = 500 * 10**6; // 500 USDC with 6 decimals
uint256 sharesBurned = IMetaMorpho(vaultAddress).withdraw(
    amountToWithdraw,
    receiverAddress, // Where to send the tokens
    ownerAddress     // Who owns the shares being burned
);

When to use: When users need a specific amount of tokens.

Redeem

Use redeem() when you want to withdraw with a specific amount of vault shares. This can be considered as a "Shares-First Approach"

// Redeem exactly 300 vault shares
uint256 sharesToRedeem = 300 * 10**18; // 300 shares with 18 decimals
uint256 assetsReceived = IMetaMorpho(vaultAddress).redeem(
    sharesToRedeem,
    receiverAddress, // Where to send the tokens
    ownerAddress     // Who owns the shares being burned
);

When to use: For full withdrawals, this is typically better as it avoids dust.

Key Differences

Understanding the differences is crucial for proper integration:

FunctionInputOutputUse Case
depositAsset amountShares receivedMost common: "I want to deposit X tokens"
mintShares amountAssets requiredAdvanced: "I want exactly Y shares"
withdrawAsset amountShares burnedSpecific: "I need X tokens back"
redeemShares amountAssets receivedBest for full exit: "Redeem all my shares"

Practical Implementation Tips

For Deposits:

  • Always use deposit() unless you have a specific reason to use mint()
  • Remember to handle approvals before calling deposit functions

For Withdrawals:

  • Use redeem() for full withdrawals to avoid dust
  • Use withdraw() when users need specific token amounts
  • Check maxRedeem() and maxWithdraw() before executing to avoid reverts

Gas Optimization:

  • For large vaults with many markets, withdrawals may be gas-intensive

Edge Case:

  • During high utilization, withdrawals may be limited by available liquidity in the resp. market where the vault allocated its liquidity into