AlphaPortfolioValuesFeed.sol

AlphaPortfolioValuesFeed.sol

This feed is responsible for passing in the pool's greek exposure (most importantly delta) and the portfolio's liabilities (or value of options contracts held) to the liquidity pool.

fulfill(address underlying, address strikeAsset) external No Access Control

This function is responsible for doing the calculation for determining the portfolio delta and portfolio valuation. It achieves this by storing all the addresses of series held by the liquidityPool in an addressSet where each address is a key to a mapping that contains details on the option position [option series (with strike in e18) and amount in e18], then looping over all of these and computing the delta and value of each one, then finally summing those to form the portfolio delta and value. The amount incremented is the netExposure (shortExposure - longExposure)

It works by looping through the addressSet then searching the storesForAddress mapping using the address of the loop. It first checks that the series being calculated has expired, if it has expired the fulfill will revert (the revert will also provide the address and index that it reverted at), what this indicates is that the oToken vault needs to be settled or redeemed and then removed from the loop via syncLooper or cleanLooperManually. This is done to prevent any miscalculated values of the pool due to expired options, since valuations are done manually and infrequently, this is reasonable to do. After that the volatility is determined from the VolatilityFeed and the black scholes delta and value of the option of the loop is determined. These values then increment the portfolioValues. Once the loop is complete, the delta and portfolioValues are pushed to storage.

updateStores(Types.OptionSeries _optionSeries, int256 shortExposure, int256 longExposure, address _seriesAddress) Only Accessible by handlers

Update stores is the function that tells the Portfolio values feed any new positions that the liquidity pool has taken on. Then the addressSet is checked for _seriesAddress, if it already exists then just increment the stores of that series by the signedAmount, otherwise add it to the addressSet and store the option details in storesForAddress[_seriesAddress].

An EnumerableSet.AddressSet by OpenZeppelin is used as it is easier to clean and much easier to search through.

Update stores can theoretically be pushed to by any set of contracts, meaning that a buyside products could also be used and could share the same liquidityPool liquidity and be represented by the same portfolio. Long exposure and short exposure are updated seperately and they are ints so that reducing positions is easily done via updateStores.

syncLooper() external Only Accessible by keeper or above

This function is used to clean out the addressSet of expired options, the purpose being to keep the addressSet at the optimal size and to remove any expired options that might disrupt the valuation calculations.

It loops through the addressSet, if it finds any options that have expired then it adds it to another list, after looping through the addressSet. This new list is then looped through and each option is deleted from the addressSet and has its stores cleaned.

WARNING: A current danger of this function is that options that have not been settled but are settlable could be removed from the loop, this could result in incorrect counting of the option values. Thinking through ideas of how to fix this and open to ideas

cleanLooperManually() external Only Accessible by keeper or above

This function is used to clean out the addressSet of expired options, the purpose being to keep the addressSet at the optimal size and to remove any expired options that might disrupt the valuation calculations.

This is a more manual process, it takes an address and an index. It checks the addressSet at that index. It compares it to the address given, if they are the same then it checks if the option has expired, if it has then it removes the option.

WARNING: A current danger of this function is that options that have not been settled but are settlable could be removed from the loop, this could result in incorrect counting of the option values. Thinking through ideas of how to fix this and open to ideas

accountLiquidatedSeries(addressseries) external Only Accessible by keeper or above

This function is used to fix accounting in the stores if a series gets liquidated. This is mostly here to deal with the edge case that a vault does get liquidated. It first checks that the series exists in the stores then it checks that the stores have short exposure, if it does then it will check for the vault id in the option registry, if it exists then we know the liquidity pool had this position. Then in order to match the records of that vault we set the stores to the e18 version of the short amount in that opyn vault, the reason we do not set it to 0 is because partial liquidations are possible. This function would NEED to be called when a liquidation has occured so should be managed by a bot, however it is likely that guardian protocols would have kicked in if a liquidation has occured (protocol has paused).

migrate(_migrateContract) external Only Accessible by Governance

This function is used to migrate all stored options data in one PortfolioValuesFeed to a new contract that has the IPortfolioValuesFeed interface. This is done if an update needs to be made to the PortfolioValuesFeed. (We as a team are not comfortable with using proxy solutions that achieve the same outcome)

Clear migration instructions are provided here:

////////////////////////////////////////////////////////////////////////////////////////////
/**  MIGRATION PROCESS - FOR ALPHA
  *	  1/ On the migrate contract set this contract as a handler via Governance
  *   2/ Make sure the storage of options in this contract is up to date and clean/synced
  *   3/ Call migrate here via Governance 
  *   3i/ If the migration gas gets too big then
  *   4/ Make sure the storage was correctly transferred to the new contract
  *   5/ Properly configure the handlers on the new contract via Governance
  *   6/ Properly configure the keepers on the new contract via Governance
  *   7/ Set the liquidity pool on the new contract via Governance
  *   8/ Change the PortfolioValuesFeed in the Protocol contract via Governance
  */ 
////////////////////////////////////////////////////////////////////////////////////////////

AlphaPortfolioValuesFeed

Options portfolio storage and calculations

OptionStores

struct OptionStores {
  struct Types.OptionSeries optionSeries;
  int256 shortExposure;
  int256 longExposure;
}

oTokenDecimals

uint256 oTokenDecimals

immutable variables ///

storesForAddress

mapping(address => struct AlphaPortfolioValuesFeed.OptionStores) storesForAddress

dynamic variables ///

addressSet

struct EnumerableSet.AddressSet addressSet

portfolioValues

mapping(address => mapping(address => struct Types.PortfolioValues)) portfolioValues

protocol

contract Protocol protocol

govern settable variables ///

liquidityPool

contract ILiquidityPool liquidityPool

handler

mapping(address => bool) handler

netDhvExposure

mapping(bytes32 => int256) netDhvExposure

keeper

mapping(address => bool) keeper

rfr

uint256 rfr

DataFullfilled

event DataFullfilled(address underlying, address strike, int256 delta, int256 gamma, int256 vega, int256 theta, int256 callPutsValue)

events ///

RequestedUpdate

event RequestedUpdate(address _underlying, address _strike)

StoresUpdated

event StoresUpdated(address seriesAddress, int256 shortExposure, int256 longExposure, struct Types.OptionSeries optionSeries)

OptionHasExpiredInStores

error OptionHasExpiredInStores(uint256 index, address seriesAddress)

NoVaultForShortPositions

error NoVaultForShortPositions()

IncorrectSeriesToRemove

error IncorrectSeriesToRemove()

SeriesNotExpired

error SeriesNotExpired()

NoShortPositions

error NoShortPositions()

constructor

constructor(address _authority) public

Executes once when a contract is created to initialize state variables Make sure the protocol is configured after deployment

setLiquidityPool

function setLiquidityPool(address _liquidityPool) external

setters ///

setProtocol

function setProtocol(address _protocol) external

setRFR

function setRFR(uint256 _rfr) external

setKeeper

function setKeeper(address _keeper, bool _auth) external

change the status of a keeper

setHandler

function setHandler(address _handler, bool _auth) external

change the status of a handler

fulfill

function fulfill(address _underlying, address _strikeAsset) external

Fulfills the portfolio delta and portfolio value by doing a for loop over the stores. This is then used to update the portfolio values for external contracts to know what the liquidity pool's value is 1/ Make sure any expired options are settled, otherwise this fulfillment will fail 2/ Once the addressSet is cleared of any

NameTypeDescription

_underlying

address

- response; underlying address

_strikeAsset

address

- response; strike address

updateStores

function updateStores(struct Types.OptionSeries _optionSeries, int256 shortExposure, int256 longExposure, address _seriesAddress) external

Updates the option series stores to be used for portfolio value calculation

callable by the handler and also during migration

NameTypeDescription

_optionSeries

struct Types.OptionSeries

the option series that was created, strike in e18

shortExposure

int256

the amount of short to increment the short exposure by

longExposure

int256

the amount of long to increment the long exposure by

_seriesAddress

address

the address of the series represented by the oToken

addyList

address[] addyList

LOOP CLEANING - FOR ALPHA This is necessary to reduce the size of the foor loop when its not necessary to.

  • Make sure the option has been settled!

syncLooper

function syncLooper() external

function to clean all expired series from the options storage to remove them from the looped array.

FOLLOW THE LOOP CLEANING INSTRUCTIONS ABOVE WHEN CALLING THIS FUNCTION

cleanLooperManually

function cleanLooperManually(address _series) external

function to clean an expired series from the portfolio values feed, this function will make sure the series and index match and will also check if the series has expired before any cleaning happens.

FOLLOW THE LOOP CLEANING INSTRUCTIONS ABOVE WHEN CALLING THIS FUNCTION

NameTypeDescription

_series

address

the series at the index input above

_cleanLooper

function _cleanLooper(address _series) internal

internal function for removing an address from the address set and clearing all option stores for that series

NameTypeDescription

_series

address

the option series address to be cleared

accountLiquidatedSeries

function accountLiquidatedSeries(address _series) external

if a vault has been liquidated we need to account for it, so adjust our short positions to reality

NameTypeDescription

_series

address

the option series address to be cleared

migrate

function migrate(contract IPortfolioValuesFeed _migrateContract) external

migrate all stored options data to a new contract that has the IPortfolioValuesFeed interface

FOLLOW THE MIGRATION PROCESS INSTRUCTIONS WHEN CALLING THIS FUNCTION

NameTypeDescription

_migrateContract

contract IPortfolioValuesFeed

the new portfolio values feed contract to migrate option values too

requestPortfolioData

function requestPortfolioData(address _underlying, address _strike) external returns (bytes32 id)

requests a portfolio data update

getPortfolioValues

function getPortfolioValues(address underlying, address strike) external view returns (struct Types.PortfolioValues)

non-complex getters ///

_isKeeper

function _isKeeper() internal view

keepers, managers or governors can access

_isHandler

function _isHandler() internal view

handlers can access

isAddressInSet

function isAddressInSet(address _a) external view returns (bool)

get the address set details

addressAtIndexInSet

function addressAtIndexInSet(uint256 _i) external view returns (address)

addressSetLength

function addressSetLength() external view returns (uint256)

getAddressSet

function getAddressSet() external view returns (address[])

_getVolatilityFeed

function _getVolatilityFeed() internal view returns (contract VolatilityFeed)

get the volatility feed used by the liquidity pool

NameTypeDescription

[0]

contract VolatilityFeed

the volatility feed contract interface

_getOptionRegistry

function _getOptionRegistry() internal view returns (contract IOptionRegistry)

get the option registry used for storing and managing the options

NameTypeDescription

[0]

contract IOptionRegistry

the option registry contract

_getUnderlyingPrice

function _getUnderlyingPrice(address underlying, address _strikeAsset) internal view returns (uint256)

get the underlying price with just the underlying asset and strike asset

NameTypeDescription

underlying

address

the asset that is used as the reference asset

_strikeAsset

address

the asset that the underlying value is denominated in

NameTypeDescription

[0]

uint256

the underlying price

Last updated