ERC-4626 Tokenized Vault Standard (Tokenized Vaults)

Final · Vaults & DeFi · created 2021-12-22

Defines a common deposit and withdrawal interface for a vault that accepts a single ERC-20 token and gives back shares in the form of a token. Wallets and apps do not have to write different integration code for each vault.

Why it is needed

Ethereum has many vault-style services that return a share token when you deposit tokens. Lending markets, aggregators that split funds across multiple places, and tokens that earn interest just by being held are typical examples. However, these vaults have no standard, so their implementation details differ. As a result, integration is difficult for aggregators or plugin layers that must support many standards at once, and each protocol had to build its own adapter. Adapters are prone to mistakes and waste development resources. This standard aims to unify the share token as ERC-20 and define deposit, withdrawal and query functions, which reduces the effort of integrating yield-bearing vaults and makes implementations more consistent and robust.

What to implement

In depth

Shares must be ERC-20 tokens

A vault that follows the standard must implement EIP-20 to represent shares. All EIP-20 behavior such as balanceOf, transfer and totalSupply applies to the vault's shares. A share represents ownership of a portion of the underlying assets the vault holds. If you want to make shares non-transferable, you may revert calls to transfer and transferFrom (MAY). The optional metadata extension of EIP-20 must be implemented. The name and symbol must reflect the name and symbol of the underlying token in some way (SHOULD). To improve the share approval experience across services, EIP-2612 may be implemented (MAY).

Four terms: asset, share, fee, slippage

An asset is the underlying token the vault manages, and its unit is set by the corresponding EIP-20 contract. A share is the vault's token, and the vault decides the rate at which shares are exchanged for the underlying asset on mint, deposit, withdraw and redeem. A fee is an amount of assets or shares the vault charges users, and it can be applied to any item the vault chooses, such as deposits, yield, assets under management (AUM) or withdrawals. Slippage is the part of the difference between the quoted share price and the actual deposit or withdrawal result that is not explained by fees.

View functions: asset, totalAssets, convertToShares, convertToAssets

asset returns the address of the underlying token used for accounting, deposits and withdrawals. It MUST be an EIP-20 token contract and MUST NOT revert. totalAssets is the total amount of underlying assets the vault manages. It SHOULD include any compounding that occurs from yield, MUST include any fees charged against vault assets, and MUST NOT revert. convertToShares and convertToAssets give the amount of shares or assets the vault would exchange under ideal conditions. They do not include fees and do not vary by caller. They also do not reflect on-chain conditions such as slippage. They MUST NOT revert except for integer overflow caused by unreasonably large inputs, and MUST round down toward 0. The value shows the price per share an average user would expect, not the price for a specific user.

max functions: the maximum amount currently possible

maxDeposit and maxMint are the maximum amount of assets and the maximum amount of shares that can be put in for the receiver through deposit or mint. maxWithdraw and maxRedeem are the maximum amount of assets and the maximum amount of shares that can be taken out of the owner's balance through withdraw or redeem. None of the four functions may return a value higher than the actual maximum that would be accepted, and they should underestimate if necessary. They MUST reflect both global limits and per-user limits, and return 0 if the action is disabled, even temporarily. maxDeposit and maxMint return 2 ** 256 - 1 if there is no limit. They assume the user has unlimited assets, so they must not rely on the balanceOf of asset. None of the four functions may revert.

preview functions: exact simulation within the same block

previewDeposit, previewMint, previewWithdraw and previewRedeem compute the result of an actual call in advance, under the on-chain conditions of the current block. previewDeposit returns a value no greater than the shares that deposit would mint, and previewRedeem returns a value no greater than the assets that redeem would return. previewMint returns a value no less than the assets that mint would take, and previewWithdraw returns a value no less than the shares that withdraw would burn. In other words, within the same transaction the actual function gives the user a result equal to or better than the preview. They MUST include deposit or withdrawal fees, and they ignore the limits from the max functions and any approval status, assuming the call is always accepted. They MUST NOT revert because of vault limits, but may revert for other conditions that would cause the actual function to revert. If the convertTo value and the preview value differ unfavorably, the difference should be treated as slippage in the share price.

Deposit and withdrawal functions: deposit, mint, withdraw, redeem

deposit takes in exactly assets of the underlying token and mints the corresponding shares to the receiver. mint mints exactly shares and takes the assets required. Both MUST emit the Deposit event and MUST support the EIP-20 approve and transferFrom flow for asset. They MAY additionally support a flow in which the underlying token is transferred to the vault before execution. They MUST revert if they cannot process the full amount. withdraw burns the owner's shares and sends exactly assets to the receiver. redeem burns exactly shares and sends the assets. Both MUST emit the Withdraw event and MUST support both the case where the owner is msg.sender and the case where msg.sender has EIP-20 approval over the owner's shares. They SHOULD check with allowance whether msg.sender can spend the owner's funds. withdraw converts the assets to shares and then checks against those shares. Some implementations require a prior request to the vault before withdrawal, and that step is performed separately.

Deposit and Withdraw events

The Deposit event means the sender converted assets into shares and delivered those shares to the owner. It MUST be emitted when tokens enter the vault through mint and deposit. sender and owner are indexed, and assets and shares are not indexed. The Withdraw event means the sender converted the owner's shares into assets and delivered those assets to the receiver. It MUST be emitted when shares leave through redeem and withdraw. sender, receiver and owner are indexed, and assets and shares are not indexed.

Design rationale and compatibility

The interface is designed to be feature-complete yet minimal, tailored to the parties that integrate with it. How deposited tokens are accounted for and allocated is deliberately left unspecified. On-chain, a vault is treated as a black box, and the standard assumes it is inspected off-chain before use. EIP-20 is required because implementation details such as approvals and balance calculations carry directly into share accounting, and because it is immediately compatible with all existing EIP-20 use cases. mint is included for symmetry and completeness. Targeting a specific number of shares is rare today, but one can imagine strategies in which the shares themselves carry unique meaning. The convertTo functions are rough estimates that ignore fees and are meant for frontends. Exact values come from the preview function paired with each state-changing function, and limits come from the max functions. That preview does not reflect limits is a choice made to make composition easier. This standard is fully compatible with EIP-20, and existing vaults that do not use the standard can be wrapped with an adapter. The status is Final.

Things to watch out for

Original ERC · ← ERCs