Skip to content

Instantly share code, notes, and snippets.

@alexisgauba
Created June 25, 2021 18:53
Show Gist options
  • Save alexisgauba/cf055f521bcfded018116f3f37074f67 to your computer and use it in GitHub Desktop.
Save alexisgauba/cf055f521bcfded018116f3f37074f67 to your computer and use it in GitHub Desktop.
Vesting Call Options

Vesting Call Options

The following instructions go step-by-step through how to create vesting call options, similar to equity options that startups typically use to incentivize employees.

H/t @Fubuloubu, who approached us about creating these for the Yearn team to potentially use! This allows Yearn or similar projects (on-chain DAOs) to grant vesting options to any contributor.

We'll use YFI call options as an example.

Deploy the call options

  • Call createOptionsContract from the OptionFactory via Etherscan
    • To create a $0.50 YFI call option, parameters as follows:
      • collateralType: 0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e (YFI)
      • collateralExp: -18
      • underlyingType: 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 (USDC)
      • underlyingExp: -6
      • oTokenExchangeExp: -6
      • strikePrice: 2000000 (2)
      • strikeExp: -6
      • strikeAsset: 0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e (YFI)
      • expiry: 1685545200 (5/31/23 8:00AM UTC)
      • windowSize: 1685545200 (5/31/23 8:00AM UTC)
  • Note that each oToken has a multiplier for calls. So in this case 0.5 oTokens = 1 call option.
  • See below for a detailed explanation of the parameters

Mint the call options

  • Find the address of options contract you just created by going to the event logs of your createOptionsContract transaction and grabbing the address from the second event, which is the OptionsContractCreated event
  • Approve YFI collateral to the oToken
  • Go to the options contract you created and call createERC20CollateralOption via Etherscan, parameters as follows:
    • amtToCreate: 2000000
      • Amount of oTokens to create, here 2 oTokens
    • amtCollateral: 1000000000000000000
      • Amount of YFI to use as collateral, here 1 YFI
    • receiver: 0x…
      • Address to receive the oTokens you created

Send the call options to the vesting contract

Exercise upon vest

  • In order to exercise, you will need to send oTokens and USDC to the options contract and in return you will receive YFI. Continuing with our same example parameters, to exercise 2 call options, you would send 1 oToken and 1 USDC and receive 2 YFI.
  • Approve USDC to the oToken
  • Make sure you have enough USDC otherwise txn will revert eg. 1000000 USDC for 1000000 oToken including decimals
  • Go to the options contract address and call exercise via Etherscan, parameters as follows:
    • oTokensToExercise: 1000000
      • 1 oToken
    • vaultsToExerciseFrom: [“0x….”, “0x….”]
      • Insert the address or addresses of vault holders to exercise from
      • You should provide these addresses to contributors when they are exercising. These addresses should be the EOAs or smart contracts you used to mint oTokens

Redeem after exercise

  • If someone exercises before expiry, you can go to the options contract address and redeem the underlying by calling removeUnderlying via Etherscan, just by clicking “write” and confirming txn.
  • To redeem your remaining vault balance after expiry, you can go to the options contract address call redeemVaultBalance via Etherscan, just by clicking “write” and confirming txn.

Parameters explained:

Calls are inverse puts

  • In Opyn v1, call options are inverse puts. For example, a YFI-USDC put would have YFI as underlying and USDC as collateral. To create a call option we simply have YFI as collateral and USDC as underlying.
  • This means that each oToken has a multiplier, where strikePrice oTokens = 1 call option. For example, for a $100,000 YFI Call, 100,000 oTokens = 1 call option.

Collateral type & collateral exp

  • This would be YFI, which has 18 decimals, thus collateralExp = -18

Underlying type & underlying exp

  • Since calls are inverse puts, this would be USDC, which has 6 decimals, thus underlyingExp = -6

oTokenExchange exponent

  • The oToken exchange exponent refers to the smallest unit of underlying we can have an option on. In every above example, because USDC has 6 decimals we are limited by 6, so the oTokenExchangeExp = -6.

Strike Price

  • Example 1: Since calls are inverse puts, to get the strike price, you must invert your desired strike. For example for a $0.50 strike price, I am getting 0.50 USDC for every 1 YFI I have a call option on. Inverting this, such that my option is denominated in 1 unit of underlying (in this case the underlying is USDC), for every 1 USDC, I get 2 YFI. Thus my strike price is 2.
  • Example 2: Let’s take another example where I want a $32 strike YFI call option. Here I am getting 1 YFI for 32 USDC, so inverting this to get in terms of 1 USDC, I am getting 1/32 YFI for 1 USDC. 1/32 = 0.03125. To represent this as a nicer strike price, I can use 3125 and adjust the strike exponent (discussed in the next section).
  • Note that we advise not using strikes where inverting gives repeating decimals as this results in calculations being off by small amounts

Strike exponent

  • The strike exponent is the number of decimals of the strike price. We’ll expand on the same examples from above to explain.
  • Example 1: We are getting 2 YFI for every 1 USDC. Because USDC has 6 decimals, that is the max precision we can support. So here expanding out to include decimals, we get 2 * (10^-6) YFI for every 1 * (10^-6) USDC. The exponent of our strike price, 2, is -6, which is our strike exponent.
  • Example 2: Here we are getting 0.03125 YFI for every 1 USDC. Expanding to include decimals, we get 0.03125 * (10^-6) YFI for every 1 * (10^-6) USDC. We can express this as a nicer strike price by using 3125 * (10^-11) YFI for every 1 * (10^-6) USDC. The exponent of our strike price 3125, is -11, which is our strike exponent.

Strike Asset

  • This would be YFI, which has 18 decimals

Expiry

  • UTC unix time you’d like the option to expire

windowSize

  • If you’d like to create a European option you can set an exercise window using this parameter by setting it to the UTC unix time of when people can start exercising before expiry.
  • If you’d like to create an American option (anyone can exercise at anytime), simply set the windowSize to the same UTC unix time as expiry.

Creating safe oTokens

  • In order to create safe oTokens by preventing overflows, your oTokens must satisfy the below conditions
    • abs(oTokenExchangeExp - underlyingExp) < 19
    • max(abs(strikeExp + liqIncentiveExp - collateralExp), abs(strikeExp - collateralExp)) <= 9
      • LiqIncentiveExp should be 0 here. This is only used if you are using parameters that require liquidations eg. ETH collateralized puts on cDAI
    • You can make a copy of this spreadsheet and use it to check these safety conditions.

Feel free to reach out on discord to cross check parameters or for any other help + questions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment