Premia Finance - Smart Contract Audit Report

Summary

 PremiaFinance Audit Report Premia Finance is a Decentralized Financial Instrument Protocol. Premia delivers Financial Instruments as a Service to Users, in which the use of the Premia Token is incentivized through various methods. Premia Finance is building an options trading platform using a new and innovative technique for upgradability known as the EIP-2535 Diamond standard.

We reviewed Premia Finance's contracts at commit e0b4bf582630921b8ca1edcbc03e6a440bc65907 on the team's private GitHub.

We previously reviewed the project team's Phase 1 effort here.

Notes on Individual Contracts:
Premia contract:
  • The Premia contract establishes the deployer of the contract as the owner of the platform, which extends to all subsequent contracts.
  • The Premia contract is a gas-optimized implementation of the EIP-2535 Diamond standard.
  • The Premia platform uses the Diamond standard in order to promote upgradability for segmented portions of their platform's implementation logic.
  • The Diamond standard allows the Premia platform to include various "facets", or implementation contracts, which define different parts of the functionality used within the platform.
  • These "facets" can be removed or replaced, and any new "facets" can be added by the project team at any time.
  • The Premia implementation of the Diamond standard allows the team to retain any and all existing storage data while swapping out and upgrading their implementation code.
  • The team has included the proper checks to ensure that contracts that are added as "facets" are not empty and do contain code.
ProxyManager contract:
  • The project team can use the ProxyManager contract to deploy option pools for a base and underlying asset.
  • There can only be one pool for each base and underlying asset pair.
  • The base and underlying asset minimums as well as the prices of each are set by the project team on deployment of each pool.
  • The team must exercise caution when deploying option pools to avoid ERC777-compliant tokens (this is uncommon).
PoolWrite contract:
  • Anyone can use the PoolWrite contract to purchase a call or put option.
  • Users can even provide ETH or any token of their choice, which will be swapped for the appropriate asset and deposited appropriately.
  • The user must specify a maturity date in seconds between 1 and 90 days in the future and ensure the maturity date is the first second of the day in UTC time.
  • The user must specify a strike price that is between 0.8x and 2x the spot price for calls, and between 0.5x and 1.2x the spot price for puts.
  • The user must specify the contract size in terms of the amount of the underlying asset and the maximum acceptable cost the user is willing to spend after accounting for slippage.
  • The contract size must be at least the minimum and no more than the available supply of Free Liquidity tokens.
  • The base cost of the option contract is calculated using the Premia Finance model, which is based on the popularly used Black-Scholes model with some added enhancements.
  • A percentage of the base cost is added on as a fee; some addresses may be eligible for a fee discount.
  • The user will receive an amount of Long Option tokens equal to the desired contract size specified.
  • An equivalent amount of Free Liquidity tokens is burned from underwriters (liquidity providers) and exchanged with Short Option tokens.
  • The fee cost is minted to the fee receiver address as Reserved Liquidity tokens.
  • The total cost is transferred from the user to the contract address in the appropriate Pool asset; users may pay all or part in ETH if the Pool asset is WETH.
  • A user can also choose to write an option without using liquidity from the Pool, on behalf of the user or another specified receiver.
  • The user can specify an address as the underwriter as long as the proper approvals are in place; otherwise the user will be considered the underwriter.
  • The price in this case is based on the contract size and will be transferred from the specifed underwriter to the contract address.
  • The Long Option tokens are minted to the specified receiver, and the Short Option tokens are minted to the specified underwriter.
PoolExercise contract:
  • Anyone can use the PoolExercise contract to exercise their call or put option contract as long as it has not expired.
  • Users can exercise option contracts on behalf of other holders as long as the proper approvals are in place and it has not expired.
  • The option contract must be "in the money" in order to be exercised, meaning the strike price has surpassed the current price; otherwise the option has no exercise value.
  • A portion of the exercise value is transferred to the fee receiver address in Reserved Liquidity tokens as a fee.
  • The remaining exercise value is transferred to the holder in the Pool asset, and the holder's Long Option tokens are burned.
  • The Short Option tokens are burned from the underwriters and replaced with either Free Liquidity tokens or Reserved Liquidity tokens, depending on the underwriter's reinvestment status.
  • A portion of the underwriter's Free or Reserved Liquidity tokens received are taken as a fee and transferred to the fee receiver address.
  • Anyone can process any expired option contract in order to free liquidity and distribute profits.
PoolIO contract:
  • Anyone can use the PoolIO contract to deposit the underlying or base asset into the Pool to provide liquidity and underwrite call or put options as long as the user's divestment timestamp is at least 1 day in the future at the time of deposit.
  • Users can even provide ETH or any token of their choice, which will be swapped for the appropriate asset and deposited appropriately.
  • A user can set their divestment timestamp to any value at least 1 day in the future at any time.
  • The divestment timestamp will determine the underwriter's reinvestment status, which decides if they will recieve Free or Reserved Liquidity tokens when options they are providing liquidity for are exercised.
  • The user's deposited amount is staked in the PremiaMining contract where users will earn rewards on the deposited amount.
  • Deposited funds are locked for 1 day.
  • When deposited funds are unlocked, the user may withdraw those funds and will burn an equivalent amount of Reserved Liquidity tokens supplemented by Free Liquidity tokens if needed.
  • A user can use the PoolIO contract to reassign the short position to a new underwriter.
  • If the price has decreased, the difference will be transferred to the user in the appropriate Pool asset token.
  • Anyone can annihilate an option contract in which the user is holding both the long and short positions; the Long Option tokens and Short Option tokens will be burned and the equivalent amount of Pool asset tokens are transferred from the contract to the user.
  • Anyone can transfer the fees that have accumulated in the Pool to the fee receiver address at any time.
  • Anyone can use the PoolIO contract to claim their rewards and update the call and put pools in the PremiaMining staking contract.
PremiaMining contract:
  • The project team can add any staking pool at any time; staking pools are added automatically when option pools are deployed.
  • Pools can only be updated via calls from the PoolIO contract, which will recalculate pending rewards; pending rewards are minimized to the amount of Premia tokens available in the contract.
  • Pools can only be allocated to via calls from the PoolIO contract, which will recalculate the user's reward amount based on the new total the user has staked.
  • Rewards from pools can only be claimed via calls from the PoolIO contract, which will recalculate the pending rewards, and transfer to the user the reward amount (up to the Premia balance available in the contract).
  • The project team can use the PremiaMiningProxy to set the PremiaMining implementation contract address at any time.
  • The owner must transfer Premia tokens to the contract address in order to fund rewards, and can do so at any time.
  • The owner can set the reward rate to any value at any time.
  • The owner can set the allocation points of any existing pool to any value at any time.
Volatility Surface Oracle contract:
  • The Volatility Surface Oracle contract is used to calculate the annualized volatility for an option, and calculate the Black-Scholes price using that volatility value.
  • Any whitelisted user is able to add volatility surfaces at any time.
  • The owner is able to add or remove any address from the whitelist at any time.
General notes across all contracts:
  • Excellent structuring of logic to prevent reentrancy attacks.
  • The contract uses the ERC1155 Multi-Token Standard to represent option contracts as well as a user's share of liquidity.
  • The contract uses the Chainlink AggregatorV3 Oracle to fetch the most up-to-date price data; This is tamper-resistant and considered the industry standard.
  • The contracts utilize 64x64 fixed point number representation for arithmetic operations, which promotes gas efficiency in calculations, but sacrifies range and precision that the standard floating point number representation offers.
  • The project team has included fine-tuned logic to avoid blocks of code where it is appropriate, and optimize gas usage even further.
  • The contracts are implemented with Solidity v0.8.x, and thus are protected from overflows.

Audit Findings Summary:
  • No security issues from outside attackers were identified.
  • Investing requires placing trust in the project team as they have substantial power in the ecosystem. The team can upgrade many of the platform's contracts and update other critical variables.
  • Date: August 16th, 2021.
  • Updated: September 10th, 2021 to review new volitility calculations, restructuring of logic to support gas optimization, and swap functionality in order to support the use of many different tokens within the platform.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APass
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

Contract Source Summary and Visualizations

Name

Address/Source Code

Visualized
(Hover-Zoom Recommended)

Premia

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

ProxyManager

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

PoolWrite

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

PoolExercise

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

PoolIO

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

PoolView

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

PremiaMiningProxy

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

PremiaMining

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

VolatilitySurfaceOracle

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.