Skip to content

Commit

Permalink
Config for deployed vaults (#59)
Browse files Browse the repository at this point in the history
* Vault deployment (#58)
* chore: added config for new vaults on mainnet
* chore: more Hardhat task refactoring
* chore: Hardhat tasks to snap basic vault and convex meta vault details
* chore: bump package version
  • Loading branch information
naddison36 authored Oct 21, 2022
1 parent f3e5b18 commit 79f09a1
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ abstract contract SameAssetUnderlyingsAbstractVault is AbstractVault {
vaultIndexMap = vaultIndexMapMem;
}

// 0000001011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100010000

/**
* @notice Includes all the assets in this vault plus all the underlying vaults.
* The amount of assets in each underlying vault is calculated using the vault's share of the
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mstable/metavaults",
"version": "0.0.2",
"version": "0.0.3",
"description": "mStable EIP-4626 Tokenized Vaults",
"author": "mStable <info@mstable.org>",
"license": "AGPL-3.0-or-later",
Expand Down
125 changes: 113 additions & 12 deletions tasks/convex3CrvMetaVault.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { simpleToExactAmount } from "@utils/math"
import { formatUnits } from "ethers/lib/utils"
import { subtask, task, types } from "hardhat/config"
import { AssetProxy__factory, PeriodicAllocationPerfFeeMetaVault__factory } from "types/generated"
import { AssetProxy__factory, IERC20__factory, PeriodicAllocationPerfFeeMetaVault__factory } from "types/generated"

import { config } from "./deployment/convex3CrvVaults-config"
import { usdFormatter } from "./utils"
import { getBlock } from "./utils/blocks"
import { deployContract } from "./utils/deploy-utils"
import { verifyEtherscan } from "./utils/etherscan"
import { getChain, resolveAddress, resolveToken } from "./utils/networkAddressFactory"
Expand Down Expand Up @@ -106,16 +109,10 @@ export const deployPeriodicAllocationPerfFeeMetaVault = async (
const proxyConstructorArguments = [vaultImpl.address, proxyAdmin, data]
const proxy = await deployContract<AssetProxy>(new AssetProxy__factory(signer), "AssetProxy", proxyConstructorArguments)

await verifyEtherscan(hre, {
address: proxy.address,
contract: "contracts/upgradability/Proxies.sol:AssetProxy",
constructorArguments: proxyConstructorArguments,
})

return { proxy, impl: vaultImpl }
}

subtask("convex-3crv-meta-vault-deploy", "Deploys Convex 3Crv Meta Vault")
subtask("convex-3crv-mv-deploy", "Deploys Convex 3Crv Meta Vault")
.addParam("vaults", "Comma separated symbols or addresses of the underlying convex vaults", undefined, types.string)
.addParam(
"singleSource",
Expand All @@ -124,7 +121,7 @@ subtask("convex-3crv-meta-vault-deploy", "Deploys Convex 3Crv Meta Vault")
types.string,
)
.addOptionalParam("name", "Vault name", "3CRV Convex Meta Vault", types.string)
.addOptionalParam("symbol", "Vault symbol", "mv3CRV", types.string)
.addOptionalParam("symbol", "Vault symbol", "mv3CRV-CVX", types.string)
.addOptionalParam("asset", "Token address or symbol of the vault's asset", "3Crv", types.string)
.addOptionalParam("admin", "Instant or delayed proxy admin: InstantProxyAdmin | DelayedProxyAdmin", "InstantProxyAdmin", types.string)
.addOptionalParam("feeReceiver", "Address or name of account that will receive vault fees.", "mStableDAO", types.string)
Expand All @@ -136,17 +133,31 @@ subtask("convex-3crv-meta-vault-deploy", "Deploys Convex 3Crv Meta Vault")
types.int,
)
.addOptionalParam("updateThreshold", "Asset per share update threshold. default 100k", 100000, types.int)
.addOptionalParam("vaultManager", "Name or address to override the Vault Manager", "VaultManager", types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string)
.setAction(async (taskArgs, hre) => {
const { name, symbol, asset, vaults, admin, feeReceiver, fee, singleSource, singleThreshold, updateThreshold, speed } = taskArgs
const {
name,
symbol,
asset,
vaults,
admin,
feeReceiver,
fee,
singleSource,
singleThreshold,
updateThreshold,
vaultManager,
speed,
} = taskArgs

const signer = await getSigner(hre, speed)
const chain = getChain(hre)

const nexusAddress = resolveAddress("Nexus", chain)
const assetToken = resolveToken(asset, chain)
const proxyAdminAddress = resolveAddress(admin, chain)
const vaultManagerAddress = resolveAddress("VaultManager", chain)
const vaultManagerAddress = resolveAddress(vaultManager, chain)

const underlyings = vaults.split(",")
const underlyingAddresses = underlyings.map((underlying) => resolveAddress(underlying, chain))
Expand Down Expand Up @@ -174,6 +185,96 @@ subtask("convex-3crv-meta-vault-deploy", "Deploys Convex 3Crv Meta Vault")

return { proxy, impl }
})
task("convex-3crv-meta-vault-deploy").setAction(async (_, __, runSuper) => {
task("convex-3crv-mv-deploy").setAction(async (_, __, runSuper) => {
return runSuper()
})

subtask("convex-3crv-mv-snap", "Logs Convex 3Crv Meta Vault details")
.addParam("vault", "Vault symbol or address", undefined, types.string)
.addOptionalParam("owner", "Address, contract name or token symbol to get balances for. Defaults to signer", undefined, types.string)
.addOptionalParam("block", "Block number. (default: current block)", 0, types.int)
.setAction(async (taskArgs, hre) => {
const { vault, owner, block, speed } = taskArgs

const signer = await getSigner(hre, speed)
const chain = getChain(hre)

const blk = await getBlock(hre.ethers, block)

const vaultToken = resolveToken(vault, chain)
const vaultContract = PeriodicAllocationPerfFeeMetaVault__factory.connect(vaultToken.address, signer)
const assetToken = resolveToken(vaultToken.assetSymbol, chain)
const assetContract = IERC20__factory.connect(assetToken.address, signer)

await hre.run("vault-snap", {
vault,
owner,
})

console.log(`\nPeriodicAllocationPerfFeeMetaVault`)
const assetsInVault = await assetContract.balanceOf(vaultToken.address, {
blockTag: blk.blockNumber,
})
const totalAssets = await vaultContract.totalAssets({
blockTag: blk.blockNumber,
})
console.log(
`Assets in vault : ${usdFormatter(assetsInVault, assetToken.decimals)} ${formatUnits(
assetsInVault.mul(10000).div(totalAssets),
2,
)}%`,
)
const assetsInUnderlyings = totalAssets.sub(assetsInVault)
console.log(
`Assets in underlyings : ${usdFormatter(assetsInUnderlyings, assetToken.decimals)} ${formatUnits(
assetsInUnderlyings.mul(10000).div(totalAssets),
2,
)}%`,
)
console.log(
`stored assets/share : ${formatUnits(
await vaultContract.assetsPerShare({
blockTag: blk.blockNumber,
}),
26,
)}`,
)
const current = await vaultContract.calculateAssetPerShare({
blockTag: blk.blockNumber,
})
console.log(`current assets/share : ${formatUnits(current.assetsPerShare_, 26)}`)
const fee = await vaultContract.performanceFee({
blockTag: blk.blockNumber,
})
console.log(`Performance fee : ${fee.toNumber() / 10000}%`)
console.log(
`Fee receiver : ${await vaultContract.feeReceiver({
blockTag: blk.blockNumber,
})}`,
)
console.log(
`Active underlying vaults: ${await vaultContract.activeUnderlyingVaults({
blockTag: blk.blockNumber,
})}`,
)
console.log(
`Total underlying vaults : ${await vaultContract.totalUnderlyingVaults({
blockTag: blk.blockNumber,
})}`,
)
const sourceParams = await vaultContract.sourceParams()
console.log(`Single vault threshold : ${sourceParams.singleVaultSharesThreshold / 100}%`)
console.log(
`Vault Manager : ${await vaultContract.vaultManager({
blockTag: blk.blockNumber,
})}`,
)
console.log(
`Paused : ${await vaultContract.paused({
blockTag: blk.blockNumber,
})}`,
)
})
task("convex-3crv-mv-snap").setAction(async (_, __, runSuper) => {
return runSuper()
})
27 changes: 19 additions & 8 deletions tasks/convex3CrvVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,13 @@ export async function deployConvex3CrvLiquidatorVault(
`Convex3CrvLiquidatorVault ${name} (${symbol})`,
constructorArguments,
)

await verifyEtherscan(hre, {
address: vaultImpl.address,
contract: "contracts/vault/liquidity/convex/Convex3CrvLiquidatorVault.sol:Convex3CrvLiquidatorVault",
constructorArguments: constructorArguments,
})

// Proxy
const data = vaultImpl.interface.encodeFunctionData("initialize", [
name,
Expand All @@ -168,12 +170,6 @@ export async function deployConvex3CrvLiquidatorVault(
const proxyConstructorArguments = [vaultImpl.address, proxyAdmin, data]
const proxy = await deployContract<AssetProxy>(new AssetProxy__factory(signer), "AssetProxy", proxyConstructorArguments)

await verifyEtherscan(hre, {
address: proxy.address,
contract: "contracts/upgradability/Proxies.sol:AssetProxy",
constructorArguments: proxyConstructorArguments,
})

return { proxy, impl: vaultImpl }
}

Expand Down Expand Up @@ -210,17 +206,32 @@ subtask("convex-3crv-vault-deploy", "Deploys Convex 3Crv Liquidator Vault")
.addOptionalParam("donateToken", "Address or token symbol of token that rewards will be swapped to.", "DAI", types.string)
.addOptionalParam("fee", "Liquidation fee scaled to 6 decimal places. default 16% = 160000", 160000, types.int)
.addOptionalParam("feeReceiver", "Address or name of account that will receive vault fees.", "mStableDAO", types.string)
.addOptionalParam("vaultManager", "Name or address to override the Vault Manager", "VaultManager", types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string)
.setAction(async (taskArgs, hre) => {
const { name, symbol, pool, asset, stream, admin, calculatorLibrary, slippage, donateToken, fee, feeReceiver, speed } = taskArgs
const {
name,
symbol,
pool,
asset,
stream,
admin,
calculatorLibrary,
slippage,
donateToken,
fee,
feeReceiver,
vaultManager,
speed,
} = taskArgs

const signer = await getSigner(hre, speed)
const chain = getChain(hre)

const nexusAddress = resolveAddress("Nexus", chain)
const assetAddress = resolveAddress(asset, chain)
const proxyAdminAddress = resolveAddress(admin, chain)
const vaultManagerAddress = resolveAddress("VaultManager", chain)
const vaultManagerAddress = resolveAddress(vaultManager, chain)
const convexBoosterAddress = resolveAddress("ConvexBooster", chain)

const convex3CrvPool = config.convex3CrvPools[pool.toLowerCase()]
Expand Down
46 changes: 44 additions & 2 deletions tasks/curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ICurve3Pool__factory, IERC20__factory } from "types/generated"

import { logTxDetails } from "./utils/deploy-utils"
import { logger } from "./utils/logger"
import { getChain, resolveAddress } from "./utils/networkAddressFactory"
import { getChain, resolveAddress, resolveToken } from "./utils/networkAddressFactory"
import { getSigner } from "./utils/signerFactory"
import { DAI, ThreeCRV, USDC, USDT } from "./utils/tokens"

Expand All @@ -15,7 +15,7 @@ subtask("curve-add", "Add liquidity to Curve 3Pool")
.addOptionalParam("dai", "Amount of DAI to add", 0, types.int)
.addOptionalParam("usdc", "Amount of USDC to add", 0, types.int)
.addOptionalParam("usdt", "Amount of USDT to add", 0, types.int)
.addOptionalParam("slippage", "Max allowed slippage as a percentage to 2 decimal places.", 1, types.float)
.addOptionalParam("slippage", "Max allowed slippage as a percentage to 2 decimal places.", 1.0, types.float)
.addOptionalParam("pool", "Name or address of the Curve pool", "CurveThreePool", types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string)
.setAction(async (taskArgs, hre) => {
Expand Down Expand Up @@ -52,3 +52,45 @@ subtask("curve-add", "Add liquidity to Curve 3Pool")
task("curve-add").setAction(async (_, __, runSuper) => {
await runSuper()
})

subtask("curve-swap", "Swap tokens using Curve 3Pool")
.addParam("amount", "Amount to swap from", undefined, types.int)
.addParam("from", "Token symbol or address that is being swapped from", undefined, types.string)
.addParam("to", "Token symbol or address that is being swapped to", undefined, types.string)
.addOptionalParam("slippage", "Max allowed slippage as a percentage to 2 decimal places.", 1.0, types.float)
.addOptionalParam("pool", "Name or address of the Curve pool", "CurveThreePool", types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string)
.setAction(async (taskArgs, hre) => {
const { amount, from, to, pool, slippage, speed } = taskArgs
const chain = getChain(hre)
const signer = await getSigner(hre, speed)

const poolAddress = resolveAddress(pool, chain)
const poolContract = ICurve3Pool__factory.connect(poolAddress, signer)

const fromToken = resolveToken(from, chain)
const fromAmount = simpleToExactAmount(amount, fromToken.decimals)
const toToken = resolveToken(to, chain)

const indexes = {
[DAI.address]: 0,
[USDC.address]: 1,
[USDT.address]: 2,
}

const fromIndex = indexes[fromToken.address]
const toIndex = indexes[toToken.address]

const fairAmount = await poolContract.get_dy(fromIndex, toIndex, fromAmount)
log(`Fair swap of ${amount} ${fromToken.symbol} to ${toToken.symbol} is ${formatUnits(fairAmount, toToken.decimals)}`)
const slippageScaled = slippage * 100
const minAmount = fairAmount.mul(10000 - slippageScaled).div(10000)

const tx = await poolContract.exchange(fromIndex, toIndex, fromAmount, minAmount)

await logTxDetails(tx, `Swap ${amount} ${fromToken.symbol} to ${toToken.symbol} using pool ${pool.address}`)
})

task("curve-swap").setAction(async (_, __, runSuper) => {
await runSuper()
})
15 changes: 5 additions & 10 deletions tasks/curve3CrvVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,6 @@ export const deployCurve3CrvMetaVault = async (hre: HardhatRuntimeEnvironment, s
const proxyConstructorArguments = [vaultImpl.address, proxyAdmin, data]
const proxy = await deployContract<AssetProxy>(new AssetProxy__factory(signer), "AssetProxy", proxyConstructorArguments)

await verifyEtherscan(hre, {
address: proxy.address,
contract: "contracts/upgradability/Proxies.sol:AssetProxy",
constructorArguments: proxyConstructorArguments,
})

return { proxy, impl: vaultImpl }
}

Expand Down Expand Up @@ -130,25 +124,26 @@ task("curve-3crv-lib-deploy").setAction(async (_, __, runSuper) => {
return runSuper()
})

subtask("curve-3crv-meta-vault-deploy", "Deploys Curve 3Crv Meta Vault")
.addParam("metaVault", "Underlying Meta Vault override", "mv3CRV", types.string)
subtask("curve-3crv-meta-vault-deploy", "Deploys Curve 3Pool Meta Vault")
.addParam("name", "Meta Vault name", undefined, types.string)
.addParam("symbol", "Meta Vault symbol", undefined, types.string)
.addParam("asset", "Token address or symbol of the vault's asset. eg DAI, USDC or USDT", undefined, types.string)
.addOptionalParam("metaVault", "Underlying Meta Vault override", "mv3CRV-CVX", types.string)
.addOptionalParam("admin", "Instant or delayed proxy admin: InstantProxyAdmin | DelayedProxyAdmin", "InstantProxyAdmin", types.string)
.addOptionalParam("calculatorLibrary", "Name or address of the Curve calculator library.", "Curve3CrvCalculatorLibrary", types.string)
.addOptionalParam("slippage", "Max slippage in basis points. default 1% = 100", 100, types.int)
.addOptionalParam("vaultManager", "Name or address to override the Vault Manager", "VaultManager", types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", types.string)
.setAction(async (taskArgs, hre) => {
const { metaVault, name, symbol, asset, calculatorLibrary, slippage, admin, speed } = taskArgs
const { metaVault, name, symbol, asset, calculatorLibrary, slippage, admin, vaultManager, speed } = taskArgs

const signer = await getSigner(hre, speed)
const chain = getChain(hre)

const nexusAddress = resolveAddress("Nexus", chain)
const assetToken = resolveToken(asset, chain)
const proxyAdminAddress = resolveAddress(admin, chain)
const vaultManagerAddress = resolveAddress("VaultManager", chain)
const vaultManagerAddress = resolveAddress(vaultManager, chain)
const metaVaultAddress = resolveAddress(metaVault, chain)
const calculatorLibraryAddress = resolveAddress(calculatorLibrary, chain)

Expand Down
8 changes: 4 additions & 4 deletions tasks/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ task("token-transfer-from").setAction(async (_, __, runSuper) => {

subtask("token-allowance", "Logs the amount of tokens a spender can transfer from an owner")
.addParam("token", "Token symbol or address. eg mUSD, MTA, BUSD, 3Crv, mvDAI-3PCV or vcx3CRV-FRAX", undefined, types.string)
.addParam("owner", "Address or contract name where the tokens are held.", undefined, types.string)
.addParam("spender", "Address or contract name that can transferFrom.", undefined, types.string)
.addOptionalParam("owner", "Address or contract name where the tokens are held.", undefined, types.string)
.setAction(async (taskArgs, hre) => {
const { owner, spender, token } = taskArgs
const chain = getChain(hre)
Expand All @@ -114,7 +114,7 @@ subtask("token-allowance", "Logs the amount of tokens a spender can transfer fro
const tokenConfig = resolveToken(token, chain)
const tokenContract = ERC20__factory.connect(tokenConfig.address, signer)

const ownerAddress = resolveAddress(owner, chain)
const ownerAddress = owner ? resolveAddress(owner, chain) : await signer.getAddress()
const spenderAddress = resolveAddress(spender, chain)

const amount = await tokenContract.allowance(ownerAddress, spenderAddress)
Expand All @@ -131,7 +131,7 @@ task("token-allowance").setAction(async (_, __, runSuper) => {

subtask("token-balance", "Logs the token balance of an owner")
.addParam("token", "Token symbol or address. eg mUSD, MTA, BUSD, 3Crv, mvDAI-3PCV or vcx3CRV-FRAX", undefined, types.string)
.addParam("owner", "Address or contract name where the tokens are held.", undefined, types.string)
.addOptionalParam("owner", "Address or contract name where the tokens are held.", undefined, types.string)
.setAction(async (taskArgs, hre) => {
const { owner, token } = taskArgs
const chain = getChain(hre)
Expand All @@ -140,7 +140,7 @@ subtask("token-balance", "Logs the token balance of an owner")
const tokenConfig = resolveToken(token, chain)
const tokenContract = ERC20__factory.connect(tokenConfig.address, signer)

const ownerAddress = resolveAddress(owner, chain)
const ownerAddress = owner ? resolveAddress(owner, chain) : await signer.getAddress()

const amount = await tokenContract.balanceOf(ownerAddress)

Expand Down
Loading

0 comments on commit 79f09a1

Please sign in to comment.