-
Notifications
You must be signed in to change notification settings - Fork 477
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
--- | ||
eip: 7575 | ||
title: Partial and Extended ERC-4626 Vaults | ||
description: Modular ERC-4626 Interface enabling Multi-Vault, Pipes, Partial and Alternative Vaults | ||
author: Jeroen Offerijns (@hieronx), Alina Sinelnikova (@ilinzweilin), Vikram Arun (@vikramarun), Joey Santoro (@joeysantoro), Farhaan Ali (@0xfarhaan) | ||
discussions-to: https://ethereum-magicians.org/t/erc-7575-partial-and-extended-erc-4626-vaults/17274 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2023-12-11 | ||
requires: 20, 165, 2771, 4626 | ||
--- | ||
|
||
## Abstract | ||
|
||
The following standard adapts [ERC-4626](./eip-4626.md) into several modular components which can be used in isolation or combination to unlock new use cases. | ||
|
||
New functionality includes multiple assets or entry points for the same share token, conversions between arbitrary tokens, and implementations which use partial entry/exit flows from ERC-4626. | ||
|
||
This standard adds nomenclature for the different components/interfaces of the base ERC-4626 standard including `ERC7575MinimalVaultInterface` and an interface for each entry/exit function. | ||
|
||
It adds a new `share` method to allow the [ERC-20](./eip-20.md) dependency to be externalized. | ||
|
||
Lastly, it enforces [ERC-165](./eip-165.md) support for Vaults. | ||
|
||
## Motivation | ||
|
||
[ERC-4626](./eip-4626.md) represents a "complete" and symmetrical standard for a Tokenized Vault pattern. Certain use cases may want to borrow functionality from 4626 to maintain some interface compatibility without wanting the entire standard. | ||
|
||
One major use case are Vaults which have multiple assets or entry points such as LP Tokens. These are generally unwieldy or non-compliant due to the requirement of ERC-4626 to itself be an ERC-20. | ||
|
||
Another are Vaults which don't have a true share token but rather convert between two arbitrary external tokens. | ||
|
||
Some Vaults always have a 1:1 conversion rate between `assets` and `shares` and would benefit from being able to implement only one entry or exit function from the Vault rather than both. | ||
|
||
There are so many customizeable use cases that it is beneficial to modularize the Vault standard. | ||
|
||
## Specification | ||
|
||
### Definitions: | ||
|
||
The existing definitions from [ERC-4626](./eip-4626.md) apply. | ||
|
||
- Multi-Vault: A Vault which has multiple assets/entry points | ||
- Pipe: A converter from one token to another (unidirectional or bidirectional) | ||
- Entry Function: A Vault function which converts `asset` to `shares`. Either `deposit` or `mint` in ERC-4626 | ||
- Exit Function: A Vault function which converts `shares` to `assets`. Either `withdraw` or `redeem` in ERC-4626 | ||
- Partial Vault: A Vault which implements only one Entry or Exit function from ERC-4626 | ||
|
||
First the standard defines a new `share` function which is useful for many configurable use cases, and then goes into detail on the requirements for different configurations. | ||
|
||
### Methods | ||
|
||
#### share | ||
|
||
The address of the underlying `share` received on deposit into the Vault. MUST return an address of an ERC-20 share representation of the Vault. | ||
|
||
`share` MAY return the address of the Vault itself. | ||
|
||
If the `share` returns an external token i.e. `share != address(this)`: | ||
* entry functions MUST increase the `share` balance of the `receiver` by the `shares` amount. i.e. `share.balanceOf(receiver) += shares` | ||
* exit functions MUST decrease the `share` balance of the `owner` by the `shares` amount. i.e. `share.balanceOf(owner) -= shares` | ||
|
||
MUST _NOT_ revert. | ||
|
||
```yaml | ||
- name: share | ||
type: function | ||
stateMutability: view | ||
|
||
inputs: [] | ||
outputs: | ||
- name: shareTokenAddress | ||
type: address | ||
``` | ||
### `ERC7575MinimalVault` Interface | ||
The Minimal Vault Interface consists of the methods which are required for any `share` based Vault with a corresponding deposit `asset`. | ||
|
||
It is defined as the following ERC-4626 methods (and `share` described above): | ||
- `asset` | ||
- `share` | ||
- `convertToAssets` | ||
- `convertToShares` | ||
- `totalAssets` | ||
|
||
It also includes the `Deposit` and `Withdraw` events. | ||
|
||
### Partial Vault Interfaces | ||
A Partial Vault omits at least one of the ERC-4626 entry or exit functions. | ||
|
||
A Partial Vault MUST implement both the `preview*` and `max*` methods associated with any implemented entry/exit functions. | ||
|
||
Partial Vaults SHOULD prefer implementing `deposit` and `redeem` over `mint` and `withdraw`, respectively. | ||
|
||
A Partial Vault MAY implement none of the ERC-4626 entry or exit functions and instead use a bespoke entry/exit. In this case it still MUST implement `ERC7575MinimalVault` interface. Any bespoke entry/exit from the Vault MUST emit `Deposit` or `Withdraw`, respectively. | ||
|
||
This standard defines four modular interfaces beyond the Minimal Vault Interface: | ||
- `ERC7575DepositVault` - `deposit`, `previewDeposit`, `maxDeposit` | ||
- `ERC7575MintVault` - `mint`, `previewMint`, `maxMint` | ||
- `ERC7575RedeemVault` - `redeem`, `previewRedeem`, `maxRedeem` | ||
- `ERC7575WithdrawVault` - `withdraw`, `previewWithdraw`, `maxWithdraw` | ||
|
||
### Multi-Vaults | ||
Multi-vaults share a single `share` token with multiple entry points denominated in different `asset` tokens. | ||
|
||
Multi-vaults MUST implement the `share` method on each entry point. The entry points SHOULD NOT be ERC-20. | ||
|
||
### Pipes | ||
Pipes convert between a single `asset` and `share` which are both ERC-20 tokens outside the Vault. | ||
|
||
A Pipe MAY be either unidirectional or bidirectional. | ||
|
||
If the exchange rate is fixed, the Pipe SHOULD be a Partial Vault implementing only `deposit` and/or `redeem`. | ||
|
||
A unidirectional Pipe SHOULD implement only the entry function(s) `deposit` and/or `mint`. | ||
|
||
### [ERC-165](./eip-165.md) support | ||
|
||
Smart contracts implementing any of the above Vault interfaces MUST implement the [ERC-165](./eip-165.md) `supportsInterface` function. | ||
|
||
`ERC7575MinimalVault` MUST return the constant value `true` if `0x50a526d6` is passed through the `interfaceID` argument. | ||
|
||
`ERC7575DepositVault` MUST return the constant value `true` if `0xc1f329ef` is passed through the `interfaceID` argument. | ||
|
||
`ERC7575MintVault` MUST return the constant value `true` if `0xe1550342 ` is passed through the `interfaceID` argument. | ||
|
||
`ERC7575RedeemVault` MUST return the constant value `true` if `0x2fd7d42a ` is passed through the `interfaceID` argument. | ||
|
||
`ERC7575WithdrawVault` MUST return the constant value `true` if `0x70dec094 ` is passed through the `interfaceID` argument. | ||
|
||
If a Vault implements all 5 interfaces, it MUST also return the constant value `true` if `0x2f0a18c5` is passed through the `interfaceID` argument. This value is the chained XOR of all 5 interfaces, i.e. the [ERC-165](./eip-165.md) compliant `interfaceID` for the complete [ERC-7575](./eip-7575.md) implementation. | ||
|
||
## Rationale | ||
|
||
This standard is intentionally flexible to support both existing [ERC-4626](./eip-4626.md) Vaults easily by the introduction of a single new method, but also flexible to support new use cases by allowing separate share tokens. | ||
|
||
### Ability to externalize ERC20 Dependency | ||
By allowing share != address(this), the Vault can have an external contract managing the ERC20 functionality of the Share. In the case of Multi-Vaults, this avoids the confusion that might arise if each Vault itself were required to be an ERC20, which could cause confusion for integrators and front-ends. This approach also enables the creation of new types of Vaults, such as Pipes, which facilitate the conversion between two external ERC20 tokens. | ||
|
||
|
||
## Backwards Compatibility | ||
|
||
Existing [ERC-4626](./eip-4626.md) Vaults can be made compatible with ERC-x by adding a single `share` method that returns the address of the Vault. | ||
|
||
## Reference Implementation | ||
|
||
N/A | ||
## Security Considerations | ||
|
||
[ERC-20](./eip-20.md) non-compliant Vaults must take care with supporting a redeem flow where `owner` is not `msg.sender`, since the [ERC-20](./eip-20.md) approval flow does not by itself work if the Vault and share are separate contracts. It can work by setting up the Vault as a Trusted Forwarder of the share token, using [ERC-2771](./eip-2771.md). | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |