Architecture
Overview
Stream vaults are vaults composed as a solidity contract that follow a round-by-round model. Every week, the vault round gets rolled over by a specialized role called the vault keeper. Ownership over the vault is represented by an underlying ERC20 as "shares". Each vault has a specific underlying ERC20 which represents the token that deposits are accepted in. Additionally, the vaults allow for asynchronous withdraw through an initiate-confirm withdraw process. Finally the vaults also allow for self-custody of share tokens rather than sitting in the smart contract enabling composability of vault ownership represenatationship.
Vault Deposit Flow
- User deposits 1000 USDC into LevUSDC Vault in round n through
deposit()
ordepositFor()
- The contract creates an entry in
depositReceipt.amount
for 1000 USDC and updatesvaultState.totalPending
- Vault Keeper rolls the contract through
rollToNextRound()
to advance the round to n+1 - Upon rolling the 1000 USDC is transfered to the Vault Keeper and corresponding shares are minted
- The 1000 USDC is utilized in the active DMM strategy
Vault Withdraw Flow
Stream Vaults allow for two types of withdraws: asynchronous withdraws and same-round-withdraws (instant withdraws)
Instant Withdraws
Instant withdraws are only available when a user withdraws tokens in the same round they were deposited. These withdraws are fulfilled instantly as their tokens have not yet been deposited in the DMM strategy, but rather are still in a pending state in the smart contracts.
- User deposits 1000 USDC into LevUSDC Vault in round n through
deposit()
ordepositFor()
- The contract creates an entry in
depositReceipt.amount
for 1000 USDC - User changes their mind on size and withdraws 500 USDC through
instantWithdraw()
- User receives 500 USDC and updates
depositReceipt.amount
to be the remaining 500 USDC
Asynchronous Withdraws
Asynchronous withdraws occur when a user deposited in a previous round, has their funds operating in the DMM strategy, and now want to make a request to withdraw their funds. In this scenario a request is made and only fulfilled at the time of the next round rollover. This means a user can wait -- in the worst case -- a week long to receive their deposited funds + yield through a secondary call to the vault's contracts after the rollover.
- User deposits 1000 USDC into LevUSDC Vault in round n through
deposit()
ordepositFor()
- The contract creates an entry in
depositReceipt.amount
for 1000 USDC - Vault Keeper rolls the contract through
rollToNextRound()
to advance the round to n+1 - Upon rolling the 1000 USDC is transfered to the Vault Keeper
- The 1000 USDC is utilized in the active DMM strategy
- User decides to withdraw funds and creates a call to
initiateWithdraw()
for 1000 USDC in round n+1 - A
withdrawReceipt
is created for the amount of shares 1000 USDC in round n accounts for -- say 10 shares -- while updatingcurrentQueuedWithdrawShares
accordingly - Vault Keeper rolls over round to n+2 and deposits (1000 + captured yield) USDC to fulfill 10 shares (calculated when rolling over round)
- In round n+2 the user makes a call to
completeWithdraw()
and the contract sends 1000 USDC + yield to the user currentQueuedWithdrawShares
andwithdrawReceipt
is updated to maintain proper state while burned 10 shares
Redemption Flow
After a user deposit is processed and utilized in the DMM strategy, the user has the ability to either have the vault custody their shares or withdraw/hold their shares themselves.
- User deposits 1000 USDC into LevUSDC Vault in round n through
deposit()
ordepositFor()
- The contract creates an entry in
depositReceipt.amount
for 1000 USDC - Vault Keeper rolls the contract through
rollToNextRound()
to advance the round to n+1 - Upon rolling the 1000 USDC is transfered to the Vault Keeper
- The 1000 USDC is utilized in the active DMM strategy
- User wants to hold their shares and call
redeem()
ormaxRedeem()
- User receives vault shares ERC20 and
depositReceipt.amount
is set to 0 while settingdepositReceipt.unredeemedShares
to the amount of shares withdrawn
When a user decides to withdraw funds after holding their own shares, they don't need to approve the vault token to send shares to the vault in order to be burned. The vault and only the vault can transfer without traditional approval permission