Skip to content

Commit

Permalink
Plugin stargate fixes and changes (#953)
Browse files Browse the repository at this point in the history
Co-authored-by: pmckelvy1 <[email protected]>
  • Loading branch information
julianmrodri and pmckelvy1 authored Oct 4, 2023
1 parent 9014df3 commit faefb75
Show file tree
Hide file tree
Showing 14 changed files with 97 additions and 249 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,30 @@ import "./interfaces/IStargatePool.sol";
import "./StargatePoolFiatCollateral.sol";

/**
* @title StargatePoolETHCollateral
* ************************************************************
* WARNING: this plugin is DEPRECATED!
* Not ready to be deployed and used in Production environments
* ************************************************************
*/

/**
* @title StargatePoolETHCollateral (DO NOT USE)
* @notice Collateral plugin for Stargate ETH,
* tok = wstgETH
* ref = ETH
* tar = ETH
* UoA = USD
*/

contract StargatePoolETHCollateral is StargatePoolFiatCollateral {
using FixLib for uint192;
using OracleLib for AggregatorV3Interface;

/// @param config.chainlinkFeed Feed units: {UoA/target}
// solhint-disable no-empty-blocks
constructor(CollateralConfig memory config) StargatePoolFiatCollateral(config) {}
constructor(CollateralConfig memory config, uint192 revenueHiding)
StargatePoolFiatCollateral(config, revenueHiding)
{}

/// Can revert, used by other contract functions in order to catch errors
/// Should not return FIX_MAX for low
Expand Down
6 changes: 3 additions & 3 deletions contracts/plugins/assets/stargate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ To use the wrapper token for automatic staking and reward collection, follow the

## Collateral plugin

There are 2 variants of this plugin that can be deployed.
There are 2 variants of this plugin:

1. **`StargatePoolFiatCollateral`**: This contract serves for the USDC, USDT and any other USD-pegged token. The target for these collaterals is **USD**.
2. **`StargatePoolETHCollateral`**: This contract serves the ETH pool. The underlying token for the Stargate ETH pool is SGETH which is mapped 1:1 with ETH. The chainlink feed that will then be provided during deployment would be an ETH-USD oracle. The target for this collateral is **ETH**.
1. **`StargatePoolFiatCollateral`**: This contract serves for the USDC, USDT and any other USD-pegged token. The target for these collaterals is **USD**. Ready for deployment and use.
2. **`StargatePoolETHCollateral`**: _DEPRECATED_. This contract serves the ETH pool. The underlying token for the Stargate ETH pool is SGETH which is mapped 1:1 with ETH. The chainlink feed that will then be provided during deployment would be an ETH-USD oracle. The target for this collateral is **ETH**. _Warning: Not ready to be used in Production_

The **`{ref/tok}`** is computed as the ratio of the total liquidity to the total LP tokens in circulation. This ratio never drops except for a very rare occasion where the pool's total supply drops to zero, in which case the **`{ref/tok}`** falls back to 1 and the plugin will default under such circumstances.

Expand Down
108 changes: 9 additions & 99 deletions contracts/plugins/assets/stargate/StargatePoolFiatCollateral.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
pragma solidity 0.8.19;

import "../../../libraries/Fixed.sol";
import "../OracleLib.sol";
import "../FiatCollateral.sol";
import "../AppreciatingFiatCollateral.sol";
import "./interfaces/IStargatePool.sol";

import "./StargateRewardableWrapper.sol";

/**
Expand All @@ -16,114 +14,26 @@ import "./StargateRewardableWrapper.sol";
* tar = USD
* UoA = USD
*/
contract StargatePoolFiatCollateral is FiatCollateral {
using FixLib for uint192;
using OracleLib for AggregatorV3Interface;

// does not become nonzero until after first refresh()
uint192 public lastReferencePrice; // {ref/tok} last ref price observed

contract StargatePoolFiatCollateral is AppreciatingFiatCollateral {
IStargatePool private immutable pool;

/// @param config.chainlinkFeed Feed units: {UoA/ref}
// solhint-disable no-empty-blocks
constructor(CollateralConfig memory config) FiatCollateral(config) {
pool = StargateRewardableWrapper(address(config.erc20)).pool();
}

/// Can revert, used by other contract functions in order to catch errors
/// Should not return FIX_MAX for low
/// Should only return FIX_MAX for high if low is 0
/// @dev Override this when pricing is more complicated than just a single oracle
/// @param low {UoA/tok} The low price estimate
/// @param high {UoA/tok} The high price estimate
/// @param pegPrice {target/tok} The actual price observed in the peg
function tryPrice()
external
view
virtual
override
returns (
uint192 low,
uint192 high,
uint192 pegPrice
)
constructor(CollateralConfig memory config, uint192 revenueHiding)
AppreciatingFiatCollateral(config, revenueHiding)
{
pegPrice = chainlinkFeed.price(oracleTimeout); // {target/ref}

// Assumption: {UoA/target} = 1; target is same as UoA
// {UoA/tok} = {UoA/target} * {target/ref} * {ref/tok}
uint192 p = pegPrice.mul(refPerTok());

// {UoA/tok} = {UoA/tok} * {1}
uint192 delta = p.mul(oracleError);

low = p - delta;
high = p + delta;
}

/// Should not revert
/// Refresh exchange rates and update default status.
/// @dev Should not need to override: can handle collateral with variable refPerTok()
function refresh() public virtual override {
CollateralStatus oldStatus = status();

// Check for hard default

uint192 referencePrice = refPerTok();
uint192 lastReferencePrice_ = lastReferencePrice;

// uint192(<) is equivalent to Fix.lt
if (referencePrice < lastReferencePrice_) {
markStatus(CollateralStatus.DISABLED);
} else if (referencePrice > lastReferencePrice_) {
lastReferencePrice = referencePrice;
}

// Check for soft default + save prices
try this.tryPrice() returns (uint192 low, uint192 high, uint192 pegPrice) {
// {UoA/tok}, {UoA/tok}, {target/ref}
// (0, 0) is a valid price; (0, FIX_MAX) is unpriced

// Save prices if priced
if (high < FIX_MAX) {
savedLowPrice = low;
savedHighPrice = high;
lastSave = uint48(block.timestamp);
} else {
// must be unpriced
assert(low == 0);
}

// If the price is below the default-threshold price, default eventually
// uint192(+/-) is the same as Fix.plus/minus
if (pegPrice < pegBottom || pegPrice > pegTop || low == 0) {
markStatus(CollateralStatus.IFFY);
} else {
markStatus(CollateralStatus.SOUND);
}
} catch (bytes memory errData) {
// see: docs/solidity-style.md#Catching-Empty-Data
if (errData.length == 0) revert(); // solhint-disable-line reason-string
markStatus(CollateralStatus.IFFY);
}

CollateralStatus newStatus = status();
if (oldStatus != newStatus) {
emit CollateralStatusChanged(oldStatus, newStatus);
}
pool = StargateRewardableWrapper(address(config.erc20)).pool();
}

/// @return _rate {ref/tok} Quantity of whole reference units per whole collateral tokens
function refPerTok() public view virtual override returns (uint192 _rate) {
function _underlyingRefPerTok() internal view virtual override returns (uint192) {
uint256 _totalSupply = pool.totalSupply();

uint192 _rate = FIX_ONE; // 1:1 if pool has no tokens at all
if (_totalSupply != 0) {
_rate = divuu(pool.totalLiquidity(), _totalSupply);
} else {
// In case the pool has no tokens at all, the rate is 1:1
_rate = FIX_ONE;
}

return _rate;
}

function claimRewards() external override(Asset, IRewardable) {
Expand Down
17 changes: 6 additions & 11 deletions contracts/plugins/assets/stargate/StargateRewardableWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity ^0.8.19;

import "./interfaces/IStargateLPStaking.sol";
import "./interfaces/IStargatePool.sol";

import "../erc20/RewardableERC20Wrapper.sol";

contract StargateRewardableWrapper is RewardableERC20Wrapper {
Expand Down Expand Up @@ -42,12 +41,8 @@ contract StargateRewardableWrapper is RewardableERC20Wrapper {
}

function _claimAssetRewards() internal override {
IStargateLPStaking.PoolInfo memory poolInfo = stakingContract.poolInfo(poolId);

if (poolInfo.allocPoint != 0 && totalSupply() != 0) {
if (stakingContract.totalAllocPoint() != 0) {
stakingContract.deposit(poolId, 0);
} else {
stakingContract.emergencyWithdraw(poolId);
}
}

Expand All @@ -64,13 +59,13 @@ contract StargateRewardableWrapper is RewardableERC20Wrapper {
function _beforeWithdraw(uint256 _amount, address) internal override {
IStargateLPStaking.PoolInfo memory poolInfo = stakingContract.poolInfo(poolId);

if (poolInfo.allocPoint != 0) {
uint256 underlyingBalance = underlying.balanceOf(address(this));
if (underlyingBalance < _amount) {
uint256 underlyingBalance = underlying.balanceOf(address(this));
if (underlyingBalance < _amount) {
if (poolInfo.allocPoint != 0) {
stakingContract.withdraw(poolId, _amount - underlyingBalance);
} else {
stakingContract.emergencyWithdraw(poolId);
}
} else {
stakingContract.emergencyWithdraw(poolId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,6 @@ interface IStargateLPStaking {
function add(uint256 _allocPoint, IERC20 _lpToken) external;

function owner() external view returns (address);

function totalAllocPoint() external view returns (uint256);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ contract StargateLPStakingMock is IStargateLPStaking {
ERC20Mock public immutable stargateMock;
IERC20 public immutable stargate;

uint256 public totalAllocPoint = 0;

constructor(ERC20Mock stargateMock_) {
stargateMock = stargateMock_;
stargate = stargateMock_;
Expand Down Expand Up @@ -70,9 +72,11 @@ contract StargateLPStakingMock is IStargateLPStaking {
info.lpToken = lpToken;
info.allocPoint = 10;
_poolInfo.push(info);
totalAllocPoint = totalAllocPoint + info.allocPoint;
}

function setAllocPoint(uint256 pid, uint256 allocPoint) external {
totalAllocPoint = (totalAllocPoint - _poolInfo[pid].allocPoint) + allocPoint;
_poolInfo[pid].allocPoint = allocPoint;
}

Expand Down
10 changes: 10 additions & 0 deletions contracts/plugins/assets/stargate/mocks/StargatePoolMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ contract StargatePoolMock is ERC20Mock {
return _decimals;
}

function exchangeRate() external view returns (uint192) {
uint256 _totalSupply = totalSupply();
uint192 _rate = FIX_ONE; // 1:1 if pool has no tokens at all
if (_totalSupply != 0) {
_rate = divuu(totalLiquidity, _totalSupply);
}

return _rate;
}

function setExchangeRate(uint192 rate) external {
uint192 fixTotalLiquidity = rate.mul(shiftl_toFix(totalSupply(), -int8(decimals())));
totalLiquidity = shiftl_toFix(fixTotalLiquidity, -(36 - int8(decimals())));
Expand Down

This file was deleted.

Loading

0 comments on commit faefb75

Please sign in to comment.