Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ pragma solidity 0.8.19;

import "./CurveStableCollateral.sol";

// No usage currently, solely for inheriting from

/**
* @title CurveAppreciatingRTokenFiatCollateral
* This plugin contract is intended for use with a CurveLP token for a pool between a
* USD reference token and an RToken that is appreciating relative to it.
* Works for both CurveGaugeWrapper and ConvexStakingWrapper.
* USD reference token and an RToken that is appreciating relative to it,
* as captured by an internal exchange rate oracle.
* Works for both CurveGaugeWrapper and ConvexStakingWrapper.
*
* Warning: Defaults after haircut! After the RToken accepts a devaluation this collateral
* plugin will default and the collateral will be removed from the basket.
*
* LP Token should be worth 2x the reference token at deployment
* LP Token should be worth 1x the reference token at deployment, not 2x like many CryptoSwaps.
*
* tok = ConvexStakingWrapper(volatileCryptoPool)
* tok = ConvexStakingWrapper(stableSwapNGPool)
* ref = USDC
* tar = USD
* UoA = USD
Expand All @@ -30,26 +33,38 @@ contract CurveAppreciatingRTokenFiatCollateral is CurveStableCollateral {
IAssetRegistry internal immutable pairedAssetRegistry; // AssetRegistry of paired RToken
IBasketHandler internal immutable pairedBasketHandler; // BasketHandler of paired RToken

uint256 public immutable pairedRTokenRefreshInterval; // {s}

/// @dev config Unused members: chainlinkFeed, oracleError, oracleTimeout
/// @dev config.erc20 should be a CurveGaugeWrapper or ConvexStakingWrapper
/// @param pairedRTokenRefreshInterval_ {s} Refresh interval of the inner RToken
constructor(
CollateralConfig memory config,
uint192 revenueHiding,
PTConfiguration memory ptConfig
PTConfiguration memory ptConfig,
uint256 pairedRTokenRefreshInterval_
) CurveStableCollateral(config, revenueHiding, ptConfig) {
rToken = IRToken(address(token0));
IMain main = rToken.main();
pairedAssetRegistry = main.assetRegistry();
pairedBasketHandler = main.basketHandler();

pairedRTokenRefreshInterval = pairedRTokenRefreshInterval_;
}

/// Should not revert
/// Refresh exchange rates and update default status.
/// Have to override to add custom default checks
function refresh() public virtual override {
// solhint-disable-next-line no-empty-blocks
try pairedAssetRegistry.refresh() {} catch {
// must allow failure since cannot brick refresh()
// refresh paired (inner) RToken lazily
if (
pairedRTokenRefreshInterval == 0 ||
pairedAssetRegistry.lastRefresh() + pairedRTokenRefreshInterval <= block.timestamp
) {
// solhint-disable-next-line no-empty-blocks
try pairedAssetRegistry.refresh() {} catch {
// must allow failure since cannot brick refresh()
}
}

CollateralStatus oldStatus = status();
Expand Down Expand Up @@ -128,20 +143,15 @@ contract CurveAppreciatingRTokenFiatCollateral is CurveStableCollateral {

/// @dev Not up-only! The RToken can devalue its exchange rate peg
/// @dev Assumption: The RToken BU is intended to equal the reference token in value
/// @dev Assumption: The pool's virtual price already embeds the RToken's appreciation
/// @return {ref/tok} Quantity of whole reference units per whole collateral tokens
function underlyingRefPerTok() public view virtual override returns (uint192) {
// {ref/tok} = quantity of the reference unit token in the pool per LP token

// {lpToken@t=0/lpToken}
uint192 virtualPrice = _safeWrap(curvePool.get_virtual_price());
// this is missing the fact that the RToken has also appreciated in this time

// {BU/rTok}
uint192 rTokenRate = divuu(rToken.basketsNeeded(), rToken.totalSupply());
// not worth the gas to protect against div-by-zero

// {ref/tok} = {ref/lpToken} = {lpToken@t=0/lpToken} * {1} * 2{ref/lpToken@t=0}
return virtualPrice.mul(rTokenRate.sqrt()).mulu(2); // LP token worth twice as much
return _safeWrap(curvePool.get_virtual_price());
// the RToken's BU exchange rate is already embedded in the virtual price
Comment thread
tbrent marked this conversation as resolved.
Outdated
// for StableSwapNG pools with internal oracles
}

/// @dev Warning: Can revert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ import "./CurveAppreciatingRTokenFiatCollateral.sol";
* Warning: Defaults after haircut! After the RToken accepts a devaluation this collateral
* plugin will default and the collateral will be removed from the basket.
*
* LP Token should be worth 2x the reference token at deployment
* LP Token should be worth 1x the reference token at deployment, not 2x like many CryptoSwaps.
*
* tok = ConvexStakingWrapper(volatileCryptoPool)
* tok = ConvexStakingWrapper(stableSwapNGPool)
* ref = WETH
* tar = ETH
* UoA = USD
*
* @notice This Curve Pool contains WETH, which can be used to intercept execution by providing
* `use_eth=true` to remove_liquidity()/remove_liquidity_one_coin(). It is guarded against
* by the recommended method of calling `claim_admin_fees()`.
* @notice This plugin assumes pure WETH, and does therefore NOT guard against reentrancy.
*/
contract CurveAppreciatingRTokenSelfReferentialCollateral is CurveAppreciatingRTokenFiatCollateral {
using OracleLib for AggregatorV3Interface;
Expand All @@ -31,18 +29,20 @@ contract CurveAppreciatingRTokenSelfReferentialCollateral is CurveAppreciatingRT

/// @dev config Unused members: chainlinkFeed, oracleError, oracleTimeout
/// @dev config.erc20 should be a CurveGaugeWrapper or ConvexStakingWrapper
/// @param pairedRTokenRefreshInterval_ {s} Refresh interval of the inner RToken
constructor(
CollateralConfig memory config,
uint192 revenueHiding,
PTConfiguration memory ptConfig
) CurveAppreciatingRTokenFiatCollateral(config, revenueHiding, ptConfig) {}

/// Should not revert (unless CurvePool is re-entrant!)
/// Refresh exchange rates and update default status.
function refresh() public virtual override {
curvePool.claim_admin_fees(); // revert if curve pool is re-entrant
super.refresh();
}
PTConfiguration memory ptConfig,
uint256 pairedRTokenRefreshInterval_
)
CurveAppreciatingRTokenFiatCollateral(
config,
revenueHiding,
ptConfig,
pairedRTokenRefreshInterval_
)
{}

// === Internal ===

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ async function main() {
oracleTimeouts: [[bn('1')], [WETH_ORACLE_TIMEOUT]],
oracleErrors: [[bn('1')], [WETH_ORACLE_ERROR]],
lpToken: ETHPLUS_BP_TOKEN,
}
},
'86400' // refresh ETH+ every 24h
)
)
await collateral.deployed()
Expand Down
10 changes: 5 additions & 5 deletions test/plugins/individual-collateral/curve/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ETHPLUS = networkConfig['1'].tokens.ETHPLUS!
export const ETHPLUS_ASSET_REGISTRY = '0xf526f058858E4cD060cFDD775077999562b31bE0'
export const ETHPLUS_BASKET_HANDLER = '0x56f40A33e3a3fE2F1614bf82CBeb35987ac10194'
export const ETHPLUS_BACKING_MANAGER = '0x608e1e01EF072c15E5Da7235ce793f4d24eCa67B'
export const ETHPLUS_TIMELOCK = '0x5f4A10aE2fF68bE3cdA7d7FB432b10C6BFA6457B'
export const ETHPLUS_TIMELOCK = '0x5d8A7DC9405F08F14541BA918c1Bf7eb2dACE556'

// USDC+
export const USDCPLUS = networkConfig['1'].tokens.USDCPLUS!
Expand Down Expand Up @@ -141,10 +141,10 @@ export const EUSD_BASKET_HANDLER = '0x6d309297ddDFeA104A6E89a132e2f05ce3828e07'
export const eUSD_BACKING_MANAGER = '0xF014FEF41cCB703975827C8569a3f0940cFD80A4'

// ETH+ + ETH
export const ETHPLUS_BP_POOL = '0x7fb53345f1b21ab5d9510adb38f7d3590be6364b'
export const ETHPLUS_BP_TOKEN = '0xe8a5677171c87fcb65b76957f2852515b404c7b1'
export const ETHPLUS_BP_POOL_ID = 185
export const ETHPLUS_ETH_HOLDER = '0x298bf7b80a6343214634aF16EB41Bb5B9fC6A1F1'
export const ETHPLUS_BP_POOL = '0x2c683fAd51da2cd17793219CC86439C1875c353e'
export const ETHPLUS_BP_TOKEN = '0x2c683fAd51da2cd17793219CC86439C1875c353e'
export const ETHPLUS_BP_POOL_ID = 470
export const ETHPLUS_ETH_HOLDER = '0xAD6D1a4B1B2F33712A8b18BeDc95c0A1f9832269'

// USDC + USDC+
export const USDC_USDCPLUS_GAUGE = networkConfig['1'].tokens.sdUSDCUSDCPlus!
Expand Down
Loading
Loading