ERC4626: The Game Changer for Interest-Bearing Crypto

Vicente Bermúdez
5 min readDec 10, 2023

What is ERC4626?

  • It’s a tokenized vault standard that uses ERC20 tokens to represent shares of an asset.
  • Used in crypto lending markets, aggregators, and interest-bearing tokens. This standard is key to DeFi protocols.
  • Designed to allow developers to easily configure the vault’s behavior to include specific financial logic.

How it works

  • You deposit an asset (for example, an ERC20 token) into the contract, and get a token back. These are called “shares”.
  • Shares represent your ownership of the tokens stored in the contract.
  • At some other moment, you may transfer your shares to the vault to get the deposited assets back.
  • If, proportionally, the contract now has a higher asset per share than previously, your shares will represent a larger amount of assets.

For example: Initially, the vault contains 100 assets for 10 shares. (10:1 ratio) → I convert 10 assets into 1 share. → Someone else donates 10 assets into the vault. (now, 11:1 ratio) → I can convert my share into 11 assets.

Motivation

Suppose you own a company earning WETH, and each month it receives 10 ETH from NFT sales revenue, distributed among 5 shareholders. Here are the primary challenges:

  • Shares configuration: What if there are changes in share distribution or new equity holders join the company?
  • Permissions: The logic should safeguard against unauthorized updates to the shares of individual shareholders.
  • Ledger: The contract must maintain a ledger to record the owed asset amounts for each shareholder.
  • Transfer: When the business owner claims their part of the revenue, the contract would need to update the ledger and transfer the corresponding WETH to their EOA or wallet address.

With ERC4626, these difficulties cease to exist, and gas fees are lower since we don’t need as much access control and ledger arithmetic.

Let’s say you want to build an NFT company with nine friends. Each of you deposits 10 WETH to the ERC4626 vault, and as a result, you get one share of the company. This is the initial investment you’ve made to get the company running, and that one share is the official representation of your part in it. (100 WETH / 10 shares)

You guys just launched a series of cute randomly-generated capybara JPEGs, and the sales have come in, earning the company a total of 10 WETH. Now the ratio is 110 WETH per 10 shares, or in other words, the value of the company has gone up — and your share is worth 10% more.

Notice how the calculation of WETH owed to a shareholder is just one operation — a simple division. This is much easier than controlling and keeping track of a debt ledger and shareholder representation.

However, there are many ways to configure the vault. You can have an arbitrary formula that determines the relationship between shares and assets. This flexibility allows us to implement different mechanisms such as tax enforcement rules when withdrawing assets from the vault.

Note: The use case I mentioned is an example, and ERC4626 can find applications in various financial scenarios beyond this illustration.

Solidity implementation 🤓

The most important functions:

  • function asset() returns (address): Returns the contract address of the underlying asset token. (e.g WETH)
  • function totalAssets() returns (uint256): Returns the total asset count of the underlying asset token. In our previous example, this would be the 11 WETH the company owns after selling their NFTs.
  • function deposit(uint256 address, address receiver) public virtual override returns (uint256) — You request a deposit, and the contract transfers that amount to the vault’s address, and then mints shares for the receiver. Returns total shares generated.
  • function mint(uint256 shares, address receiver) public virtual override returns (uint256) — You specify how many shares you want, and the function will calculate how many assets to transfer from you. Returns total shares generated.

Prediction

Static calls to previewDeposit and previewMint will allow you to predict the assets needed for a deposit. No gas is required. convertToShares will return the shares you’d get under ideal conditions — no slippage or fees. These methods can be used to calculate fees, substractingconvertToShared by previewMint or previewDeposit .

Withdrawing

To withdraw, you specify how many assets you want to take from the vault, and then the contract will burn the required amount of your shares. There’s also the redeem function, which will burn a given amount of shares, and transfer the equivalent of assets. With previewWithdrawand convertToAssets, the same predictive logic applies to this.

Events

ERC4626 has only two events in addition to the ERC20 events it inherits: Deposit and Withdraw. These are also emitted if mint and redeem were called, because functionally the same thing happened: tokens were swapped.

Problem: Slippage

Slippage: this is the issue where the user does not get back the amount of tokens they were expecting.

For example, liquidity pools. These “pools” are composed of a pair of tokens — for instance, LINK and SHIB. Users can deposit ETH to get an LP (interest-bearing liquidity pool token) to represent their contribution. Subsequently, they can swap LINK to obtain SHIB, and vice-versa. However, several transactions can occur before your swap order gets included in a block so the actual amount of SHIB obtained can change. Despite a formula for estimating returns, accuracy is still uncertain, introducing the concept of “slippage tolerance”. The user can set a percentage as an acceptable price slippage from the estimated rate.

To safeguard against slippage, the ERC4626 contract should assess the shares received during a deposit (and assets during a withdrawal). It should simply revert the transaction if the received quantity falls outside the expected range, considering the specified tolerance (generally 2–5%).

Problem: Inflation attacks

Most implementations of this standard use a linear relationship. If there are 10,000 assets and 100 shares, then the asset-per-share ratio is 100. A big problem comes up:

  • A user wants to exchange 99 shares.
  • 99 shares = 0,99 assets.
  • Since the EVM only deals with integers, the user’s amount will be rounded down. In this scenario, it would be rounded down to zero.

Though it’s unlikely for someone to intentionally lose their assets this way, there’s a vulnerability to front-running attacks.

Frontrunning

  • A vault has a 100 asset per share ratio.
  • A user initiates an asset → share swap. The order’s inclusion in a block is delayed due to a low gas priority fee.
  • An attacker donates assets to the vault via a high-priority transaction. By setting a high gas priority fee, this transaction is quickly included in a block.
  • The ratio increases from 100 to 300 assets per share.
  • As a result of the executed attacker’s transaction, subsequent transactions, including the user’s, are impacted, leading the user to effectively contribute 100 assets to the pool.
  • The attacker exchanges shares for assets, gaining profit.

There are three protective measures:

  1. Revert the transaction if the received amount falls outside the specified slippage tolerance (generally 2–5%), as discussed earlier.
  2. The contract deployer should inject sufficient assets into the pool, making an inflation attack financially impractical.
  3. Introduce “virtual liquidity” to the vault, adjusting pricing as if the pool had originally been deployed with enough assets.

--

--