Skip to content

Commit

Permalink
EIP-4626: Tokenized Vault Standard (ethereum#4626)
Browse files Browse the repository at this point in the history
* Create eip-4626.md

* Update eip-4626.md

* Update eip-4626.md

Co-authored-by: Micah Zoltu <micah@zoltu.net>

* Update eip-4626.md

* Update eip-4626.md

* Apply suggestions from code review

* Update eip-4626.md

Co-authored-by: William Schwab <31592931+wschwab@users.noreply.github.com>

* Update eip-4626.md

Co-authored-by: William Schwab <31592931+wschwab@users.noreply.github.com>

* Update eip-4626.md

Co-authored-by: t11s <greenfeatherhelp@gmail.com>

* Update eip-4626.md

Co-authored-by: t11s <greenfeatherhelp@gmail.com>

* Update eip-4626.md

Co-authored-by: t11s <greenfeatherhelp@gmail.com>

* Update eip-4626.md

Co-authored-by: t11s <greenfeatherhelp@gmail.com>

* Update eip-4626.md

Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com>

* Update eip-4626.md

* Backward compatibility

and withdrawFrom, redeemFrom, events

* Fixes

* Update eip-4626.md

* Apply suggestions from code review

* move eip into eips folder

Co-authored-by: Micah Zoltu <micah@zoltu.net>
Co-authored-by: William Schwab <31592931+wschwab@users.noreply.github.com>
Co-authored-by: t11s <greenfeatherhelp@gmail.com>
Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com>
Co-authored-by: lightclient@protonmail.com <lightclient@protonmail.com>
  • Loading branch information
6 people authored and PhABC committed Jan 25, 2022
1 parent e0a8cdd commit 1b70718
Showing 1 changed file with 148 additions and 0 deletions.
148 changes: 148 additions & 0 deletions EIPS/eip-4626.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
---
eip: 4626
title: Tokenized Vault Standard
description: A standard for tokenized vaults with a single underlying ERC-20 token.
author: Joey Santoro (@joeysantoro), t11s (@transmissions11), Jet Jadeja (@JetJadeja)
discussions-to: https://ethereum-magicians.org/t/eip-4626-yield-bearing-vault-standard/7900
status: Draft
type: Standards Track
category: ERC
created: 2021-12-22
---

## Abstract

The following standard allows for the implementation of a standard API for tokenized vaults with a single underlying [ERC-20](./eip-20.md) within smart contracts. This standard is an extension on the ERC-20 token that provides basic functionality for depositing and withdrawing tokens and reading balances.

## Motivation

Tokenized vaults have a lack of standardization leading to diverse implementation details. Some various examples include lending markets (Compound, Aave, Fuse), aggregators (Yearn, Rari Vaults, Idle), and intrinsically interest bearing tokens (xSushi). This makes integration difficult at the aggregator or plugin layer for protocols which need to conform to many standards. This forces each protocol to implement their own adapters which are error prone and waste development resources.

A standard for tokenized vaults will allow for a similar cambrian explosion to ERC-20, unlocking access to yield and other strategies in a variety of applications with little specialized effort from developers.


## Specification

All tokenized vaults MUST implement ERC20. If a vault is to be non-transferrable, it MAY revert on calls to transfer or transferFrom. The ERC20 operations balanceOf, transfer, totalSupply, etc. operate on the vault "shares" which represent ownership in the underlying.

### Methods

#### deposit

`function deposit(address _to, uint256 _value) public returns (uint256 _shares)`

Deposits `_value` tokens into the vault and grants ownership of them to `_to`.

MUST emit the `Deposit` event.

#### withdraw

`function withdraw(address _to, uint256 _value) public returns (uint256 _shares)`

Withdraws `_value` tokens from the vault and transfers them to `_to`.

MUST emit the `Withdraw` event.

#### withdrawFrom

`function withdrawFrom(address _from, address _to, uint256 _value) public returns (uint256 _shares)`

Withdraws `_value` tokens from owner `_from` and transfers them to `_to`.

MUST share the same authorization mechanism as transferFrom.

MUST emit the `Withdraw` event.

#### redeem

`function redeem(address _to, uint256 _shares) public returns (uint256 _value)`

Redeems a specific number of `_shares` for underlying tokens and transfers them to `_to`.

MUST emit the `Withdraw` event.

#### redeemFrom

`function redeemFrom(address _from, address _to, uint256 _shares) public returns (uint256 _value)`

Redeems a specific number of `_shares` from owner `_from` for underlying tokens and transfers them to `_to`.

MUST share the same authorization mechanism as transferFrom.

MUST emit the `Withdraw` event.

#### totalUnderlying
`function totalUnderlying() public view returns (uint256)`

Returns the total amount of underlying tokens held/managed by the vault.

#### balanceOfUnderlying
`function balanceOfUnderlying(address _owner) public view returns (uint256)`

Returns the total amount underlying tokens held in the vault for `_owner`.

#### underlying
`function underlying() public view returns (address)`

Returns the address of the token the vault uses for accounting, depositing, and withdrawing.

MUST return the address of a token implementing the ERC-20 standard.

#### calculateShares
`function calculateShares(uint256 underlyingAmount) public view returns (uint256 sharesAmount)`

Returns the amount of vault shares corresponding to a given underlying amount.

`calculateShares(calculateUnderlying(sharesAmount))` MUST equal `sharesAmount`

#### calculateUnderlying

`function calculateUnderlying(uint256 sharesAmount) public view returns (uint256 underlyingAmount)`;

Returns the amount of underlying tokens corresponding to a given amount of vault shares.

`calculateUnderlying(calculateShares(underlyingAmount))` MUST equal `underlyingAmount`

### Events

#### Deposit

MUST be emitted when tokens are deposited into the vault.

`event Deposit(address indexed _from, address indexed _to, uint256 _value)`

Where `_from` is the user who triggered the deposit for `_value` underlying tokens to the vault, and `_to` is the user who is able to withdraw the deposited tokens.


#### Withdraw

MUST be emitted when tokens are withdrawn from the vault by a depositor.

`event Withdraw(address indexed _from, address indexed _to, uint256 _value)`

Where `_from` is the owner who and held `_value` underlying tokens in the vault, and `_to` is the user who received the withdrawn tokens.


## Rationale

The vault interface is designed to be optimized for minimal implementation and integration logic while maintaining flexibility for both parties. Details such as accounting and allocation of deposited tokens are intentionally not specified, as vaults are expected to be treated as black boxes on-chain and inspected off-chain before use.

ERC20 is forced because implementation details like token approval and balance calculation directly carry over to the shares accounting. This standardization makes the vaults immediately compatible with all ERC20 use cases in addition to ERC4626.

## Backwards Compatibility

ERC-4626 is fully backward compatible with the ERC-20 standard and has no known compatibility issues with other standards. For production implementations of vaults which do not use ERC-4626, wrapper adapters can be developed and used.

## Reference Implementation

[Solmate Minimal Implementation](https://github.com/Rari-Capital/solmate/pull/88) - a tokenized vault using the ERC-20 extension with hooks for developers to add logic in deposit and withdraw.

[Rari Vaults](https://github.com/Rari-Capital/vaults/blob/main/src/Vault.sol) are an implementation that is nearly ready for production release. Any discrepancies between the vaults abi and this ERC will be adapted to conform to the ERC before mainnet deployment.

## Security Considerations

This specification has similar security considerations to the ERC-20 interface. Fully permissionless yield aggregators, for example, could fall prey to malicious implementations which only conform to the interface but not the specification.

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 comments on commit 1b70718

Please sign in to comment.