On Mainnet. Activate the FRAX Sept 2023 series. Migrate the funds in March-September 6M strategies from v1 to v2. Invest the March-September 6M strategies in the Sept 2023 series.
On Arbitrum. Roll the USDT March 2023 Series. Migrate the funds in March-September 6M strategies from v1 to v2. Invest the March-September 6M strategies in the Sept 2023 series.
The Strategy v2 contracts simplify the rolling process and include emergency mechanisms to exit an investment before maturity. The rest of the rolling operation is as usual.
The steps are:
- Deploy new FYTokens and Non-tv pools.
- Deploy new Strategies.
- Governance proposal i. Orchestrate contracts ii. Add new series iii. Add all ilks to the new series iv. Migrate the funds from v1 strategies to v2 strategies v. Invest the funds in the v2 strategies in the Sept 2023 series
Scripts for mainnet deployment & activation and with config for deployment & migration.
Scripts for arbitrum:
import { BigNumber } from 'ethers'
import { ONE64, secondsInOneYear } from '../../../../shared/constants'
import { ETH, DAI, USDC, FRAX, EWETH, EDAI, EUSDC } from '../../../../shared/constants'
import { EOSEP23 } from '../../../../shared/constants'
import { FYETH2309, FYDAI2309, FYUSDC2309, FYFRAX2309 } from '../../../../shared/constants'
import { YSETH6MMS, YSDAI6MMS, YSUSDC6MMS, YSFRAX6MMS } from '../../../../shared/constants'
import { SAFE_ERC20_NAMER, YIELDMATH, ACCUMULATOR, COMPOUND, EULER } from '../../../../shared/constants'
import { ContractDeployment } from '../../confTypes' // Note we use the series id as the asset id
import { readAddressMappingIfExists } from '../../../../shared/helpers'
import * as base_config from '../../base.mainnet.config'
export const chainId: number = base_config.chainId
export const developer: string = '0xC7aE076086623ecEA2450e364C838916a043F9a8'
export const whales: Map<string, string> = base_config.whales
export const external: Map<string, string> = base_config.external
export const governance: Map<string, string> = base_config.governance
export const protocol: Map<string, string> = base_config.protocol
export const assets: Map<string, string> = base_config.assets
export const joins: Map<string, string> = base_config.joins
export const fyTokens = () => readAddressMappingIfExists('fyTokens.json')
export const pools = () => readAddressMappingIfExists('pools.json')
export const strategies = () => readAddressMappingIfExists('strategies.json')
/// @notice Time stretch to be set in the PoolFactory prior to pool deployment
/// @param series identifier (bytes6 tag)
/// @param time stretch (64.64)
export const timeStretch: Map<string, BigNumber> = new Map([[FYFRAX2309, ONE64.div(secondsInOneYear.mul(45))]])
/// @notice Sell base to the pool fee, as fp4
export const g1: number = 9000
// ----- deployment parameters -----
export const contractDeployments: ContractDeployment[] = [
/// @notice Deploy fyToken series
/// @param underlying identifier (bytes6 tag)
/// @param Address for the chi oracle
/// @param Address for the related Join
/// @param Maturity in unix time (seconds since Jan 1, 1970)
/// @param Name for the series
/// @param Symbol for the series
{
addressFile: 'fyTokens.json',
name: FYFRAX2309,
contract: 'FYToken',
args: [
() => FRAX,
() => protocol.getOrThrow(ACCUMULATOR),
() => joins.getOrThrow(FRAX),
() => EOSEP23,
() => 'FYFRAX2309',
() => 'FYFRAX2309',
],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
/// @notice Deploy plain YieldSpace pools
/// @param pool identifier, usually matching the series (bytes6 tag)
/// @param base address
/// @param fyToken address
/// @param time stretch, in 64.64
/// @param g1, in 64.64
{
addressFile: 'pools.json',
name: FYFRAX2309,
contract: 'PoolNonTv',
args: [
() => assets.getOrThrow(FRAX)!,
() => fyTokens().getOrThrow(FYFRAX2309)!,
() => timeStretch.get(FYFRAX2309)!.toString(),
() => g1.toString(),
],
libs: {
YieldMath: protocol.getOrThrow(YIELDMATH)!,
},
},
/// @notice Deploy strategies
/// @param strategy name
/// @param strategy identifier (bytes6 tag)
/// @param Address for the Ladle
/// @param Address for the underlying asset
/// @param Underlying asset identifier (bytes6 tag)
/// @param Address for the underlying asset join
{
addressFile: 'strategies.json',
name: YSFRAX6MMS,
contract: 'Strategy',
args: [() => 'Yield Strategy FRAX 6M Mar Sep', () => 'YSFRAX6MMS', () => fyTokens().getOrThrow(FYFRAX2309)!],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
]
import { ethers } from 'hardhat'
import { DAI, USDC, FRAX } from '../../../../shared/constants'
import { ACCUMULATOR } from '../../../../shared/constants'
import { FYFRAX2309 } from '../../../../shared/constants'
import { YSFRAX6MMS, YSFRAX6MMS_V1 } from '../../../../shared/constants'
import * as base_config from '../../base.mainnet.config'
export const chainId: number = base_config.chainId
export const developer: string = '0xC7aE076086623ecEA2450e364C838916a043F9a8'
export const deployers: Map<string, string> = base_config.deployers
export const whales: Map<string, string> = base_config.whales
export const governance: Map<string, string> = base_config.governance
export const protocol: Map<string, string> = base_config.protocol
export const assets: Map<string, string> = base_config.assets
export const joins: Map<string, string> = base_config.joins
export const fyTokens: Map<string, string> = base_config.fyTokens
export const pools: Map<string, string> = base_config.pools
export const strategyAddresses: Map<string, string> = base_config.strategyAddresses
export const series: Map<string, Series> = base_config.series
export const strategies: Map<string, Strategy> = base_config.strategies
import { Series, Strategy, Strategy_V1 } from '../../confTypes'
const frax = base_config.bases.getOrThrow(FRAX)!
const fraxIlks = base_config.ilks.getOrThrow(FRAX)!
const fyFRAX2309: Series = {
seriesId: FYFRAX2309,
base: frax,
fyToken: {
assetId: FYFRAX2309,
address: fyTokens.getOrThrow(FYFRAX2309)!,
},
chiOracle: protocol.getOrThrow(ACCUMULATOR)!,
pool: {
assetId: FYFRAX2309,
address: pools.getOrThrow(FYFRAX2309)!,
},
ilks: fraxIlks,
}
export const newSeries: Series[] = [fyFRAX2309]
const ysFRAX6MMS: Strategy = {
assetId: YSFRAX6MMS,
address: strategyAddresses.getOrThrow(YSFRAX6MMS)!,
base: frax,
seriesToInvest: fyFRAX2309,
}
const ysFRAX6MMSV1: Strategy_V1 = {
assetId: YSFRAX6MMS_V1,
address: strategyAddresses.getOrThrow(YSFRAX6MMS_V1)!,
base: frax,
seriesToInvest: ysFRAX6MMS,
}
export const oldStrategies: Strategy_V1[] = [ysFRAX6MMSV1]
export const newStrategies: Strategy[] = [ysFRAX6MMS]
export const rollStrategies = oldStrategies
export const joinLoans = [
[DAI, ethers.utils.parseUnits('1000000', 18)],
[USDC, ethers.utils.parseUnits('1000000', 6)],
[FRAX, ethers.utils.parseUnits('1000000', 18)],
]
/// @notice Time stretch to be set in the PoolFactory prior to pool deployment
/// @param series identifier (bytes6 tag)
/// @param time stretch (64.64)
export const timeStretch: Map<string, BigNumber> = new Map([[FYUSDT2309, ONE64.div(secondsInOneYear.mul(35))]])
/// @notice Sell base to the pool fee, as fp4
export const g1: number = 9000
// ----- deployment parameters -----
export const contractDeployments: ContractDeployment[] = [
/// @notice Deploy fyToken series
/// @param underlying identifier (bytes6 tag)
/// @param Address for the chi oracle
/// @param Address for the related Join
/// @param Maturity in unix time (seconds since Jan 1, 1970)
/// @param Name for the series
/// @param Symbol for the series
{
addressFile: 'fyTokens.json',
name: FYUSDT2309,
contract: 'FYToken',
args: [
() => USDT,
() => protocol().getOrThrow(ACCUMULATOR)!,
() => joins().getOrThrow(USDT)!,
() => EOSEP23,
() => 'FYUSDT2309',
() => 'FYUSDT2309',
],
libs: {
SafeERC20Namer: protocol().getOrThrow(SAFE_ERC20_NAMER)!,
},
},
/// @notice Deploy plain YieldSpace pools
/// @param pool identifier, usually matching the series (bytes6 tag)
/// @param base address
/// @param fyToken address
/// @param time stretch, in 64.64
/// @param g1, in 64.64
{
addressFile: 'pools.json',
name: FYUSDT2309,
contract: 'PoolNonTv',
args: [
() => assets.get(USDT)!,
() => fyTokens().getOrThrow(FYUSDT2309)!,
() => timeStretch.get(FYUSDT2309)!.toString(),
() => g1.toString(),
],
libs: {
YieldMath: protocol().getOrThrow(YIELDMATH)!,
},
},
]
const fyUSDT2309: Series = {
seriesId: FYUSDT2309,
base: usdt,
fyToken: {
assetId: FYUSDT2309,
address: fyTokens.getOrThrow(FYUSDT2309)!,
},
chiOracle: protocol.getOrThrow(ACCUMULATOR)!,
pool: {
assetId: FYUSDT2309,
address: pools.getOrThrow(FYUSDT2309)!,
},
ilks: usdtIlks,
}
export const newSeries: Series[] = [fyUSDT2309]
const ysUSDT6MMS: Strategy = {
assetId: YSUSDT6MMS,
address: strategyAddresses.getOrThrow(YSUSDT6MMS)!,
base: usdt,
seriesToInvest: fyUSDT2309,
}
export const rollStrategies: Strategy[] = [ysUSDT6MMS]
/// @notice Time stretch to be set in the PoolFactory prior to pool deployment
/// @param series identifier (bytes6 tag)
/// @param time stretch (64.64)
export const timeStretch: Map<string, BigNumber> = new Map([
[FYETH2309, ONE64.div(secondsInOneYear.mul(25))],
[FYDAI2309, ONE64.div(secondsInOneYear.mul(45))],
[FYUSDC2309, ONE64.div(secondsInOneYear.mul(55))],
])
/// @notice Sell base to the pool fee, as fp4
export const g1: number = 9000
// ----- deployment parameters -----
export const contractDeployments: ContractDeployment[] = [
/// @notice Deploy fyToken series
/// @param underlying identifier (bytes6 tag)
/// @param Address for the chi oracle
/// @param Address for the related Join
/// @param Maturity in unix time (seconds since Jan 1, 1970)
/// @param Name for the series
/// @param Symbol for the series
{
addressFile: 'fyTokens.json',
name: FYETH2309,
contract: 'FYToken',
args: [
() => ETH,
() => protocol.getOrThrow(ACCUMULATOR),
() => joins.getOrThrow(ETH),
() => EOSEP23,
() => 'FYETH2309',
() => 'FYETH2309',
],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
{
addressFile: 'fyTokens.json',
name: FYDAI2309,
contract: 'FYToken',
args: [
() => DAI,
() => protocol.getOrThrow(ACCUMULATOR),
() => joins.getOrThrow(DAI),
() => EOSEP23,
() => 'FYDAI2309',
() => 'FYDAI2309',
],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
{
addressFile: 'fyTokens.json',
name: FYUSDC2309,
contract: 'FYToken',
args: [
() => USDC,
() => protocol.getOrThrow(ACCUMULATOR),
() => joins.getOrThrow(USDC),
() => EOSEP23,
() => 'FYUSDC2309',
() => 'FYUSDC2309',
],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
/// @notice Deploy plain YieldSpace pools
/// @param pool identifier, usually matching the series (bytes6 tag)
/// @param base address
/// @param fyToken address
/// @param time stretch, in 64.64
/// @param g1, in 64.64
{
addressFile: 'pools.json',
name: FYETH2309,
contract: 'PoolNonTv',
args: [
() => assets.get(ETH)!,
() => fyTokens().getOrThrow(FYETH2309)!,
() => timeStretch.get(FYETH2309)!.toString(),
() => g1.toString(),
],
libs: {
YieldMath: protocol.getOrThrow(YIELDMATH)!,
},
},
{
addressFile: 'pools.json',
name: FYDAI2309,
contract: 'PoolNonTv',
args: [
() => assets.get(DAI)!,
() => fyTokens().getOrThrow(FYDAI2309)!,
() => timeStretch.get(FYDAI2309)!.toString(),
() => g1.toString(),
],
libs: {
YieldMath: protocol.getOrThrow(YIELDMATH)!,
},
},
{
addressFile: 'pools.json',
name: FYUSDC2309,
contract: 'PoolNonTv',
args: [
() => assets.get(USDC)!,
() => fyTokens().getOrThrow(FYUSDC2309)!,
() => timeStretch.get(FYUSDC2309)!.toString(),
() => g1.toString(),
],
libs: {
YieldMath: protocol.getOrThrow(YIELDMATH)!,
},
},
/// @notice Deploy strategies
/// @param strategy name
/// @param strategy identifier (bytes6 tag)
/// @param Address for the Ladle
/// @param Address for the underlying asset
/// @param Underlying asset identifier (bytes6 tag)
/// @param Address for the underlying asset join
{
addressFile: 'strategies.json',
name: YSETH6MMS,
contract: 'Strategy',
args: [() => 'Yield Strategy ETH 6M Mar Sep', () => 'YSETH6MMS', () => fyTokens().getOrThrow(FYETH2309)!],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
{
addressFile: 'strategies.json',
name: YSDAI6MMS,
contract: 'Strategy',
args: [() => 'Yield Strategy DAI 6M Mar Sep', () => 'YSDAI6MMS', () => fyTokens().getOrThrow(FYDAI2309)!],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
{
addressFile: 'strategies.json',
name: YSUSDC6MMS,
contract: 'Strategy',
args: [() => 'Yield Strategy USDC 6M Mar Sep', () => 'YSUSDC6MMS', () => fyTokens().getOrThrow(FYUSDC2309)!],
libs: {
SafeERC20Namer: protocol.getOrThrow(SAFE_ERC20_NAMER)!,
},
},
]
const fyETH2309: Series = {
seriesId: FYETH2309,
base: eth,
fyToken: {
assetId: FYETH2309,
address: fyTokens.getOrThrow(FYETH2309)!,
},
chiOracle: protocol.getOrThrow(ACCUMULATOR)!,
pool: {
assetId: FYETH2309,
address: pools.getOrThrow(FYETH2309)!,
},
ilks: ethIlks,
}
const fyDAI2309: Series = {
seriesId: FYDAI2309,
base: dai,
fyToken: {
assetId: FYDAI2309,
address: fyTokens.getOrThrow(FYDAI2309)!,
},
chiOracle: protocol.getOrThrow(ACCUMULATOR)!,
pool: {
assetId: FYDAI2309,
address: pools.getOrThrow(FYDAI2309)!,
},
ilks: daiIlks,
}
const fyUSDC2309: Series = {
seriesId: FYUSDC2309,
base: usdc,
fyToken: {
assetId: FYUSDC2309,
address: fyTokens.getOrThrow(FYUSDC2309)!,
},
chiOracle: protocol.getOrThrow(ACCUMULATOR)!,
pool: {
assetId: FYUSDC2309,
address: pools.getOrThrow(FYUSDC2309)!,
},
ilks: usdcIlks,
}
export const newSeries: Series[] = [fyETH2309, fyDAI2309, fyUSDC2309]
const ysETH6MMS: Strategy = {
assetId: YSETH6MMS,
address: strategyAddresses.getOrThrow(YSETH6MMS)!,
base: eth,
seriesToInvest: fyETH2309,
}
const ysDAI6MMS: Strategy = {
assetId: YSDAI6MMS,
address: strategyAddresses.getOrThrow(YSDAI6MMS)!,
base: dai,
seriesToInvest: fyDAI2309,
}
const ysUSDC6MMS: Strategy = {
assetId: YSUSDC6MMS,
address: strategyAddresses.getOrThrow(YSUSDC6MMS)!,
base: usdc,
seriesToInvest: fyUSDC2309,
}
const ysETH6MMSV1: Strategy_V1 = {
assetId: YSETH6MMS_V1,
address: strategyAddresses.getOrThrow(YSETH6MMS_V1)!,
base: eth,
seriesToInvest: ysETH6MMS,
}
const ysDAI6MMSV1: Strategy_V1 = {
assetId: YSDAI6MMS_V1,
address: strategyAddresses.getOrThrow(YSDAI6MMS_V1)!,
base: dai,
seriesToInvest: ysDAI6MMS,
}
const ysUSDC6MMSV1: Strategy_V1 = {
assetId: YSUSDC6MMS_V1,
address: strategyAddresses.getOrThrow(YSUSDC6MMS_V1)!,
base: usdc,
seriesToInvest: ysUSDC6MMS,
}
export const oldStrategies: Strategy_V1[] = [ysETH6MMSV1, ysDAI6MMSV1, ysUSDC6MMSV1]
export const newStrategies: Strategy[] = [ysETH6MMS, ysDAI6MMS, ysUSDC6MMS]
export const rollStrategies = oldStrategies
Manual verification of the deployment done on mainnet tenderly fork & arbitrum tenderly fork