ERC-4626 is the Ethereum standard for tokenized vaults. It extends ERC-20 with a uniform interface for depositing assets, receiving shares, and redeeming those shares for the underlying asset plus any yield the vault has earned. Before this standard, every protocol invented its own vault API, making integration painful and error-prone. ERC-4626 fixes that – one interface, universal composability.

The share/asset model#

A vault holds a pool of a single ERC-20 asset (e.g. DAI, USDC, WETH). Users deposit that asset and receive vault shares in return. The shares are themselves ERC-20 tokens, so they can be transferred, traded on a DEX, or used as collateral in other protocols.

As the vault earns yield – through lending, staking, yield farming, or any other strategy – the total assets in the vault grow while the share supply stays fixed. Each share becomes redeemable for more of the underlying asset over time.

The conversion math:

shares = deposit_amount * total_shares / total_assets
assets = shares * total_assets / total_shares

When the vault is empty, most implementations set a 1:1 initial exchange rate (often with a small offset to prevent share inflation attacks).

The interface#

ERC-4626 defines a compact set of functions on top of the standard ERC-20 interface:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IERC4626 is IERC20 {
    // The underlying asset
    function asset() external view returns (address);

    // Deposit `assets` and mint shares to `receiver`
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    // Burn `shares` from `owner` and send `assets` to `receiver`
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);

    // Burn shares to withdraw exactly `assets`
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    // Mint exactly `shares` by depositing the required assets
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    // Preview functions (read-only, for UI display)
    function previewDeposit(uint256 assets) external view returns (uint256 shares);
    function previewRedeem(uint256 shares) external view returns (uint256 assets);
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);
    function previewMint(uint256 shares) external view returns (uint256 assets);

    // Totals
    function totalAssets() external view returns (uint256);

    // Caps (may return type(uint256).max if unlimited)
    function maxDeposit(address receiver) external view returns (uint256);
    function maxRedeem(address owner) external view returns (uint256);
    function maxWithdraw(address owner) external view returns (uint256);
    function maxMint(address receiver) external view returns (uint256);
}

The four deposit/withdraw entry points (deposit, mint, withdraw, redeem) cover every combination of “I know how many assets I want to spend” vs. “I know how many shares I want to receive,” and the corresponding preview functions let frontends show the expected outcome before the user signs.

Yield-bearing use cases#

Use case How the vault earns yield
Lending (Aave, Compound) Interest from borrowers accrues to the vault’s asset balance
Staking (Lido’s wstETH wrapper) Staking rewards increase the underlying ETH per share
Yield aggregation (Yearn) Vault strategies rotate between the highest-yielding opportunities
LP positions Fees from an AMM liquidity pool accumulate in the vault

Because all of these expose the same deposit/redeem interface, a protocol that integrates one ERC-4626 vault can integrate any of them with zero additional code.

Why it matters#

Before ERC-4626, integrating with Yearn vaults required different code than integrating with Aave’s aTokens, which required different code again for Compound’s cTokens. Each had its own accounting quirks. ERC-4626 collapses this into a single integration target, which means:

  • Composability. A vault share can be deposited into another vault, used as collateral in a lending market, or traded on a DEX – all without custom adapters.
  • Auditing efficiency. A well-tested ERC-4626 base (like OpenZeppelin’s implementation) reduces the surface area for accounting bugs.
  • Ecosystem breadth. New yield sources become instantly compatible with every tool that speaks ERC-4626.

Security considerations#

  • Share inflation attacks. If a vault starts empty and an attacker donates assets before the first depositor, they can manipulate the exchange rate. The standard mitigation is to use virtual shares and assets (an offset) in the conversion math. OpenZeppelin’s ERC4626 contract does this by default.
  • Rounding. The spec requires that rounding always favours the vault (round down on deposit shares, round up on withdraw assets). Incorrect rounding can be exploited to drain the vault over many small transactions.