Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: StakedaoEcrvPricer #441

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@
* pricers
* [ChainlinkPricer](docs/contracts-documentation/pricers/ChainlinkPricer.md)
* [CompoundPricer](docs/contracts-documentation/pricers/CompoundPricer.md)
* [StakedaoEcrvPricer](docs/contracts-documentation/pricers/StakedaoEcrvPricer.md)
* [YearnPricer](docs/contracts-documentation/pricers/YearnPricer.md)
16 changes: 16 additions & 0 deletions contracts/interfaces/ICurve.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;

interface ICurve {
function add_liquidity(uint256[2] memory amounts, uint256 minAmount) external payable returns (uint256);

function remove_liquidity_one_coin(
uint256 _token_amount,
int128 i,
uint256 _minAmount
) external returns (uint256);
aparnakr marked this conversation as resolved.
Show resolved Hide resolved

function get_virtual_price() external view returns (uint256);
}
26 changes: 26 additions & 0 deletions contracts/interfaces/IStakeDao.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT

import {ERC20Interface} from "./ERC20Interface.sol";

pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
aparnakr marked this conversation as resolved.
Show resolved Hide resolved

interface IStakeDao {
function depositAll() external;

function deposit(uint256 amount) external;

function withdrawAll() external;

function withdraw(uint256 _shares) external;

function token() external returns (ERC20Interface);

function balanceOf(address account) external view returns (uint256);

function approve(address spender, uint256 amount) external returns (bool);

function transfer(address recipient, uint256 amount) external returns (bool);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This contract is also from the StakeDao templates. I don't think it's a good idea to have a different contract here than what's in the stakedao-master branch in the perp vault templates repo.


function getPricePerFullShare() external view returns (uint256);
}
104 changes: 104 additions & 0 deletions contracts/pricers/StakedaoEcrvPricer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.6.10;

import {ERC20Interface} from "../interfaces/ERC20Interface.sol";
import {ICurve} from "../interfaces/ICurve.sol";
import {IStakeDao} from "../interfaces/IStakeDao.sol";
import {OracleInterface} from "../interfaces/OracleInterface.sol";
import {SafeMath} from "../packages/oz/SafeMath.sol";

/**
* Error Codes
* P1: cannot deploy pricer, lpToken address cannot be 0
* P2: cannot deploy pricer, underlying address cannot be 0
* P3: cannot deploy pricer, oracle address cannot be 0
* P4: cannot deploy pricer, curve address cannot be 0
* P5: cannot retrieve price, underlying price is 0
* P6: cannot set expiry price in oracle, underlying price is 0 and has not been set
* P7: cannot retrieve historical prices, getHistoricalPrice has been deprecated
*/

/**
* @title StakedaoEcrvPricer
* @author Opyn Team
* @notice A Pricer contract for a Stakedao lpToken
*/
contract StakedaoEcrvPricer {
using SafeMath for uint256;

/// @notice curve pool
ICurve public curve;

/// @notice underlying asset for this lpToken
ERC20Interface public underlying;
CruzMolina marked this conversation as resolved.
Show resolved Hide resolved

/// @notice opyn oracle address
OracleInterface public oracle;

/// @notice lpToken that this pricer will a get price for
IStakeDao public lpToken;

/**
* @param _lpToken lpToken asset
* @param _underlying underlying asset for this lpToken
* @param _oracle Opyn Oracle contract address
* @param _curve curve pool contract address
*/
constructor(
address _lpToken,
address _underlying,
address _oracle,
address _curve
) public {
require(_lpToken != address(0), "P1");
require(_underlying != address(0), "P2");
require(_oracle != address(0), "P3");
require(_curve != address(0), "P4");

lpToken = IStakeDao(_lpToken);
underlying = ERC20Interface(_underlying);
oracle = OracleInterface(_oracle);
curve = ICurve(_curve);
}

/**
* @notice get the live price for the asset
* @dev overrides the getPrice function in OpynPricerInterface
* @return price of 1e8 lpToken in USD, scaled by 1e8
*/
function getPrice() external view returns (uint256) {
uint256 underlyingPrice = oracle.getPrice(address(underlying));
require(underlyingPrice > 0, "P5");
return _underlyingPriceToYtokenPrice(underlyingPrice);
}

/**
* @notice set the expiry price in the oracle
* @dev requires that the underlying price has been set before setting a lpToken price
* @param _expiryTimestamp expiry to set a price for
*/
function setExpiryPriceInOracle(uint256 _expiryTimestamp) external {
(uint256 underlyingPriceExpiry, ) = oracle.getExpiryPrice(address(underlying), _expiryTimestamp);
require(underlyingPriceExpiry > 0, "P6");
uint256 lpTokenPrice = _underlyingPriceToYtokenPrice(underlyingPriceExpiry);
oracle.setExpiryPrice(address(lpToken), _expiryTimestamp, lpTokenPrice);
}

/**
* @dev convert underlying price to lpToken price with the lpToken to underlying exchange rate
* @param _underlyingPrice price of 1 underlying token (ie 1e6 USDC, 1e18 WETH) in USD, scaled by 1e8
* @return price of 1e8 lpToken in USD, scaled by 1e8
*/
function _underlyingPriceToYtokenPrice(uint256 _underlyingPrice) private view returns (uint256) {
uint256 pricePerShare = lpToken.getPricePerFullShare();
uint8 underlyingDecimals = 18;
uint256 curvePrice = curve.get_virtual_price();

return pricePerShare.mul(_underlyingPrice).mul(curvePrice).div(10**uint256(2 * underlyingDecimals));
CruzMolina marked this conversation as resolved.
Show resolved Hide resolved
}

function getHistoricalPrice(uint80) external pure returns (uint256, uint256) {
revert("P7");
}
}
4 changes: 2 additions & 2 deletions docs/contracts-documentation/core/Controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ use donate() instead of direct transfer() to store the balance in assetBalance

allows the partialPauser to toggle the systemPartiallyPaused variable and partially pause or partially unpause the system

can only be called by the pauser
can only be called by the partialPauser

#### Parameters:

Expand All @@ -242,7 +242,7 @@ can only be called by the pauser

allows the fullPauser to toggle the systemFullyPaused variable and fully pause or fully unpause the system

can only be called by the pauser
can only be called by the fullyPauser

#### Parameters:

Expand Down
15 changes: 15 additions & 0 deletions docs/contracts-documentation/interfaces/ICurve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# `ICurve`

## Functions:

- `add_liquidity(uint256[2] amounts, uint256 minAmount) (external)`

- `remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 _minAmount) (external)`

- `get_virtual_price() (external)`

### Function `add_liquidity(uint256[2] amounts, uint256 minAmount) → uint256 external`

### Function `remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 _minAmount) → uint256 external`

### Function `get_virtual_price() → uint256 external`
39 changes: 39 additions & 0 deletions docs/contracts-documentation/interfaces/IStakeDao.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# `IStakeDao`

## Functions:

- `depositAll() (external)`

- `deposit(uint256 amount) (external)`

- `withdrawAll() (external)`

- `withdraw(uint256 _shares) (external)`

- `token() (external)`

- `balanceOf(address account) (external)`

- `approve(address spender, uint256 amount) (external)`

- `transfer(address recipient, uint256 amount) (external)`

- `getPricePerFullShare() (external)`

### Function `depositAll() external`

### Function `deposit(uint256 amount) external`

### Function `withdrawAll() external`

### Function `withdraw(uint256 _shares) external`

### Function `token() → contract ERC20Interface external`

### Function `balanceOf(address account) → uint256 external`

### Function `approve(address spender, uint256 amount) → bool external`

### Function `transfer(address recipient, uint256 amount) → bool external`

### Function `getPricePerFullShare() → uint256 external`
47 changes: 47 additions & 0 deletions docs/contracts-documentation/pricers/StakedaoEcrvPricer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# `StakedaoEcrvPricer`

A Pricer contract for a Stakedao lpToken

## Functions:

- `constructor(address _lpToken, address _underlying, address _oracle, address _curve) (public)`

- `getPrice() (external)`

- `setExpiryPriceInOracle(uint256 _expiryTimestamp) (external)`

- `getHistoricalPrice(uint80) (external)`

### Function `constructor(address _lpToken, address _underlying, address _oracle, address _curve) public`

#### Parameters:

- `_lpToken`: lpToken asset

- `_underlying`: underlying asset for this lpToken

- `_oracle`: Opyn Oracle contract address

- `_curve`: curve pool contract address

### Function `getPrice() → uint256 external`

get the live price for the asset

overrides the getPrice function in OpynPricerInterface

#### Return Values:

- price of 1e8 lpToken in USD, scaled by 1e8

### Function `setExpiryPriceInOracle(uint256 _expiryTimestamp) external`

set the expiry price in the oracle

requires that the underlying price has been set before setting a lpToken price

#### Parameters:

- `_expiryTimestamp`: expiry to set a price for

### Function `getHistoricalPrice(uint80) → uint256, uint256 external`
Binary file modified docs/control-flow/Gamma.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaAddressbook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaController.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaFactory.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaHighLevel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaOracle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaOtoken.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaPool.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaPricer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/control-flow/GammaWhitelist.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/uml/GammaPricer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 40 additions & 19 deletions docs/uml/GammaPricer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading