Ribbon V2
Ribbon v2 is the next version for Ribbon’s Theta Vault product. It brings several major improvements to the vault and makes the vault operations decentralized.

V2 changes include

  1. 1.
    Decentralization of Theta Vault operations
  2. 2.
    Improved capital efficiency
  3. 3.
    No more withdrawal fees
  4. 4.
    Meta-Vault strategies

Architecture

  1. 1.
    User deposits 100 ETH into Theta Vault (ETH call).
  2. 2.
    On Friday 10am UTC, the vault uses 100% of its funds to mint 100 otokens, which are ERC20 representations of options contracts. The 100 ETH is locked for a week in Opyn.
  3. 3.
    After receiving the 100 otokens, the vault puts it up for auction.
    1. 1.
      Anyone can participate and bid on the otokens. They pay the premiums for the otoken in ETH.
    2. 2.
      At the end of the auction, the vault collects 1 ETH in premiums in the form of ETH.
    3. 3.
      Any remaining otokens that are not bought are burned, redeeming 1 otoken for 1 unit of collateral from Opyn.
  4. 4.
    On the next Friday 10am UTC,
    1. 1.
      If the options expire in the money, the vault withdraws less than 100 ETH from Opyn.
    2. 2.
      If the options expire out the money, the vault withdraws exactly 100 ETH.
  5. 5.
    Let's say it expires out the money. The vault repeats step 2 with 101 ETH (original 100 ETH + 1 ETH premium).

Architecture / Codebase Walkthrough

Name
Description
Contains all data structures shared across all vault types
Contains all logic related to how the Vault functions on a weekly basis
Contains all common logic like accounting and options rolling shared across RibbonThetaVault and RibbonDeltaVault.
Theta Vault contract that creates short options position with Opyn on a weekly basis
Periphery contract used to calculate the best strike price for the Theta Vault to choose for the week, given a few parameters

Deposit Flow

Deposit Flow
  1. 1.
    The user deposits 1 ETH into TV.
  2. 2.
    We first check if they have an existing DepositReceipt from the past round. Using the round and amount, we update the unredeemedShares field. This essentially tracks how many shares the user owns, but has not yet redeemed.
1
struct DepositReceipt {
2
round
3
amount
4
unredeemedShares
5
}
Copied!
  1. 1.
    We create the DepositReceipt with the new details.
  2. 2.
    At rollToNextOption, the vault will mint all the shares that are owed to users to address(this). This increments the vaultState.round.
  3. 3.
    Since the round is concluded, the user's vault shares should show up by calling RibbonVault.shares(account)
The end result:
  • Their shares show up automatically once the round concludes.
  • DepositReceipts are used to track all the user's unredeemed shares. This is used for withdrawals and redemptions in the future.

Withdrawal Flow

The withdrawal flow is slightly more involved. We have two types of withdrawals - Standard and Instant withdrawals.
Standard withdrawals
  • Withdrawals are created with the initiateWithdraw function, which queues the shares to be burned.
  • Withdrawals are completed with completeWithdraw function, which burns the shares, and returns the assets.
  • Users can only call completeWithdraw only AFTER the week's Friday 10am UTC. For example, the user calls initiateWithdraw on Wednesday. They can only complete the withdrawal after the same week's Friday 10am UTC.
  • Withdrawals stack on top of each other. This means that if I do initiateWithdraw(10), and I do initiateWithdraw(20) again, I will have a total withdrawal of 30 shares by Friday.
Initiate Withdraw Flow
Complete Withdraw Flow
Instant withdrawals
  • Instant withdrawals are only accessible to funds that are deposited mid-week.
  • For example, user deposits 10 ETH into TV on Wednesday. They can call withdrawInstantly to return up to 10 ETH, from Wednesday till Friday.

Share Redemption Flow

Share redemption is a "pro" feature catered to power-users and protocols that want to integrate with Ribbon.
As mentioned before, when the user deposits into the vault, the vault mints and holds custody of the user's shares on address(this). This is not ideal for protocols or Meta-Vaults that want to hold custody of their shares. By calling the redeem or maxRedeem function, contracts are able to take custody of their vault shares.
The share redemption flow is also triggered implicitly when users call initiateWithdraw.
Share Redemption Flow

Access Control

Name
Privileges
Owner
The owner can set key parameters of the vault such as feeRecipient, performanceFee, managementFee, deposit cap etc.
Some functions in the vault's lifecycle is only limited to the owner, such as commitAndClose and rollToNextOption.
Admin
The admin can upgrade the proxy's implementation address.
Both of these privileged roles use a Gnosis Safe multisig wallet.