ERC-7540 Asynchronous Tokenized Vault Extension (Asynchronous ERC-4626 Tokenized Vaults)

Final · Vaults & DeFi · created 2023-10-18

An extension of ERC-4626 tokenized vaults that adds asynchronous deposits and redemptions. You submit a Request first, and once the vault finishes processing it, you receive the result through the existing ERC-4626 functions.

Why it is needed

The ERC-4626 tokenized vault standard made yield-bearing tokens easy to compose across DeFi, but it is optimized for a structure in which deposits and redemptions complete instantly in a single call. When a limit is reached, new deposits or redemptions cannot be accepted at all. This does not fit systems that must have asynchronous processing or delays before interacting with a vault, such as real-world asset (RWA) protocols, undercollateralized lending, cross-chain lending, liquid staking tokens and insurance safety modules. For example, unstaking has a waiting period, so a redemption cannot be processed immediately. This standard formalizes a two-step flow of submitting a request first and claiming later, so that the ERC-4626 vault interface can still be used in these asynchronous use cases.

What to implement

In depth

Choosing between the two flows and the ERC-4626 overrides

An ERC-7540 vault MUST implement at least one of asynchronous deposit and asynchronous redemption, and the side it does not implement must behave exactly like synchronous ERC-4626. In an asynchronous deposit vault, the asset transfer has already happened in requestDeposit, so deposit and mint do not move assets. previewDeposit and previewMint MUST revert for all callers and inputs. In an asynchronous redemption vault, redeem and withdraw likewise do not move shares, for the same reason. Renaming the owner field of those two functions to controller is recommended, and the controller must be msg.sender or an account that has approved msg.sender as an operator. previewRedeem and previewWithdraw MUST also revert.

Request lifecycle and the pull principle

After submission, a request passes through the Pending, Claimable and Claimed stages. A request can move to Claimable immediately, but it cannot skip the Claimable stage. Even within the same block, the user must call the request function and the claim function separately. A vault is forbidden from pushing tokens to the user after processing a request, and the user must pull them directly. maxDeposit rises and falls together with claimableDepositRequest. Whether a pending redemption request earns yield and whether its exchange rate is fixed depends on the implementation.

requestId rules

requestId is returned by requestDeposit and requestRedeem. Multiple requests can share the same requestId, so a request is identified by the combination of requestId and controller. Requests with the same requestId must be fungible. That is, they must move from Pending to Claimable at the same time and receive the same exchange rate. If a request with a nonzero requestId becomes partially claimable, all requests with the same requestId must become claimable together at the same ratio. There is no requirement on ordering or correlation between different requestIds. If requestId is 0, the vault distinguishes request state only by controller and aggregates multiple requests from the same controller. A vault that returns 0 for any one request must return 0 for all requests.

Controllers and operators

The controller is the owner of a request and manages request-related actions, including receiving assets or shares. An account can approve another account as an operator with setOperator to let it manage the account's requests, and isOperator queries the approval status. The owner of requestDeposit must be msg.sender or an account that has approved msg.sender as an operator. In requestRedeem, msg.sender's authority, when msg.sender is not the owner, can come from an ERC-20 approve on the shares or from an operator approval. The way allowances are deducted must match the approval and operator rules of ERC-6909. In addition, overloads of deposit and mint that add a controller input must be supported, and they must revert unless msg.sender is the controller itself or an approved operator. In this case the first parameter of the Deposit event must be the controller and the second must be the receiver.

Why requestMint and requestWithdraw do not exist

ERC-4626 provides both deposit/withdraw and mint/redeem for converting between assets and shares, which makes it symmetric, but an asynchronous vault can only work on the side whose amount is fixed at request time. That is assets for deposits and shares for redemptions. The amount of assets corresponding to the requested shares can change until settlement, so the deposit request flow cannot be based on a mint amount and the redeem request flow cannot be based on a withdraw amount. A request cancellation flow is also not included in the standard, because cancellation is often technically difficult and can be either synchronous or asynchronous, so it was judged that it should be standardized in a separate EIP.

Why preview functions are forced to revert

The preview functions have no address parameter, so msg.sender is the only way to distinguish differences in exchange rate. This creates an integration complexity: a supporting contract cannot compute the result of a claim made on behalf of the controller. Also, the only valid next state transition at the claim step is the claim itself, so previewing has no on-chain benefit, and if the caller does not like the result, the calling contract can simply look at the output of that function call and revert. The request functions also do not output assets or shares, because the exchange rate at claim time cannot be known at request time. An event at the moment of transition to Claimable is also not required, because the way the transition happens differs between implementations.

ERC-165 and ERC-7575 support requirements

A contract implementing this standard must implement ERC-165 supportsInterface. Every asynchronous vault must return true for 0xe3bc4e65, which represents the operator methods, and for 0x2f0a18c5, which represents the ERC-7575 interface. An asynchronous deposit vault must return true for 0xce3bbe50, and an asynchronous redeem vault must return true for 0x620ee8e4. Because whether deposits and redemptions are asynchronous is optional, integrators can use this query to identify the vault type and support all cases with a single contract. The ERC-7575 standard, in particular the share method, must also be implemented. The status of this proposal is finalized as Final.

Things to watch out for

Original ERC · ← ERCs