Tokenized Vaults with Lock-in Period
相关视频
正文
Abstract
This standard extends EIP-4626 to support lock-in periods.
Motivation
The EIP-4626 standard defines a tokenized vault allowing users (contracts or EOAs) to deposit and withdraw underlying tokens at any time. However, there exist cases where the vault needs to lock the underlying tokens (perhaps to execute certain strategies). During the lock-in period, neither withdrawals nor deposits should be allowed. This standard extends the EIP-4626 to support lock-in periods and handle scheduled deposits and withdrawals during them.
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 and RFC 8174.
All vaults that follow this EIP MUST implement EIP-4626 to provide basic vault functions and EIP-20 to represent shares.
Definitions
- asset: The underlying EIP-20 token that the vault accepts and manages.
- share: The EIP-20 token that the vault issued.
- locked: A status of the vault. When the vault is locked, user can’t withdraw or deposit assets from the vault.
- unlocked: A status of the vault. When the vault is unlocked, user can withdraw or deposit assets from the vault.
- round: The period that the vault is locked.
View Methods
isLocked
The current state of the vault.
true
represents a vault is in the locked state, and false
represents a vault is in the unlocked state.
- name: isLocked type: bool stateMutability: view inputs: [] outputs: - name: isLocked type: bool
vaultRound
The current round of the vault.
MUST start with 0
.
MUST add 1
each time a new round starts, that is, when the isLocked
becomes true. MUST NOT be modified in any other circumstances.
- name: vaultRound type: uint256 stateMutability: view inputs: [] outputs: - name: vaultRound type: uint256
Methods
scheduleDeposit
Schedule the intent to deposit assets
when the isLocked
is true.
MUST only be callable when the isLocked
is true.
MUST transfer the assets
from the caller to the vault. MUST not issue new shares.
MUST revert if assets
cannot be deposited.
MUST revert if the isLocked
is false.
- name: scheduleDeposit type: function stateMutability: nonpayable inputs: - name: assets type: uint256
scheduleRedeem
Schedule the intent to redeem shares
from the vault when the isLocked
is true.
MUST only be callable when the isLocked
is true.
MUST transfer the shares
from the caller to the vault. MUST not transfer assets to caller.
MUST revert if shares
cannot be redeemed.
MUST revert if the isLocked
is false.
- name: scheduleRedeem type: function stateMutability: nonpayable inputs: - name: shares type: uint256
settleDeposits
Process all scheduled deposits for depositor
and minting newShares
.
MUST only be callable when the isLocked
is false.
MUST issue newShares
according to the current share price for the scheduled depositor
.
MUST revert if there is no scheduled deposit for depositor
.
- name: settleDeposits type: function stateMutability: nonpayable inputs: - name: depositor - type: address outputs: - name: newShares - type: uint256
settleRedemptions
Process all scheduled redemptions for redeemer
by burning burnShares
and transferring redeemAssets
to the redeemer
.
MUST only be callable when the isLocked
is false.
MUST burn the burnShares
and transfer redeemAssets
back to the redeemer
according to the current share price.
MUST revert if no scheduled redemption for redeemer
.
- name: settleRedemptions type: function stateMutability: nonpayable inputs: - name: redeemer - type: address outputs: - name: burnShares - type: uint256 - name: redeemAssets - type: uint256
getScheduledDeposits
Get the totalAssets
of scheduled deposits for depositor
.
MUST NOT revert.
- name: getScheduledDeposits type: function stateMutability: view inputs: - name: depositor - type: address outputs: - name: totalAssets - type: uint256
getScheduledRedemptions
Get the totalShares
of scheduled redemptions for redeemer
.
MUST NOT revert.
- name: getScheduledRedemptions type: function stateMutability: view inputs: - name: redeemer - type: address outputs: - name: totalShares - type: uint256
Events
ScheduleDeposit
sender
schedules a deposit with assets
in this round
.
MUST be emitted via scheduleDeposit
method.
- name: ScheduleDeposit type: event inputs: - name: sender indexed: true type: address - name: assets indexed: false type: uint256 - name: round indexed: false type: uint256
ScheduleRedeem
sender
schedules a redemption with shares
in this round
.
MUST be emitted via scheduleRedeem
method.
- name: ScheduleRedeem type: event inputs: - name: sender indexed: true type: address - name: shares indexed: false type: uint256 - name: round indexed: false type: uint2
SettleDeposits
Settle scheduled deposits for depositor
in this round
. Issue newShares
and transfer them to the depositor
.
MUST be emitted via settleDeposits
method.
- name: SettleDeposits type: event inputs: - name: depositor indexed: true type: address - name: newShares type: uint256 - name: round type: uint256
SettleRedemptions
Settle scheduled redemptions for redeemer
in this round
. Burn burnShares
and transfer redeemAssets
back to the redeemer
.
MUST be emitted via settleRedemptions
method.
- name: SettleRedemptions type: event inputs: - name: redeemer indexed: true type: address - name: burnShares type: uint256 - name: redeemAssets type: uint256 - name: round type: uint256
Rationale
The standard is designed to be a minimal interface. Details such as the start and end of a lock-in period, and how the underlying tokens are being used during the lock-in period are not specified.
There is no function for scheduling a withdrawal, since during the lock-in period, the share price is undetermined, so it is impossible to determine how many underlying tokens can be withdrawn.
Backwards Compatibility
The deposit
, mint
, withdraw
, redeem
methods for EIP-4626 should revert when the isLocked
is true to prevent issuing or burning shares with an undefined share price.
Security Considerations
Implementors need to be aware of unsettled scheduled deposits and redemptions. If a user has scheduled a deposit or redemption but does not settle when the isLocked
is false, and then settles it after several rounds, the vault will process it with an incorrect share price. We didn’t specify the solution in the standard since there are many possible ways to solve this issue and we think implementors should decide the solution according to their use cases. For example:
- Not allow the
isLocked
to become true if there is any unsettled scheduled deposit or redemption - Force settling the scheduled deposits or redemptions when the
isLocked
becomes true - Memorize the ending share price for each round and let the users settle according to the share prices
Copyright
Copyright and related rights waived via CC0.