📄
Contract Details

Glossary

    base asset: refers to the asset that is the quantity of a symbol. For the pair ETH USD, ETH would be the base asset.
    quote asset: refers to the asset that is the price of a symbol. For the pair ETH USD, USD would be the quote asset.

BlackScholes

The BlackScholes smart contract implements mathematical functions related to the computation of option prices using the BlackScholes pricing model. It implements both core mathematical functions (exp, ln, sqrt, stdNormal and stdNormalCDF) as well as functions specific to BlackScholes (d1d2, optionPrices, delta, vega). Beyond that, it also implements a standardised Vega function, as described in the whitepaper (stdVega).

LyraGlobals

The LyraGlobals contract holds onto all modifiable variables for the system. It also retrieves the current spot price and fee rates for a given currency pair from Synthetix.
This contract mixes two different ideas; however this was done in the interest of minimising gas costs from calls between contracts. In a similar vein, a number of globals are grouped together to minimise the number of calls made between contracts.

LiquidityPool

Allows users to deposit quote asset to receive a Liquidity Certificate. This NFT represents a share of the LP. These funds are used both as collateral/premium for the options in OptionMarket and for hedging risk in PoolHedger. This is done in a 2:1 ratio.
Rounds
Funding is done in rounds. Liquidity cannot enter, nor can it be removed, until a round is over. A round is defined by the maxExpiryTimestamp in OptionMarket. No new boards can be added with expiries greater than the maxExpiryTimestamp until all boards have been liquidated. This does not prevent new boards being added that have a shorter expiry however.
Tokens
For accounting reasons, we use a concept of a "TokenPrice" which is the value of liquidity in relation to the rest of the pool. A Token is a share of the entire pool, as such the price of a "token" is:
tokenPrice = poolValueQuote / tokenTotalSupply
As this definition requires pool value/tokens to exist, we set a base price of a token to be 1 unit of quote asset. Thus the tokenPrice is computed recursively based on the previous round value.
LiquidityCertificates
When liquidity is added, we store the amount of liquidity that will be added, along with at what timestamp the liquidity can enter the pool. When the round ends, we store the token value at the time, and by having the entry and exit value of the tokens, we can compute the amount owed the the LPs.
amount owed = liquidity / (entryTokenPrice) * (exitTokenPrice)
As we need to track these variables per bundle of liquidity, we issue an NFT to lender which is their claim to the value. These can be transferred to other users and sold on secondary markets to gain access to the value immediately. Otherwise, the tokens will need to signal they want to leave the market, and will continue to be locked until the round is over.
In the period between rounds, tokens are instantly burnable for their value as well.

LiquidityCertificate

An ERC721 (NFT) that represents the user's share in the LiquidityPool. This is defined by 5 properties:
    id: A unique identifier, integer.
    owner: The user who can use the certificate (there is also an approve flow, but we will ignore that)
    liquidity: The amount of quote the user sent to the pool
    enteredAt: The time when the funds can start earning profit, or face loss.
    burnableAt: The time after which the token value is locked, and cannot be used for providing liquidity. Funds will be burnable after this time.

OptionMarket

The OptionMarket is a collection of boards/listings which a user can trade against. Along side this, it also manages collateral locking/freeing for longs, moving collateral for shorts, board expiry, liquidation, and settling options that finished in the money.
Boards are a collection of listings at a specific expiry. Listings are a combination of strike and expiry. They are created by the owner of the contract. At the time of creation, the baseIV of the board is specified, along with a skew value per listing. These combine to define the volatility value for the option, which is required for the BlackScholes pricing model.
Trading
Traders have both the option to buy a call/put option from the market (a long) or to sell a call/put option to the market (a short). Once the trader has an outstanding position (positive for long, negative for short), they must close their position to take out a position on the opposite side (i.e. close their long to open a short). This applies separately for both calls and puts.
When options are purchased from the market, collateral is locked in the LiquidityPool, and users send the premium to the LiquidityPool. When options are sold to the market, users must lock collateral in the OptionMarket (this contract), and receive the cost from the LiquidityPool. When an option is closed, this is reversed.
When a trader is opening a long, or closing a short; that is considered a buy from the perspective of the user, the contract notes this as isBuy = true. Similarly, when a trader opens a short, or closes a long, isBuy = false.
isBuy denotes which direction the market is moving, and scales the board's iv and the listing's vol in that direction. It also denotes whether a fee is charged on top of the blackScholes option price, or removed from. i.e. if the market is paying for the option, the fee should be removed from the price; to pay less out to the trader, as LPs are the ones making the market.
Board Liquidation and Option Settling
Beyond trading, the OptionMarket is also responsible for the liquidation of assets held by a board, as well as reserving the correct amount of assets required to pay out to all the traders. This means that options are "auto-settling". When the expiry time has passed, the spot price of baseAsset is reserved, and funds are reserved appropriately for all listings. As options are cash settled, this involves holding onto the difference of spotPrice and strike for long options; and liquidating and sending a portion of the collateral from options sold to the market.

OptionMarketPricer

A collection of pricing logic for the OptionMarket. Using values from LyraGlobals, along with pricing returned from OptionGreekCache, determines the cost and fee of the options being purchased. This also provides the methods for adjusting iv/skew in the OptionMarket. It is also responsible for passing the new call/put exposure for a listing through to the OptionGreekCache.

OptionGreekCache

A system for caching greeks for listings and boards that exist in OptionMarket. This is required to help reduce gas costs dramatically for trades occurring at a high frequency. This will also permit partial updates of the system in the case of a large number of boards/listings being present on the system, allowing an external party to update all the greeks separately, before permitting trades to occur.
As greeks are fairly stable the further from expiry an option is, and given the price hasn't moved much, we consider the cache to be out of date using the following formula:
1
uint acceptablePriceMovementPercent = MAX_ACCEPTABLE_PERCENT;
2
3
if (timeToExpirySec < PRICE_SCALING_PERIOD) {
4
acceptablePriceMovementPercent =
5
((MAX_ACCEPTABLE_PERCENT - MIN_ACCEPTABLE_PERCENT) * timeToExpirySec) /
6
PRICE_SCALING_PERIOD + MIN_ACCEPTABLE_PERCENT;
7
}
8
9
acceptablePriceMovement = pastPrice * acceptablePriceMovementPercent
Copied!
This can also work as an indirect mechanism to limit trading in cases of large price swings, as the cache will be out of date more often.
The OptionMarket is the source of truth for which boards make up the netDelta/netStdVega positions, OptionMarket will call addBoard and removeBoard when boards are added or removed.
These net positions are from the perspective of the user, so when used calculating the vega fee component, the value is inverted.

OptionToken

An ERC1155 contract that tokenises user option positions. Each id represents a different combination of listingId and tradeType. Listing IDs start at 1, and go up by 4. TradeType is an enum with the following fields:
1
enum TradeType {LONG_CALL, SHORT_CALL, LONG_PUT, SHORT_PUT}
Copied!
As an example, the id used for a short call on listingId 17 would have an id of (17 + 1) = 18.

ShortCollateral

The ShortCollateral contract holds collateral from users who are selling (shorting) options to the AMM. At the time of liquidation it will send the portion owed to the LPs to the LiquidityPool, and reserve the remainder for users who opened shorts to reclaim. It also contains the logic for settling options.

PoolHedger

This contract assesses the netDelta position of the LiquidityPool/OptionMarket and hedges the risk by purchasing or shorting the base asset, to try bring the market to a delta neutral hedged position. This only leaves the LP exposed to changes in the asset volatility.
PoolHedger.hedgeDelta() is the only exposed mutative function for this contract. It gets the current global netDelta position from the OptionGreekCache, and either purchases/sells eth, or shorts/closes an eth short; using the Synthetix suite of contracts.
If the netDelta of the market is positive, it implies that when the price of the asset moves up $1, the value of the options goes up by that amount. So given the netDelta from the perspective of the users is 500; if eth moves $1, the value the LPs would have to pay out is $500 more, on the flip side, the LPs profit a similar amount if the price of the asset goes down $1. As such, to hedge the risk of the price movement (to instead create market purely on the volatility of the asset) - the LPs should purchase $500 eth.
The opposite is true for the cases where the netDelta is negative. The LPs would want to short the asset to not be exposed to price movements.
One caveat with this approach is that the LP is funded by USD, so when a call option is purchased from the market, enough collateral must be purchased to cover the options purchased. By doing so, the LPs expose themselves to price movements of the asset. As such, these purchases must be hedged by shorting the asset.
In an example:
    One 50 delta eth call is purchased
    1 eth must be purchased
    netDelta is 0.5, but the position of the LP is 1 eth, so (0.5 - 1) -> -0.5
    0.5 eth must be sold to bring the position to delta neutral
    Thus the PoolHedger shorts 0.5 eth
Last modified 1mo ago