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

Fixes and new volatile plugins and addresses #1230

Merged
merged 4 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions common/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ export interface ITokens {

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

// Sky
USDS?: string
Expand Down Expand Up @@ -159,6 +162,9 @@ export interface IPools {
aeroWETHAERO?: string
aeroMOGWETH?: string
aeroUSDzUSDC?: string
aeroWETHcbBTC?: string
aeroWETHWELL?: string
aeroWETHDEGEN?: string
}

interface INetworkConfig {
Expand Down Expand Up @@ -541,6 +547,9 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
USDz: '0x04D5ddf5f3a8939889F11E97f8c4BB48317F1938',
meUSD: '0xbb819D845b573B5D7C538F5b85057160cfb5f313',
AERO: '0x940181a94A35A4569E4529A3CDfB74e38FD98631',
cbBTC: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf',
WELL: '0xA88594D404727625A9437C3f886C7643872296AE',
DEGEN: '0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed',
},
chainlinkFeeds: {
DAI: '0x591e79239a7d679378ec8c847e5038150364c78f', // 0.3%, 24hr
Expand All @@ -561,6 +570,9 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
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
4 changes: 2 additions & 2 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
10 changes: 3 additions & 7 deletions contracts/plugins/assets/aerodrome/AerodromeStableCollateral.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract AerodromeStableCollateral is AerodromeVolatileCollateral {
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)
AerodromeVolatileCollateral(config, aptConfig)
Expand Down Expand Up @@ -73,15 +73,11 @@ contract AerodromeStableCollateral is AerodromeVolatileCollateral {
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); // not 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());
pegPrice = 0;
}

// === Internal ===
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ contract AerodromeVolatileCollateral is FiatCollateral, AerodromePoolTokens {
using FixLib for uint192;

/// @dev config Unused members: chainlinkFeed, oracleError, oracleTimout
/// @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)
Expand Down
17 changes: 9 additions & 8 deletions contracts/plugins/assets/aerodrome/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Aerodrome Stable Collateral Plugin
# Aerodrome Collateral Plugins

[Aerodrome Finance](https://aerodrome.finance) is an AMM designed to serve as Base's central liquidity hub. This plugin enables the use of any Aerodrome Stable LP token as collateral within the Reserve Protocol.
[Aerodrome Finance](https://aerodrome.finance) is an AMM designed to serve as Base's central liquidity hub. This plugin enables the use of any Aerodrome Stable and Volatile LP token as collateral within the Reserve Protocol.

Aerodrome Finance offers two different liquidity pool types based on token pair needs, `Stable Pools` and `Volatile Pools`.

Only `Stable Pools` are currently supported. These pools are designed for tokens which have little to no volatility, and use the current formula for pricing tokens:
`Stable Pools` are designed for tokens which have little to no volatility, and use the current formula for pricing tokens: `x³y + y³x ≥ k`

`x³y + y³x ≥ k`
`Volatile Pools` are designed for tokens with high price volatility, and use a generic AMM formula: `x × y ≥ k`

## Usage

Expand Down Expand Up @@ -36,10 +36,11 @@ Internally, all `tokensPriceFeeds` are stored as multiple separate immutable var

### refPerTok

Aerodrome Stable Pools do not appreciate in value over time, so `refPerTok()` will be constant for these plugins and will not change. This also means there are no hard default checks in place.
Aerodrome Pools do not appreciate in value over time, so `refPerTok()` will be constant for these plugins and will not change. This also means there are no hard default checks in place.

## Implementation

| `tok` | `ref` | `target` | `UoA` |
| :------------------: | :---------------: | :------: | :---: |
| Aero Staking Wrapper | LP token /w shift | USD | USD |
| `tok` | `ref` | `target` | `UoA` |
| :------------------: | :---------------: | :--------------: | :---: |
| Aero Staking Wrapper | LP token /w shift | USD (Stable) | USD |
| Aero Staking Wrapper | LP token /w shift | cpAMM (Volatile) | USD |
18 changes: 12 additions & 6 deletions scripts/addresses/8453-tmp-assets-collateral.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
"cUSDCv3": "0xf7a9D27c3B60c78c6F6e2c2d6ED6E8B94b352461",
"wstETH": "0x8b4374005291B8FCD14C4E947604b2FB3C660A73",
"aeroUSDCeUSD": "0x9216CD5cA133aBBd23cc6F873bB4a95A78032db0",
"aeroWETHAERO": "0x1bD9eAEB0eD1aB51dA1Ff8D437892488790bbde7",
"aeroMOGWETH": "0x6Ec09BD7d32F1023626AaEa1090e178d81C7701A",
"aeroWETHAERO": "0xaC23df4289e2FeaFb2851e63958C2AAF41DB4833",
"aeroMOGWETH": "0xfAa0cfc986041a3aF69207C6fCF35316D58fEA6a",
"meUSD": "0x0f1e10871e6a2D3A5Aa696b85b39d61a22A9e8C3",
"aeroUSDzUSDC": "0x8AAdfbea33146e28170F99D031B7747EAa87DDD4"
"aeroUSDzUSDC": "0x8AAdfbea33146e28170F99D031B7747EAa87DDD4",
"aeroWETHcbBTC": "0x5ABe1A8b04A2428589bAeF9486d12688d482D061",
"aeroWETHWELL": "0x7df3541FFeDAA956aE6136E64253f3749b055Be6",
"aeroWETHDEGEN": "0xc8E72288f717Da55b7231365daE17AcD91b59705"
},
"erc20s": {
"COMP": "0x9e1028F5F1D5eDE59748FFceE5532509976840E0",
Expand All @@ -31,10 +34,13 @@
"cUSDCv3": "0x53f1Df4E5591Ae35Bf738742981669c3767241FA",
"wstETH": "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
"aeroUSDCeUSD": "0xDB5b8cead52f77De0f6B5255f73F348AAf2CBb8D",
"aeroWETHAERO": "0x3712DDCF9aE516dD01042948B76A76901a84CD36",
"aeroMOGWETH": "0xCcC18B21be01a37ebFa5C932eD09574752F88C15",
"aeroWETHAERO": "0x65f2c1b253a3E45670aDD259C9688Edf1A3b814d",
"aeroMOGWETH": "0xfaAC26b279338dF8cF56B11A572617f674A2F69C",
"meUSD": "0xbb819D845b573B5D7C538F5b85057160cfb5f313",
"AERO": "0x940181a94A35A4569E4529A3CDfB74e38FD98631",
"aeroUSDzUSDC": "0x246Df11B856E9fD6120494F168475e1b41321c61"
"aeroUSDzUSDC": "0x246Df11B856E9fD6120494F168475e1b41321c61",
"aeroWETHcbBTC": "0x4BD08a771CdAbA5333CAc6F20322eD7d72b6cBfA",
"aeroWETHWELL": "0x1F599F8657CAA38Ee825e4E2d64F695749E2a161",
"aeroWETHDEGEN": "0xA762F790a31654D9AeF7DE550A473A0F5621E4F1"
}
}
2 changes: 1 addition & 1 deletion scripts/addresses/8453-tmp-deployments.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@
"stRSR": "0x4Cf200D7fA568611DD8B4BD85053ba9419982C7D"
}
}
}
}
14 changes: 10 additions & 4 deletions scripts/addresses/base-4.0.0/8453-tmp-assets-collateral.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@
"meUSD": "0x0f1e10871e6a2D3A5Aa696b85b39d61a22A9e8C3",
"aeroUSDCeUSD": "0x9216CD5cA133aBBd23cc6F873bB4a95A78032db0",
"aeroUSDzUSDC": "0x8AAdfbea33146e28170F99D031B7747EAa87DDD4",
"aeroWETHAERO": "0x1bD9eAEB0eD1aB51dA1Ff8D437892488790bbde7",
"aeroMOGWETH": "0x6Ec09BD7d32F1023626AaEa1090e178d81C7701A"
"aeroWETHAERO": "0xaC23df4289e2FeaFb2851e63958C2AAF41DB4833",
"aeroMOGWETH": "0xfAa0cfc986041a3aF69207C6fCF35316D58fEA6a",
"aeroWETHcbBTC": "0x5ABe1A8b04A2428589bAeF9486d12688d482D061",
"aeroWETHWELL": "0x7df3541FFeDAA956aE6136E64253f3749b055Be6",
"aeroWETHDEGEN": "0xc8E72288f717Da55b7231365daE17AcD91b59705"
},
"erc20s": {
"meUSD": "0xbb819D845b573B5D7C538F5b85057160cfb5f313",
"aeroUSDCeUSD": "0xDB5b8cead52f77De0f6B5255f73F348AAf2CBb8D",
"AERO": "0x940181a94A35A4569E4529A3CDfB74e38FD98631",
"aeroUSDzUSDC": "0x246Df11B856E9fD6120494F168475e1b41321c61",
"aeroWETHAERO": "0x3712DDCF9aE516dD01042948B76A76901a84CD36",
"aeroMOGWETH": "0xCcC18B21be01a37ebFa5C932eD09574752F88C15"
"aeroWETHAERO": "0x65f2c1b253a3E45670aDD259C9688Edf1A3b814d",
"aeroMOGWETH": "0xfaAC26b279338dF8cF56B11A572617f674A2F69C",
"aeroWETHcbBTC": "0x4BD08a771CdAbA5333CAc6F20322eD7d72b6cBfA",
"aeroWETHWELL": "0x1F599F8657CAA38Ee825e4E2d64F695749E2a161",
"aeroWETHDEGEN": "0xA762F790a31654D9AeF7DE550A473A0F5621E4F1"
}
}
3 changes: 3 additions & 0 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ async function main() {
'phase2-assets/collaterals/deploy_aerodrome_weth_aero.ts',
'phase2-assets/collaterals/deploy_aerodrome_mog_weth.ts',
'phase2-assets/collaterals/deploy_aerodrome_usdz_usdc.ts',
'phase2-assets/collaterals/deploy_aerodrome_weth_cbbtc.ts',
'phase2-assets/collaterals/deploy_aerodrome_weth_well.ts',
'phase2-assets/collaterals/deploy_aerodrome_weth_degen.ts',
'phase2-assets/collaterals/deploy_morphoeUSD.ts'
)
} else if (chainId == '42161' || chainId == '421614') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async function main() {

// Only for Base
if (baseL2Chains.includes(hre.network.name)) {
const AerodromeStableCollateralFactory = await hre.ethers.getContractFactory(
const AerodromeVolatileCollateralFactory = await hre.ethers.getContractFactory(
'AerodromeVolatileCollateral'
)
const AerodromeGaugeWrapperFactory = await ethers.getContractFactory('AerodromeGaugeWrapper')
Expand All @@ -87,14 +87,14 @@ async function main() {
`Deployed wrapper for Aerodrome Volatile MOG-WETH pool on ${hre.network.name} (${chainId}): ${wMogWeth.address} `
)

const oracleError = combinedError(MOG_ORACLE_ERROR, ETH_ORACLE_ERROR) // 0.5% & 0.5%
const oracleError = combinedError(MOG_ORACLE_ERROR, ETH_ORACLE_ERROR) // 0.5% & 0.15%

collateral = <AerodromeVolatileCollateral>await AerodromeStableCollateralFactory.connect(
collateral = <AerodromeVolatileCollateral>await AerodromeVolatileCollateralFactory.connect(
deployer
).deploy(
{
erc20: wMogWeth.address,
targetName: ethers.utils.formatBytes32String('50%ETH50%MOG'), // lexicographical order for tokens
targetName: ethers.utils.formatBytes32String('MOG_ETH_AERODROME_cpAMM'),
priceTimeout: PRICE_TIMEOUT,
chainlinkFeed: ONE_ADDRESS, // unused but cannot be zero
oracleError: oracleError.toString(), // unused but cannot be zero
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async function main() {

// Only for Base
if (baseL2Chains.includes(hre.network.name)) {
const AerodromeStableCollateralFactory = await hre.ethers.getContractFactory(
const AerodromeVolatileCollateralFactory = await hre.ethers.getContractFactory(
'AerodromeVolatileCollateral'
)
const AerodromeGaugeWrapperFactory = await ethers.getContractFactory('AerodromeGaugeWrapper')
Expand All @@ -89,12 +89,12 @@ async function main() {

const oracleError = combinedError(AERO_ORACLE_ERROR, ETH_ORACLE_ERROR) // 0.5% & 0.15%

collateral = <AerodromeVolatileCollateral>await AerodromeStableCollateralFactory.connect(
collateral = <AerodromeVolatileCollateral>await AerodromeVolatileCollateralFactory.connect(
deployer
).deploy(
{
erc20: wWethAero.address,
targetName: ethers.utils.formatBytes32String('50%AERO50%ETH'), // lexicographical order for tokens
targetName: ethers.utils.formatBytes32String('ETH_AERO_AERODROME_cpAMM'),
priceTimeout: PRICE_TIMEOUT,
chainlinkFeed: ONE_ADDRESS, // unused but cannot be zero
oracleError: oracleError.toString(), // unused but cannot be zero
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import fs from 'fs'
import hre, { ethers } from 'hardhat'
import { getChainId } from '../../../../common/blockchain-utils'
import { baseL2Chains, networkConfig } from '../../../../common/configuration'
import { expect } from 'chai'
import { CollateralStatus, ONE_ADDRESS } from '../../../../common/constants'
import {
getDeploymentFile,
getAssetCollDeploymentFilename,
IAssetCollDeployments,
getDeploymentFilename,
fileExists,
} from '../../common'
import {
AerodromeVolatileCollateral,
AerodromeGaugeWrapper,
IAeroPool,
} from '../../../../typechain'
import { combinedError } from '../../utils'
import {
AerodromePoolType,
MAX_TRADE_VOL,
PRICE_TIMEOUT,
AERO_WETH_cbBTC_POOL,
AERO_WETH_cbBTC_GAUGE,
AERO,
cbBTC_USD_FEED,
cbBTC_ORACLE_TIMEOUT,
cbBTC_ORACLE_ERROR,
ETH_USD_FEED,
ETH_ORACLE_TIMEOUT,
ETH_ORACLE_ERROR,
} from '../../../../test/plugins/individual-collateral/aerodrome/constants'

// Aerodrome volatile plugin: WETH-cbBTCvAMM

async function main() {
// ==== Read Configuration ====
const [deployer] = await hre.ethers.getSigners()

const chainId = await getChainId(hre)

console.log(`Deploying Collateral to network ${hre.network.name} (${chainId})
with burner account: ${deployer.address}`)

if (!networkConfig[chainId]) {
throw new Error(`Missing network configuration for ${hre.network.name}`)
}

// Get phase1 deployment
const phase1File = getDeploymentFilename(chainId)
if (!fileExists(phase1File)) {
throw new Error(`${phase1File} doesn't exist yet. Run phase 1`)
}
// Check previous step completed
const assetCollDeploymentFilename = getAssetCollDeploymentFilename(chainId)
const assetCollDeployments = <IAssetCollDeployments>getDeploymentFile(assetCollDeploymentFilename)

const deployedCollateral: string[] = []

/******** Deploy Aerodrome Volatile Pool for WETH-cbBTC **************************/

let collateral: AerodromeVolatileCollateral
let wWethcbBTC: AerodromeGaugeWrapper

// Only for Base
if (baseL2Chains.includes(hre.network.name)) {
const AerodromeVolatileCollateralFactory = await hre.ethers.getContractFactory(
'AerodromeVolatileCollateral'
)
const AerodromeGaugeWrapperFactory = await ethers.getContractFactory('AerodromeGaugeWrapper')

// Deploy gauge wrapper
const pool = <IAeroPool>await ethers.getContractAt('IAeroPool', AERO_WETH_cbBTC_POOL)
wWethcbBTC = <AerodromeGaugeWrapper>(
await AerodromeGaugeWrapperFactory.deploy(
pool.address,
'w' + (await pool.name()),
'w' + (await pool.symbol()),
AERO,
AERO_WETH_cbBTC_GAUGE
)
)
await wWethcbBTC.deployed()

console.log(
`Deployed wrapper for Aerodrome Volatile WETH-cbBTC pool on ${hre.network.name} (${chainId}): ${wWethcbBTC.address} `
)

const oracleError = combinedError(cbBTC_ORACLE_ERROR, ETH_ORACLE_ERROR) // 0.3% & 0.15%

collateral = <AerodromeVolatileCollateral>await AerodromeVolatileCollateralFactory.connect(
deployer
).deploy(
{
erc20: wWethcbBTC.address,
targetName: ethers.utils.formatBytes32String('ETH_BTC_AERODROME_cpAMM'),
priceTimeout: PRICE_TIMEOUT,
chainlinkFeed: ONE_ADDRESS, // unused but cannot be zero
oracleError: oracleError.toString(), // unused but cannot be zero
oracleTimeout: ETH_ORACLE_TIMEOUT, // max of oracleTimeouts
maxTradeVolume: MAX_TRADE_VOL,
defaultThreshold: '0',
delayUntilDefault: '86400', // 24h
},
{
pool: AERO_WETH_cbBTC_POOL,
poolType: AerodromePoolType.Volatile,
feeds: [[ETH_USD_FEED], [cbBTC_USD_FEED]],
oracleTimeouts: [[ETH_ORACLE_TIMEOUT], [cbBTC_ORACLE_TIMEOUT]],
oracleErrors: [[ETH_ORACLE_ERROR], [cbBTC_ORACLE_ERROR]],
}
)
} else {
throw new Error(`Unsupported chainId: ${chainId}`)
}

await collateral.deployed()
await (await collateral.refresh()).wait()
expect(await collateral.status()).to.equal(CollateralStatus.SOUND)

console.log(
`Deployed Aerodrome Volatile Collateral for WETH-cbBTC to ${hre.network.name} (${chainId}): ${collateral.address}`
)

assetCollDeployments.collateral.aeroWETHcbBTC = collateral.address
assetCollDeployments.erc20s.aeroWETHcbBTC = wWethcbBTC.address
deployedCollateral.push(collateral.address.toString())

fs.writeFileSync(assetCollDeploymentFilename, JSON.stringify(assetCollDeployments, null, 2))

console.log(`Deployed collateral to ${hre.network.name} (${chainId})
New deployments: ${deployedCollateral}
Deployment file: ${assetCollDeploymentFilename}`)
}

main().catch((error) => {
console.error(error)
process.exitCode = 1
})
Loading
Loading