Skip to content

Commit

Permalink
Update ERC-7540: Spell check ERC7540 and ERC7575
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
hieronx authored Apr 28, 2024
1 parent 884fcf1 commit b90325d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 24 deletions.
41 changes: 21 additions & 20 deletions ERCS/erc-7540.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The following standard extends [ERC-4626](./eip-4626.md) by adding support for a

New methods are added to asynchronously Request a deposit or redemption, and view the status of the Request. The existing `deposit`, `mint`, `withdraw`, and `redeem` ERC-4626 methods are used for executing Claimable Requests.

Implementations can choose to whether to add asynchronous flows for deposits, redemptions, or both.
Implementations can choose whether to add asynchronous flows for deposits, redemptions, or both.

## Motivation

Expand All @@ -37,7 +37,7 @@ The existing definitions from [ERC-4626](./eip-4626.md) apply. In addition, this
- Pending: the state where a Request has been made but is not yet Claimable
- Claimable: the state where a Request is processed by the Vault enabling the user to claim corresponding `shares` (for async deposit) or `assets` (for async redeem)
- Claimed: the state where a Request is finalized by the user and the user receives the output token (e.g. `shares` for a deposit Request)
- Claim function: the corresponding Vault method to bring a Request to Claimed state (e.g. `deposit` or `mint` claims `shares` from `requestDeposit`). Lower case claim always describes the verb action of calling a Claim function.
- Claim function: the corresponding Vault method to bring a Request to Claimed state (e.g. `deposit` or `mint` claims `shares` from `requestDeposit`). Lowercase claim always describes the verb action of calling a Claim function.
- asynchronous deposit Vault: a Vault that implements asynchronous Requests for deposit flows
- asynchronous redemption Vault: a Vault that implements asynchronous redemption flows
- fully asynchronous Vault: a Vault that implements asynchronous Requests for both deposit and redemption
Expand Down Expand Up @@ -71,11 +71,11 @@ After submission, Requests go through Pending, Claimable, and Claimed stages. An

Note that `maxDeposit` increases and decreases in sync with `claimableDepositRequest`.

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.
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. 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.
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.

### Request Ids
The request ID (`requestId`) of a request is returned by the corresponding `requestDeposit` and `requestRedeem` functions.
Expand All @@ -84,7 +84,7 @@ Multiple requests may have the same `requestId`, so a given Request is discrimin

Requests of the same `requestId` MUST be fungible with each other (except in the special case `requestId == 0` described below). I.e. all Requests with the same `requestId` MUST transition from Pending to Claimable at the same time and receive the same exchange rate between `assets` and `shares`.

If a Request becomes partially claimable, all requests of the same `requestId` MUST become claimable at the same pro rata rate.
If a Request becomes partially claimable, all requests of the same `requestId` MUST become claimable at the same pro-rata rate.

There are no assumptions or requirements of requests with different `requestId`. I.e. they MAY transition to Claimable at different times and exchange rates with no ordering or correlation enforced in any way.

Expand Down Expand Up @@ -187,7 +187,7 @@ Assumes control of `shares` from `owner` and submits a Request for asynchronous

The output `requestId` is used to partially discriminate the request along with the `receiver`. See [Request Ids](#request-ids) section for more info.

MAY support either a locking or a burning mechanism for `shares` depending on the Vault implemention.
MAY support either a locking or a burning mechanism for `shares` depending on the Vault implementation.

If a Vault uses a locking mechanism for `shares`, those `shares` MUST be burned from the Vault balance before or upon claiming the Request.

Expand All @@ -197,7 +197,7 @@ If the length of `data` is not 0, the Request MUST send an `onERC7540RedeemRecei

When the Request is Claimable, `claimableRedeemRequest` will be increased for the `receiver`. `redeem` or `withdraw` can subsequently be called by `receiver` to receive `assets`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state.

The `assets` that will be received on `redeem` or `withdraw` MAY NOT be equivalent to the value of `convertToAssets(shares)` at time of Request, as the price can change between Pending and Claimed.
The `assets` that will be received on `redeem` or `withdraw` MAY NOT be equivalent to the value of `convertToAssets(shares)` at the time of Request, as the price can change between Pending and Claimed.

SHOULD check `msg.sender` can spend `owner` funds using allowance.

Expand Down Expand Up @@ -410,7 +410,7 @@ Requests in an Asynchronous Vault have properties of NFTs or Semi-Fungible token

Using both an id and address to discriminate Requests allows for any of these use cases to be developed at an external layer without adding too much complexity to the core interface.

Certain Vaults especially `requestId==0` cases benefit from using the underlying [ERC-4626](./eip-4626) methods for claiming because there is no discrimination at the `requestId` level. This standard is written primarily with those use cases in mind. A future standard can optimize for nonzero request ID with support for claiming and transferring requests discriminated also with an `requestId`.
Certain Vaults especially `requestId==0` cases benefit from using the underlying [ERC-4626](./eip-4626) methods for claiming because there is no discrimination at the `requestId` level. This standard is written primarily with those use cases in mind. A future standard can optimize for nonzero request ID with support for claiming and transferring requests discriminated also with a `requestId`.

### Callbacks

Expand All @@ -428,11 +428,11 @@ Due to the asynchronous nature of Requests, the Vault can only operate with cert

Certain use cases are only asynchronous on one flow but not the other between Request and redeem. A good example of an asynchronous redemption Vault is a liquid staking token. The unstaking period necessitates support for asynchronous withdrawals, however, deposits can be fully synchronous.

### Non Inclusion of a Request Cancelation Flow
### Non-Inclusion of a Request Cancelation Flow

In many cases, canceling a Request may not be straightforward or even technically feasible. The state transition of cancelations could be synchronous or asynchronous, and the way to claim a cancelation interfaces with the remaining Vault functionality in complex ways.

A separate EIP should be developed to standardize behavior of cancelling a pending Request. Defining the cancel flow is still important for certain classes of use cases for which the fulfillment of a Request can take a considerable amount of time.
A separate EIP should be developed to standardizethe behavior of cancelling a pending Request. Defining the cancel flow is still important for certain classes of use cases for which the fulfillment of a Request can take a considerable amount of time.

### Request Implementation flexibility

Expand All @@ -442,31 +442,31 @@ 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.

An example of a short-circuiting 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.
- hinders integration potential: Vault integrators would need to handle both the 2-step and 1-step cases, 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.
In the case where a Request may become Claimable immediately in the same block, there can be router contracts that 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.

### No Outputs for Request functions

`requestDeposit` and `requestRedeem` may not have a known exchange rate that will happen when the Request becomes Claimed. Returning the corresponding `assets` or `shares` could not work in this case.

The Requests could also output a timestamp representing the minimum amount of time expected for the Request to become Claimable, however not all Vaults will be able to return a reliable timestamp.
The Requests could also output a timestamp representing the minimum amount of time expected for the Request to become Claimable, however, not all Vaults will be able to return a reliable timestamp.

### No Event for Claimable state

The state transition of a Request from Pending to Claimable happens at the Vault implementation level and is not specified in the standard. Requests may be batched into the Claimable state, or the state may transition automatically after a timestamp has passed. It is impractical to require an event to emit after a Request becomes Claimable at the user or batch level.

### Reversion of Preview Functions in Async Request Flows

The preview functions do not take an address parameter, therefore the only way to discriminate discrepancies in exchange rate are via the `msg.sender`. However, this could lead to integration/implementation complexities where support contracts cannot determine the output of a claim on behalf of an `owner`.
The preview functions do not take an address parameter, therefore the only way to discriminate discrepancies in the exchange rate is via the `msg.sender`. However, this could lead to integration/implementation complexities where support contracts cannot determine the output of a claim on behalf of an `owner`.

In addition, there is no on-chain benefit to previewing the Claim step as the only valid state transition is to Claim anyway. If the output of a Claim is undesirable for any reason, the calling contract can revert on the output of that function call.

Expand All @@ -477,11 +477,12 @@ 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](./eip-1155.md) or ERC-721 depending on the use case. This is intentionally left out of the spec to provide flexibility to implementers.
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](./eip-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).
The interface is fully backward compatible with [ERC-4626](./eip-4626.md). The specification of the `deposit`, `mint`, `redeem`, and `withdraw` methods is different as described in [Specification](#specification).

## Reference Implementation

Expand Down Expand Up @@ -531,10 +532,10 @@ The interface is fully backwards compatible with [ERC-4626](./eip-4626.md). The

## Security Considerations

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. For example:
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 transitions, and invariant checks should all be performed to mitigate these risks. For example:

* The view methods for viewing Pending and Claimable request states (e.g. pendingDepositRequest) are estimates useful for display purposes but can be outdated. The inability to know the final exchange rate will be on any Request requires users to trust the implementation of the asynchronous Vault in the computation of the exchange rate and fulfillment of their Request.
* 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.
* The view methods for viewing Pending and Claimable request states (e.g. pendingDepositRequest) are estimates useful for display purposes but can be outdated. The inability to know the final exchange rate on any Request requires users to trust the implementation of the asynchronous Vault in the computation of the exchange rate and fulfillment of their Request.
* Shares or assets locked for Requests can be stuck in the Pending state. Vaults may elect to allow for the fungibility of pending claims or implement some cancellation functionality to protect users.

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

Expand Down
8 changes: 4 additions & 4 deletions ERCS/erc-7575.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Lastly, it enforces [ERC-165](./eip-165.md) support for Vaults.

## Motivation

One missing use case that is not supported by [ERC-4626](./eip-4626.md) are Vaults which have multiple assets or entry points such as liquidity provider (LP) Tokens. These are generally unwieldy or non-compliant due to the requirement of ERC-4626 to itself be an [ERC-20](./eip-20.md).
One missing use case that is not supported by [ERC-4626](./eip-4626.md) is Vaults which have multiple assets or entry points such as liquidity provider (LP) Tokens. These are generally unwieldy or non-compliant due to the requirement of ERC-4626 to itself be an [ERC-20](./eip-20.md).

## Specification

Expand Down Expand Up @@ -103,15 +103,15 @@ The [ERC-20](./eip-20.md) implementation of `share` SHOULD implement a `vault` m
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 [ERC-20](./eip-20.md) Dependency
By allowing `share != address(this)`, the Vault can have an external contract managing the [ERC-20](./eip-20.md) functionality of the Share. In the case of Multi-Asset, this avoids the confusion that might arise if each Vault itself were required to be an [ERC-20](./eip-20.md), which could cause confusion for integrators and front-ends.
By allowing `share != address(this)`, the Vault can have an external contract managing the [ERC-20](./eip-20.md) functionality of the Share. In the case of Multi-Asset, this avoids the confusion that might arise if each Vault itself were required to be an [ERC-20](./eip-20.md), which could confuse 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 [ERC-20](./eip-20.md) tokens. These Pipes could be unidirectional (i.e. only for assets to shares via deposit/mint, or shares to assets via redeem/withdraw) or bidirectional for both entry and exit flows.

### Including Share-to-Vault lookup optionally

The `vault` method is included to lookup a Vault for a `share` by its `asset`. This enables integrations to easily query Multi-Asset Vaults.
The `vault` method is included to look up a Vault for a `share` by its `asset`. This enables integrations to easily query Multi-Asset Vaults.

This is optional, to maintain backwards compatibility with use cases where the `share` is an existing deployed contract.
This is optional, to maintain backward compatibility with use cases where the `share` is an existing deployed contract.


## Backwards Compatibility
Expand Down

0 comments on commit b90325d

Please sign in to comment.