From b23e9002a8bb7abd0ad9b5e1497c109b9805cd40 Mon Sep 17 00:00:00 2001 From: Dimitri <69167058+dimsome@users.noreply.github.com> Date: Tue, 2 Nov 2021 21:25:07 +0700 Subject: [PATCH] feat: add NonPeggedFeederPool deploy task (#262) feat: add NonPeggedFeederPool deploy task --- .../peripheral/RAI/IRedemptionPriceSnap.sol | 23 ++++++++++ tasks/deployFeeders.ts | 43 +++++++++++++++++++ tasks/deployIntegration.ts | 30 +++++++++---- tasks/utils/feederUtils.ts | 18 +++++++- tasks/utils/tokens.ts | 28 ++++++++++++ 5 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 contracts/peripheral/RAI/IRedemptionPriceSnap.sol diff --git a/contracts/peripheral/RAI/IRedemptionPriceSnap.sol b/contracts/peripheral/RAI/IRedemptionPriceSnap.sol new file mode 100644 index 00000000..58dc5474 --- /dev/null +++ b/contracts/peripheral/RAI/IRedemptionPriceSnap.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.8.6; +pragma experimental ABIEncoderV2; + +interface IRedemptionPriceSnap { + function TEN_THOUSAND() external view returns (uint256); + + function addAuthorization(address account) external; + + function authorizedAccounts(address) external view returns (uint256); + + function modifyParameters(bytes32 parameter, address data) external; + + function oracleRelayer() external view returns (address); + + function removeAuthorization(address account) external; + + function snappedRedemptionPrice() external view returns (uint256); + + function updateAndGetSnappedPrice() external returns (uint256); + + function updateSnappedPrice() external; +} diff --git a/tasks/deployFeeders.ts b/tasks/deployFeeders.ts index ea7eda0d..e41a6cb9 100644 --- a/tasks/deployFeeders.ts +++ b/tasks/deployFeeders.ts @@ -55,6 +55,46 @@ task("deployFeederPool", "Deploy Feeder Pool") await deployFeederPool(signer, poolData, hre) }) +// hh --config tasks-fork.config.ts --network hardhat deployNonPeggedFeederPool --masset mUSD --fasset RAI +task("deployNonPeggedFeederPool", "Deploy Non Pegged Feeder Pool") + .addParam("masset", "Token symbol of mAsset. eg mUSD or PmUSD for Polygon", "mUSD", types.string) + .addParam("fasset", "Token symbol of Feeder Pool asset. eg GUSD, WBTC, PFRAX for Polygon", "alUSD", types.string) + .addOptionalParam("a", "Amplitude coefficient (A)", 100, types.int) + .addOptionalParam("min", "Minimum asset weight of the basket as a percentage. eg 10 for 10% of the basket.", 10, types.int) + .addOptionalParam("max", "Maximum asset weight of the basket as a percentage. eg 90 for 90% of the basket.", 90, types.int) + .addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string) + .setAction(async (taskArgs, hre) => { + const signer = await getSigner(hre, taskArgs.speed) + const chain = getChain(hre) + + const mAsset = resolveToken(taskArgs.masset, chain) + const fAsset = resolveToken(taskArgs.fasset, chain) + + if (taskArgs.a < 10 || taskArgs.min > 5000) throw Error(`Invalid amplitude coefficient (A) ${taskArgs.a}`) + if (taskArgs.min < 0 || taskArgs.min > 50) throw Error(`Invalid min limit ${taskArgs.min}`) + if (taskArgs.max < 50 || taskArgs.max > 100) throw Error(`Invalid max limit ${taskArgs.min}`) + + if (!fAsset.priceGetter) throw Error(`Token ${fAsset.symbol} does not have a priceGetter`) + + const poolData: FeederData = { + mAsset, + fAsset, + fAssetRedemptionPriceGetter: fAsset.priceGetter, + name: `${mAsset.symbol}/${fAsset.symbol} Feeder Pool`, + symbol: `fP${mAsset.symbol}/${fAsset.symbol}`, + config: { + a: taskArgs.a, + limits: { + min: simpleToExactAmount(taskArgs.min, 16), + max: simpleToExactAmount(taskArgs.max, 16), + }, + }, + } + + // Deploy Feeder Pool + await deployFeederPool(signer, poolData, hre) + }) + task("deployAlcxInt", "Deploy Alchemix integration contract for alUSD Feeder Pool") .addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string) .setAction(async (taskArgs, hre) => { @@ -78,6 +118,9 @@ task("deployAlcxInt", "Deploy Alchemix integration contract for alUSD Feeder Poo console.log(`migrateBassets data:\n${migrateData}`) }) +// vault: +// // hh --config tasks-fork.config.ts --network hardhat deployVault --name "mUSD/RAI fPool Vault" --symbol v-fPmUSD/RAI +// --boosted true --stakingToken mUSD --rewardToken MTA --dualRewardToken FLX --price ? task("deployVault", "Deploy Feeder Pool with boosted dual vault") .addParam("name", "Token name of the vault. eg mUSD/alUSD fPool Vault", undefined, types.string) .addParam("symbol", "Token symbol of the vault. eg v-fPmUSD/alUSD", undefined, types.string) diff --git a/tasks/deployIntegration.ts b/tasks/deployIntegration.ts index dd7d36f1..b5bcd733 100644 --- a/tasks/deployIntegration.ts +++ b/tasks/deployIntegration.ts @@ -4,11 +4,13 @@ import "tsconfig-paths/register" import { subtask, task, types } from "hardhat/config" import { + AaveV2Integration, AaveV2Integration__factory, DelayedProxyAdmin__factory, Liquidator, Liquidator__factory, Masset__factory, + FeederPool__factory, PAaveIntegration, PAaveIntegration__factory, } from "types/generated" @@ -17,7 +19,7 @@ import { encodeUniswapPath } from "@utils/peripheral/uniswap" import { ZERO_ADDRESS } from "@utils/constants" import { deployContract, logTxDetails } from "./utils/deploy-utils" import { AAVE, ALCX, Chain, COMP, DAI, stkAAVE, tokens } from "./utils/tokens" -import { getChain, getChainAddress, resolveAddress } from "./utils/networkAddressFactory" +import { getChain, getChainAddress, resolveAddress, resolveToken } from "./utils/networkAddressFactory" import { getSigner } from "./utils/signerFactory" import { verifyEtherscan } from "./utils/etherscan" @@ -37,16 +39,28 @@ task("integration-aave-deploy", "Deploys an instance of AaveV2Integration contra const nexusAddress = getChainAddress("Nexus", chain) const platformAddress = getChainAddress("AaveLendingPoolAddressProvider", chain) + const bAsset = resolveToken(taskArgs.asset, chain) + if (!bAsset.liquidityProvider) throw Error(`No aToken address provided for token: ${taskArgs.asset}`) + const liquidityProviderAddress = resolveAddress(taskArgs.asset, chain) const rewardsTokenAddress = resolveAddress(taskArgs.rewards, chain) + const constructorArguments = [nexusAddress, liquidityProviderAddress, platformAddress, rewardsTokenAddress] + // Deploy - await deployContract(new AaveV2Integration__factory(signer), "AaveV2Integration", [ - nexusAddress, - liquidityProviderAddress, - platformAddress, - rewardsTokenAddress, - ]) + const integration = await deployContract( + new AaveV2Integration__factory(signer), + "AaveV2Integration", + constructorArguments, + ) + + const tx = await integration.initialize([bAsset.address], [bAsset.liquidityProvider]) + await logTxDetails(tx, "AaveIntegrationV2.initialize") + + await verifyEtherscan(hre, { + address: integration.address, + constructorArguments, + }) }) task("integration-paave-deploy", "Deploys mUSD and mBTC instances of PAaveIntegration") @@ -87,7 +101,7 @@ task("integration-paave-deploy", "Deploys mUSD and mBTC instances of PAaveIntegr const approveRewardTokenData = integration.interface.encodeFunctionData("approveRewardToken") console.log(`\napproveRewardToken data: ${approveRewardTokenData}`) - const mAsset = await Masset__factory.connect(liquidityProviderAddress, deployer) + const mAsset = Masset__factory.connect(liquidityProviderAddress, deployer) for (const bAsset of bAssets) { const migrateData = mAsset.interface.encodeFunctionData("migrateBassets", [[bAsset.address], integration.address]) diff --git a/tasks/utils/feederUtils.ts b/tasks/utils/feederUtils.ts index cc4d89fb..3e9e0f94 100644 --- a/tasks/utils/feederUtils.ts +++ b/tasks/utils/feederUtils.ts @@ -7,12 +7,14 @@ import { formatEther } from "ethers/lib/utils" import { HardhatRuntimeEnvironment } from "hardhat/types/runtime" import { FeederPool, + NonPeggedFeederPool, BoostedVault, MockERC20__factory, MockInitializableToken__factory, AssetProxy__factory, MockERC20, FeederPool__factory, + NonPeggedFeederPool__factory, BoostedVault__factory, Masset__factory, BoostedDualVault, @@ -21,6 +23,7 @@ import { BoostedDualVault__factory, StakingRewardsWithPlatformToken__factory, StakingRewards__factory, + IRedemptionPriceSnap__factory, } from "types/generated" import { deployContract } from "./deploy-utils" import { verifyEtherscan } from "./etherscan" @@ -39,6 +42,7 @@ interface Config { export interface FeederData { mAsset: Token fAsset: Token + fAssetRedemptionPriceGetter?: string name: string symbol: string config: Config @@ -85,8 +89,18 @@ export const deployFeederPool = async (signer: Signer, feederData: FeederData, h "contracts/feeders/FeederManager.sol:FeederManager": feederManagerAddress, } - const fpConstructorArgs = [getChainAddress("Nexus", chain), feederData.mAsset.address] - const impl = await deployContract(new FeederPool__factory(linkedAddress, signer), "FeederPool", fpConstructorArgs) + let impl: FeederPool | NonPeggedFeederPool + let fpConstructorArgs: Array + + if (feederData.fAssetRedemptionPriceGetter) { + // Update fAssetRedemptionPriceGetter price oracle + await IRedemptionPriceSnap__factory.connect(feederData.fAssetRedemptionPriceGetter, signer).updateSnappedPrice() + fpConstructorArgs = [getChainAddress("Nexus", chain), feederData.mAsset.address, feederData.fAssetRedemptionPriceGetter] + impl = await deployContract(new NonPeggedFeederPool__factory(linkedAddress, signer), "NonPeggedFeederPool", fpConstructorArgs) + } else { + fpConstructorArgs = [getChainAddress("Nexus", chain), feederData.mAsset.address] + impl = await deployContract(new FeederPool__factory(linkedAddress, signer), "FeederPool", fpConstructorArgs) + } await verifyEtherscan(hre, { address: impl.address, diff --git a/tasks/utils/tokens.ts b/tasks/utils/tokens.ts index feeb901f..d5976845 100644 --- a/tasks/utils/tokens.ts +++ b/tasks/utils/tokens.ts @@ -25,6 +25,7 @@ export interface Token { vault?: string savings?: string // interest-bearing savings contracts platformTokenVendor?: string // hold WMATIC on Polygon's v-imUSD vault + priceGetter?: string // Contract for price of asset, used for NonPeggedFeederPool } export function isToken(asset: unknown): asset is Token { @@ -209,6 +210,31 @@ export const BUSD: Token = { vault: "0xD124B55f70D374F58455c8AEdf308E52Cf2A6207", } +// NonPeggedFeederPool contains priceGetter +export const RAI: Token = { + symbol: "RAI", + address: "0x03ab458634910aad20ef5f1c8ee96f1d6ac54919", + chain: Chain.mainnet, + platform: Platform.Aave, + integrator: "", + liquidityProvider: "0xc9bc48c72154ef3e5425641a3c747242112a46af", // aRAI, + decimals: 18, + quantityFormatter: "USD", + parent: "mUSD", + feederPool: "", + vault: "", + priceGetter: "0x07210B8871073228626AB79c296d9b22238f63cE", +} + +// FLX token for RAI +export const FLX: Token = { + symbol: "FLX", + address: "0x6243d8cea23066d098a15582d81a598b4e8391f4", + chain: Chain.mainnet, + decimals: 18, + quantityFormatter: "USD", +} + // USD Feeder Pool Assets on Mainnet export const FRAX: Token = { symbol: "FRAX", @@ -452,6 +478,8 @@ export const tokens = [ DAI, GUSD, BUSD, + RAI, + FLX, renBTC, sBTC, WBTC,