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

AerodromeVolatileCollateral (base) #1221

Merged
merged 46 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
dd27190
aerodrome initial draft
julianmrodri Sep 6, 2024
f1dfdbc
fix and tweak tryPrice
tbrent Sep 7, 2024
b1f10da
apply revenue hiding and scripts
julianmrodri Sep 11, 2024
6b7be0e
apply correct k formula for stable pools
julianmrodri Sep 12, 2024
f63fb4e
temp testing changes
julianmrodri Sep 19, 2024
4ca20a4
implement new function and set debugging
julianmrodri Sep 20, 2024
0066426
Tiny change
akshatmittal Sep 20, 2024
5870acd
refPerTok()
tbrent Sep 21, 2024
3dd2b9d
final test and script adjustments
julianmrodri Sep 23, 2024
3cdb40b
fix lint
julianmrodri Sep 23, 2024
ed650aa
add readme
julianmrodri Sep 23, 2024
773ed0d
add aerodrome test in ci
julianmrodri Sep 23, 2024
4802b4d
avoid gauge test on mainnet
julianmrodri Sep 23, 2024
4475c31
add aero to config
julianmrodri Oct 1, 2024
f974bf3
add check for stable pools
julianmrodri Oct 1, 2024
49b0216
change pegPrice
julianmrodri Oct 4, 2024
434145d
low high fix
julianmrodri Oct 7, 2024
b42b0c9
deployed.
pmckelvy1 Oct 16, 2024
896ae34
init AerodromeVolatileCollateral
tbrent Oct 28, 2024
7bad215
deployment + verification scripts
tbrent Oct 28, 2024
86f4d3b
nit
tbrent Oct 28, 2024
feda2e1
fix
tbrent Oct 29, 2024
0d1943a
base addresses
tbrent Oct 29, 2024
c3a0189
deploy aero
julianmrodri Oct 29, 2024
26ff39a
adapt feed revert test
julianmrodri Nov 1, 2024
b4fcfb8
Merge branch '4.0.0' into aerodrome-plugin
julianmrodri Nov 1, 2024
fa9070e
add new parameter
julianmrodri Nov 1, 2024
6b183a7
add new param
julianmrodri Nov 1, 2024
dc65ee3
add new param to aave test
julianmrodri Nov 1, 2024
329eae3
integration test AerodromeVolatileCollateral
tbrent Nov 5, 2024
f036340
Merge branch 'aerodrome-plugin' into aero-vAMM
tbrent Nov 5, 2024
fd016d1
fix mog aero and add verify script
tbrent Nov 5, 2024
8dd1684
remove itChecksMainChainlinkOracleRevert
tbrent Nov 5, 2024
26427bf
nit
tbrent Nov 5, 2024
afb3b61
fix WETH/AERO tests
tbrent Nov 5, 2024
c40b21d
adapt tests
julianmrodri Nov 5, 2024
5baca37
Merge branch '4.0.0' into aero-vAMM
tbrent Nov 6, 2024
0afed26
cleanup merge
tbrent Nov 6, 2024
5f91274
remove itChecksMainChainlinkOracleRevert
tbrent Nov 6, 2024
a988d2f
Merge branch '4.0.0' into aero-vAMM
tbrent Nov 6, 2024
bdbce4e
new deployed addresses for stable (#1228)
julianmrodri Nov 6, 2024
f2f9fa6
rollback deployments
julianmrodri Nov 7, 2024
975b6fb
lint
julianmrodri Nov 7, 2024
b13ffa2
fix AerodomeVolatileCollateral pricing
tbrent Nov 11, 2024
6af5d83
addresses
tbrent Nov 11, 2024
ad37084
Fixes and new volatile plugins and addresses (#1230)
julianmrodri Dec 11, 2024
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
18 changes: 18 additions & 0 deletions common/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,12 @@ export interface ITokens {

// Aerodrome
AERO?: string

MOG?: string
USDz?: string
cbBTC?: string
WELL?: string
DEGEN?: string

// Sky
USDS?: string
Expand Down Expand Up @@ -154,7 +159,12 @@ export interface IPools {
crvMIM3Pool?: string
sdUSDCUSDCPlus?: string
aeroUSDCeUSD?: string
aeroWETHAERO?: string
aeroMOGWETH?: string
aeroUSDzUSDC?: string
aeroWETHcbBTC?: string
aeroWETHWELL?: string
aeroWETHDEGEN?: string
}

interface INetworkConfig {
Expand Down Expand Up @@ -533,9 +543,13 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
wstETH: '0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452',
STG: '0xE3B53AF74a4BF62Ae5511055290838050bf764Df',
eUSD: '0xCfA3Ef56d303AE4fAabA0592388F19d7C3399FB4',
MOG: '0x2Da56AcB9Ea78330f947bD57C54119Debda7AF71',
USDz: '0x04D5ddf5f3a8939889F11E97f8c4BB48317F1938',
meUSD: '0xbb819D845b573B5D7C538F5b85057160cfb5f313',
AERO: '0x940181a94A35A4569E4529A3CDfB74e38FD98631',
cbBTC: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf',
WELL: '0xA88594D404727625A9437C3f886C7643872296AE',
DEGEN: '0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed',
},
chainlinkFeeds: {
DAI: '0x591e79239a7d679378ec8c847e5038150364c78f', // 0.3%, 24hr
Expand All @@ -555,6 +569,10 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
eUSD: '0x9b2C948dbA5952A1f5Ab6fA16101c1392b8da1ab', // 0.5%, 24h
USDz: '0xe25969e2Fa633a0C027fAB8F30Fc9C6A90D60B48', // 0.5%, 24h
AERO: '0x4EC5970fC728C5f65ba413992CD5fF6FD70fcfF0', // 0.5%, 24h
MOG: '0x4aeb6D15769EaD32D0c5Be2940F40c7CFf53801d', // 0.5%, 24h
cbBTC: '0x07DA0E54543a844a80ABE69c8A12F22B3aA59f9D', // 0.3%, 20 min
WELL: '0xc15d9944dAefE2dB03e53bef8DDA25a56832C5fe', // 0.5%, 24h
DEGEN: '0xE62BcE5D7CB9d16AB8b4D622538bc0A50A5799c2', // 0.5%, 24h
},
GNOSIS_EASY_AUCTION: '0xb1875Feaeea32Bbb02DE83D81772e07E37A40f02', // mock
COMET_REWARDS: '0x123964802e6ABabBE1Bc9547D72Ef1B69B00A6b1',
Expand Down
13 changes: 8 additions & 5 deletions contracts/plugins/assets/aerodrome/AerodromePoolTokens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "contracts/plugins/assets/OracleLib.sol";
import "contracts/libraries/Fixed.sol";
import "./vendor/IAeroPool.sol";

/// Supports Aerodrome stable pools (2 tokens)
/// Supports Aerodrome stable and volatile pools (2 tokens)
contract AerodromePoolTokens {
using OracleLib for AggregatorV3Interface;
using FixLib for uint192;
Expand All @@ -20,7 +20,7 @@ contract AerodromePoolTokens {

enum AeroPoolType {
Stable,
Volatile // not supported in this version
Volatile
}

// === State (Immutable) ===
Expand Down Expand Up @@ -76,7 +76,10 @@ contract AerodromePoolTokens {

// === Tokens ===

if (config.poolType != AeroPoolType.Stable || !config.pool.stable()) {
if (config.poolType == AeroPoolType.Stable && !config.pool.stable()) {
revert("invalid poolType");
}
if (config.poolType == AeroPoolType.Volatile && config.pool.stable()) {
revert("invalid poolType");
}

Expand Down Expand Up @@ -175,8 +178,8 @@ contract AerodromePoolTokens {
}

/// @param index The index of the token: 0 or 1
/// @return [{ref_index}]
function tokenReserve(uint8 index) public view virtual returns (uint256) {
/// @return {ref_index}
function tokenReserve(uint8 index) public view virtual returns (uint192) {
if (index >= nTokens) revert WrongIndex(nTokens - 1);
// Maybe also cache token decimals as immutable?
IERC20Metadata tokenInterface = getToken(index);
Expand Down
112 changes: 19 additions & 93 deletions contracts/plugins/assets/aerodrome/AerodromeStableCollateral.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
// SPDX-License-Identifier: BlueOak-1.0.0
pragma solidity 0.8.19;

import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "contracts/interfaces/IAsset.sol";
import "contracts/libraries/Fixed.sol";
import "contracts/plugins/assets/FiatCollateral.sol";
import "../../../interfaces/IRewardable.sol";
import "./AerodromePoolTokens.sol";

// This plugin only works on Base
IERC20 constant AERO = IERC20(0x940181a94A35A4569E4529A3CDfB74e38FD98631);
import "./AerodromeVolatileCollateral.sol";

/**
* @title AerodromeStableCollateral
Expand All @@ -24,20 +14,17 @@ IERC20 constant AERO = IERC20(0x940181a94A35A4569E4529A3CDfB74e38FD98631);
* UoA = USD
*
*/
contract AerodromeStableCollateral is FiatCollateral, AerodromePoolTokens {
contract AerodromeStableCollateral is AerodromeVolatileCollateral {
using OracleLib for AggregatorV3Interface;
using FixLib for uint192;

/// @dev config Unused members: chainlinkFeed, oracleError, oracleTimeout
/// @dev No revenue hiding (refPerTok() == FIX_ONE)
/// @dev No revenue hiding (refPerTok() is constant)
/// @dev config.erc20 should be an AerodromeStakingWrapper
constructor(CollateralConfig memory config, APTConfiguration memory aptConfig)
FiatCollateral(config)
AerodromePoolTokens(aptConfig)
AerodromeVolatileCollateral(config, aptConfig)
{
require(config.defaultThreshold != 0, "defaultThreshold zero");
assert((token0.decimals() + token1.decimals()) % 2 == 0);
maxOracleTimeout = uint48(Math.max(maxOracleTimeout, maxPoolOracleTimeout()));
}

/// Can revert, used by other contract functions in order to catch errors
Expand All @@ -58,105 +45,44 @@ contract AerodromeStableCollateral is FiatCollateral, AerodromePoolTokens {
uint192 pegPrice
)
{
uint256 r0 = tokenReserve(0);
uint256 r1 = tokenReserve(1);
uint256 r0 = tokenReserve(0); // {ref_0} upcast
uint256 r1 = tokenReserve(1); // {ref_1} upcast

// xy^3 + yx^3 >= k for sAMM pools
uint256 sqrtReserve = sqrt256(sqrt256(r0 * r1) * sqrt256(r0 * r0 + r1 * r1));

// get token prices
(uint192 p0_low, uint192 p0_high) = tokenPrice(0);
(uint192 p1_low, uint192 p1_high) = tokenPrice(1);
(uint192 p0_low, uint192 p0_high) = tokenPrice(0); // {UoA/ref_0}
(uint192 p1_low, uint192 p1_high) = tokenPrice(1); // {UoA/ref_1}

uint192 totalSupply = shiftl_toFix(pool.totalSupply(), -int8(pool.decimals()), FLOOR);
// all aero pools have 18 decimals
uint192 totalSupply = _safeWrap(pool.totalSupply());

// low
{
uint256 ratioLow = ((1e18) * p0_high) / p1_low;
uint256 ratioLow = (1e18 * p0_high) / p1_low;
uint256 sqrtPriceLow = sqrt256(
sqrt256((1e18) * ratioLow) * sqrt256(1e36 + ratioLow * ratioLow)
sqrt256(1e18 * ratioLow) * sqrt256(1e36 + ratioLow * ratioLow)
);
low = _safeWrap(((((1e18) * sqrtReserve) / sqrtPriceLow) * p0_low * 2) / totalSupply);
low = _safeWrap((((1e18 * sqrtReserve) / sqrtPriceLow) * p0_low * 2) / totalSupply);
}
// high
{
uint256 ratioHigh = ((1e18) * p0_low) / p1_high;
uint256 ratioHigh = (1e18 * p0_low) / p1_high;
uint256 sqrtPriceHigh = sqrt256(
sqrt256((1e18) * ratioHigh) * sqrt256(1e36 + ratioHigh * ratioHigh)
sqrt256(1e18 * ratioHigh) * sqrt256(1e36 + ratioHigh * ratioHigh)
);

high = _safeWrap(
((((1e18) * sqrtReserve) / sqrtPriceHigh) * p0_high * 2) / totalSupply
);
high = _safeWrap((((1e18 * sqrtReserve) / sqrtPriceHigh) * p0_high * 2) / totalSupply);
}
assert(low <= high); //obviously true just by inspection

// {target/ref} = {UoA/ref} = {UoA/tok} / ({ref/tok}
// {target/ref} and {UoA/ref} are the same since target == UoA
pegPrice = ((low + high) / 2).div(refPerTok());
}

/// Should not revert
/// Refresh exchange rates and update default status.
/// Have to override to add custom default checks
function refresh() public virtual override {
CollateralStatus oldStatus = status();

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

// Save prices if priced
if (high != FIX_MAX) {
savedLowPrice = low;
savedHighPrice = high;
savedPegPrice = pegPrice;
lastSave = uint48(block.timestamp);
} else {
// must be unpriced
// untested:
// validated in other plugins, cost to test here is high
assert(low == 0);
}

// If the price is below the default-threshold price, default eventually
// uint192(+/-) is the same as Fix.plus/minus
if (low == 0 || _anyDepeggedInPool()) {
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);
}
}

/// Claim rewards earned by holding a balance of the ERC20 token
/// @custom:delegate-call
function claimRewards() external virtual override(Asset, IRewardable) {
uint256 aeroBal = AERO.balanceOf(address(this));
IRewardable(address(erc20)).claimRewards();
emit RewardsClaimed(AERO, AERO.balanceOf(address(this)) - aeroBal);
}
assert(low <= high); // not obviously true just by inspection

/// @return {ref/tok} Actual quantity of whole reference units per whole collateral tokens
function refPerTok() public view virtual override returns (uint192) {
int8 shift = 18 - int8((token0.decimals() + token1.decimals()) / 2);
return shiftl_toFix(2, shift, FLOOR);
pegPrice = 0;
}

// === Internal ===

// Override this later to implement non-stable pools
function _anyDepeggedInPool() internal view virtual returns (bool) {
function _anyDepeggedInPool() internal view virtual override returns (bool) {
// Check reference token oracles
for (uint8 i = 0; i < nTokens; ++i) {
try this.tokenPrice(i) returns (uint192 low, uint192 high) {
Expand Down
Loading
Loading