Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ERC-7540: Move to Review #52

Merged
merged 11 commits into from
Nov 15, 2023
25 changes: 20 additions & 5 deletions ERCS/erc-7540.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Asynchronous ERC-4626 Tokenized Vaults
description: Extension of ERC-4626 with asynchronous deposit and redemption support
author: Jeroen Offerijns (@hieronx), Alina Sinelnikova (@ilinzweilin), Vikram Arun (@vikramarun), Joey Santoro (@joeysantoro)
discussions-to: https://ethereum-magicians.org/t/eip-7540-asynchronous-erc-4626-tokenized-vaults/16153
status: Draft
status: Review
type: Standards Track
category: ERC
created: 2023-10-18
Expand Down Expand Up @@ -45,7 +45,7 @@ The existing definitions from [ERC-4626](./eip-4626.md) apply. In addition, this

### Request Flows

ERC-7540 Vaults MUST implement one or both of asynchronous deposit and redemption Request flows. If either flow is not implemented in a Request pattern, it MUST use the ERC-4626 standard synchronous interaction pattern.
[ERC-7540 Vaults](./erc-7540.md) MUST implement one or both of asynchronous deposit and redemption Request flows. If either flow is not implemented in a Request pattern, it MUST use the ERC-4626 standard synchronous interaction pattern.

All ERC-7540 asynchronous tokenized Vaults MUST implement ERC-4626 with overrides for certain behavior described below.

Expand All @@ -72,7 +72,7 @@ After submission, Requests go through Pending, Claimable, and Claimed stages. An

An important Vault inequality is that following a Request(s), the cumulative requested quantity MUST be more than `pendingDepositRequest + maxDeposit - claimed`. The inequality may come from fees or other state transitions outside implemented by Vault logic such as cancellation of a Request, otherwise this would be a strict equality.

Requests MUST NOT skip or otherwise short-circuit the Claim state. In other words, to initiate and claim a Request, a user MUST call both request* and the corresponding Claim function separately, even in the same block.
Requests MUST NOT skip or otherwise short-circuit the Claim state. In other words, to initiate and claim a Request, a user MUST call both request* and the corresponding Claim function separately, even in the same block. Vaults MUST NOT "push" tokens onto the user after a Request, users MUST "pull" the tokens via the Claim function.

For asynchronous Vaults, the exchange rate between `shares` and `assets` including fees and yield is up to the Vault implementation. In other words, pending redemption Requests MAY NOT be yield bearing and MAY NOT have a fixed exchange rate.

Expand Down Expand Up @@ -272,9 +272,17 @@ Likewise yield on redemption Requests can accrue or not, and the exchange rate o

### Not allowing short-circuiting for claims

If claims can short circuit, this creates ambiguity for integrators and complicates the interface with overloaded behavior on Request functions.
If claims can short circuit, this creates ambiguity for integrators and complicates the interface with overloaded behavior on Request functions.

Instead there can be router contracts which atomically check for Claimable amounts immediately upon Request. Frontends can dynamically route Requests in this way depending on the state and implementation of the Vault.
An alternative Request flow could be as follows: user triggers a Request which enters Pending state. When the Vault fulfills the Request, the corresponding `assets/shares` are pushed straight to the user. This requires only 1 step on the user's behalf.

This approach has a few issues:
- cost/lack of scalability: as the number of vault users grows it can become intractably expensive to offload the Claim costs to the Vault operator
- hinders integration potential: Vault integrators would need to handle both the 2-step and 1-step case, with the 1-step pushing arbitrary tokens in from an unknown Request at an unknown time. This pushes complexity out onto integrators and reduces the standard's utility.

The 2-step approach used in the standard may be abstracted into a 1-step approach from the user perspective through the use of routers, relayers, message signing, or account abstraction.

In the case where a Request may become Claimable immediately in the same block, there can be router contracts which atomically check for Claimable amounts immediately upon Request. Frontends can dynamically route Requests in this way depending on the state and implementation of the Vault to handle this edge case.

### Operator function parameter on requestDeposit and requestRedeem

Expand Down Expand Up @@ -302,6 +310,9 @@ It reduces code and implementation complexity at little to no cost to simply man

Implementing support for [ERC-165](./eip-165.md) is mandated because of the [optionality of flows](#optionality-of-flows). Integrations can use the `supportsInterface` method to check whether a vault is fully asynchronous, partially asynchronous, or fully synchronous, and use a single contract to support all cases.

### Not Allowing Pending Claims to be Fungible
The async pending claims represent a sort of semi-fungible intermediate share class. Vaults can elect to wrap these claims in any token standard they like, for example ERC-20, [ERC-1155](./erc-1155.md) or ERC-721 depending on the use case. This is intentionally left out of the spec to provide flexibility to implementers.

## Backwards Compatibility

The interface is fully backwards compatible with [ERC-4626](./eip-4626.md). The specification of the `deposit`, `mint`, `redeem`, and `withdraw` methods is different as described in [Specification](#specification).
Expand All @@ -316,6 +327,10 @@ The methods `pendingDepositRequest` and `pendingRedeemRequest` are estimates use

In general, asynchronicity concerns make state transitions in the Vault much more complex and vulnerable to security risks. Access control on Vault operations, clear documentation of state transitioning, and invariant checks should all be performed to mitigate these risks.

In particular, shares or assets locked for Requests can be stuck in the Pending state. Vaults may elect to allow for fungibility of pending claims or implement some cancellation functionality to protect users.

Moreover, users might not know what the final exchange rate will be on any Request due to the asynchronicity. Users therefore trust the implementation of the asynchronous Vault in the computation of the exchange rate and fulfillment of their Request.

It is worth highlighting again here that the Claim functions for any asynchronous flows MUST enforce that `msg.sender == operator/owner` to prevent theft of Claimable `assets` or `shares`

## Copyright
Expand Down