--- eip: 8161 title: Transferable Tokenized Vault Requests description: Extension of ERC-7540 enabling optional transferability of pending deposit and redeem requests author: Cain O'Sullivan (@cosullivan), Jeroen Offerijns (@hieronx) discussions-to: https://ethereum-magicians.org/t/draft-erc-transferable-asynchronous-tokenized-vault-requests/27747 status: Review type: Standards Track category: ERC created: 2025-02-12 requires: 165, 7540 --- ## Abstract This standard extends [ERC-7540](./eip-7540.md) by adding optional transferability of pending deposit and redeem Requests. It introduces two separate interfaces that allow a controller to transfer their pending Request balance to a new controller. Implementations may support either or both interfaces independently. ## Motivation [ERC-7540](./eip-7540.md) asynchronous Requests can remain in the Pending state for an extended period of time. During this period, controllers have no way to transfer their position to another address. This creates friction for users who need to migrate wallets, restructure positions across accounts, or integrate with protocols that compose on top of pending Request positions. By enabling transferability of pending Requests, this standard unlocks secondary market liquidity for pending positions and simplifies account management without requiring cancelation and re-submission of Requests. Transferability is kept optional and split into two separate interfaces so that implementations can choose to support transferable deposit Requests, transferable redeem Requests, both, or neither, depending on their security model and use case. ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174). ### Transferable Deposit Requests Vaults that support transferable deposit Requests MUST implement the `IERC7540DepositTransferable` interface. #### `transferDepositRequest` Transfers the entire pending deposit Request balance from `oldController` to `newController` for the given `requestId`. MUST only transfer the Pending balance. Claimable balances MUST NOT be affected. After a successful transfer, `pendingDepositRequest(requestId, oldController)` MUST decrease by the transferred amount and `pendingDepositRequest(requestId, newController)` MUST increase by the same amount (less any fees). `msg.sender` MUST be `oldController` or an operator approved by `oldController`. MUST emit the `TransferDepositRequest` event. ```yaml - name: transferDepositRequest type: function stateMutability: nonpayable inputs: - name: requestId type: uint256 - name: oldController type: address - name: newController type: address ``` #### `TransferDepositRequest` `from` has transferred their pending deposit Request to `to` for the given `requestId`. MUST be emitted when a pending deposit Request is transferred using the `transferDepositRequest` method. ```yaml - name: TransferDepositRequest type: event inputs: - name: requestId indexed: true type: uint256 - name: from indexed: true type: address - name: to indexed: true type: address ``` ### Transferable Redeem Requests Vaults that support transferable redeem Requests MUST implement the `IERC7540RedeemTransferable` interface. #### `transferRedeemRequest` Transfers the entire pending redeem Request balance from `oldController` to `newController` for the given `requestId`. MUST only transfer the Pending balance. Claimable balances MUST NOT be affected. After a successful transfer, `pendingRedeemRequest(requestId, oldController)` MUST decrease by the transferred amount and `pendingRedeemRequest(requestId, newController)` MUST increase by the same amount (less any fees). `msg.sender` MUST be `oldController` or an operator approved by `oldController`. MUST emit the `TransferRedeemRequest` event. ```yaml - name: transferRedeemRequest type: function stateMutability: nonpayable inputs: - name: requestId type: uint256 - name: oldController type: address - name: newController type: address ``` #### `TransferRedeemRequest` `from` has transferred their pending redeem Request to `to` for the given `requestId`. MUST be emitted when a pending redeem Request is transferred using the `transferRedeemRequest` method. ```yaml - name: TransferRedeemRequest type: event inputs: - name: requestId indexed: true type: uint256 - name: from indexed: true type: address - name: to indexed: true type: address ``` ### [ERC-165](./eip-165.md) Support Smart contracts implementing this standard MUST implement the [ERC-165](./eip-165.md) `supportsInterface` function. Vaults implementing `IERC7540DepositTransferable` MUST return the constant value `true` when `0x53b3bb0a` is passed through the `interfaceID` argument. Vaults implementing `IERC7540RedeemTransferable` MUST return the constant value `true` when `0x7846f5bd` is passed through the `interfaceID` argument. ## Rationale ### Only Transferring Pending Balances This standard deliberately restricts transfers to the Pending state. Claimable balances already have a deterministic exchange rate and can be claimed by the controller at any time; transferring them would add complexity without significant benefit. Limiting scope to Pending balances keeps the interface simple and avoids edge cases around partial claimability. ### Separate Interfaces for Deposit and Redeem Transferability Following the design philosophy of [ERC-7540](./eip-7540.md) where deposit and redemption flows are independently optional, this standard keeps deposit and redeem transferability as separate interfaces. A Vault may have valid reasons to allow transferability of one request type but not the other. For example, a Vault might allow transfer of pending deposit Requests (where assets are locked) but disallow transfer of pending redeem Requests (where shares have already been burned or locked with specific accounting implications). ### Transferring the Full Pending Balance The `transferDepositRequest` and `transferRedeemRequest` methods transfer the entire pending balance rather than accepting a partial amount. This simplifies the interface and aligns with the ERC-7540 model where Requests of the same `requestId` are fungible. ## Backwards Compatibility This standard is fully backward compatible with [ERC-7540](./eip-7540.md). Vaults that do not implement this extension continue to function as before. Integrators can detect support for transferability via [ERC-165](./eip-165.md) `supportsInterface`. ## Security Considerations ### Operator Trust As with ERC-7540, operators approved by a controller can transfer pending Requests on their behalf. Users must be aware that granting operator permissions extends to the ability to transfer pending Requests to arbitrary addresses, effectively moving locked assets or shares out of the controller's control. ### Pricing of Pending Requests Unlike Vault shares, which have `convertToShares` and `convertToAssets` as onchain price references, pending Requests have no built-in pricing mechanism. The exchange rate is unknown until fulfillment. Builders of secondary markets around transferable Requests should account for this lack of a canonical price source when designing pricing and settlement mechanisms. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md).