-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sepolia cWETHv3 deploy and proposal (#832)
Deploys cWETHv3 to Sepolia and initializes it with a proposal.
- Loading branch information
1 parent
745fddd
commit 55960cd
Showing
8 changed files
with
317 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"name": "Compound WETH", | ||
"symbol": "cWETHv3", | ||
"baseToken": "WETH", | ||
"baseTokenAddress": "0x2D5ee574e710219a521449679A4A7f2B43f046ad", | ||
"borrowMin": "1e12", | ||
"governor": "0x54a06047087927D9B0fb21c1cf0ebd792764dDB8", | ||
"pauseGuardian": "0x008a4C5448ac1Df676d6F39A0C6F13b21b189389", | ||
"storeFrontPriceFactor": 0.5, | ||
"targetReserves": "5000e18", | ||
"rates": { | ||
"supplyKink": 0.9, | ||
"supplySlopeLow": 0.01690681444, | ||
"supplySlopeHigh": 0.6066567706, | ||
"supplyBase": 0, | ||
"borrowKink": 0.9, | ||
"borrowSlopeLow": 0.05171500002, | ||
"borrowSlopeHigh": 0.5171500339, | ||
"borrowBase": 0.009945209674 | ||
}, | ||
"tracking": { | ||
"indexScale": "1e15", | ||
"baseSupplySpeed": "0.000011574074074074073e15", | ||
"baseBorrowSpeed": "0e15", | ||
"baseMinForRewards": "0.1e18" | ||
}, | ||
"assets": { | ||
"cbETH": { | ||
"decimals": "18", | ||
"borrowCF": 0.90, | ||
"liquidateCF": 0.93, | ||
"liquidationFactor": 0.95, | ||
"supplyCap": "9_000e18" | ||
}, | ||
"wstETH": { | ||
"address": "0xB82381A3fBD3FaFA77B3a7bE693342618240067b", | ||
"decimals": "18", | ||
"borrowCF": 0.90, | ||
"liquidateCF": 0.93, | ||
"liquidationFactor": 0.95, | ||
"supplyCap": "80_000e18" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; | ||
import { debug, DeploySpec, deployComet, exp, sameAddress, wait } from '../../../src/deploy'; | ||
|
||
const clone = { | ||
cbETHImpl: '0x31724cA0C982A31fbb5C57f4217AB585271fc9a5', | ||
cbETHProxy: '0xBe9895146f7AF43049ca1c1AE358B0541Ea49704', | ||
}; | ||
|
||
export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise<Deployed> { | ||
const deployed = await deployContracts(deploymentManager, deploySpec); | ||
await mintTokens(deploymentManager); | ||
return deployed; | ||
} | ||
|
||
async function deployContracts(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise<Deployed> { | ||
const ethers = deploymentManager.hre.ethers; | ||
const signer = await deploymentManager.getSigner(); | ||
|
||
// Declare existing assets as aliases | ||
const WETH = await deploymentManager.existing('WETH', '0x2D5ee574e710219a521449679A4A7f2B43f046ad', 'sepolia'); | ||
const wstETH = await deploymentManager.existing('wstETH', '0xB82381A3fBD3FaFA77B3a7bE693342618240067b', 'sepolia'); | ||
|
||
// Import shared contracts from cUSDCv3 | ||
const cometAdmin = await deploymentManager.fromDep('cometAdmin', 'sepolia', 'usdc'); | ||
const cometFactory = await deploymentManager.fromDep('cometFactory', 'sepolia', 'usdc'); | ||
const $configuratorImpl = await deploymentManager.fromDep('configurator:implementation', 'sepolia', 'usdc'); | ||
const configurator = await deploymentManager.fromDep('configurator', 'sepolia', 'usdc'); | ||
const rewards = await deploymentManager.fromDep('rewards', 'sepolia', 'usdc'); | ||
const fauceteer = await deploymentManager.fromDep('fauceteer', 'sepolia', 'usdc'); | ||
|
||
// Clone cbETH | ||
const cbETHProxyAdmin = await deploymentManager.deploy('cbETH:admin', 'vendor/proxy/transparent/ProxyAdmin.sol', []); | ||
const cbETHImpl = await deploymentManager.clone('cbETH:implementation', clone.cbETHImpl, []); | ||
const cbETHProxy = await deploymentManager.clone('cbETH', clone.cbETHProxy, [cbETHImpl.address]); | ||
const cbETHProxyAdminSlot = '0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b'; | ||
const cbETH = cbETHImpl.attach(cbETHProxy.address); | ||
await deploymentManager.idempotent( | ||
async () => !sameAddress(await ethers.provider.getStorageAt(cbETHProxy.address, cbETHProxyAdminSlot), cbETHProxyAdmin.address), | ||
async () => { | ||
debug(`Changing admin of cbETH proxy to ${cbETHProxyAdmin.address}`); | ||
await wait(cbETHProxy.connect(signer).changeAdmin(cbETHProxyAdmin.address)); | ||
|
||
debug(`Initializing cbETH`); | ||
await wait(cbETH.connect(signer).initialize( | ||
'Coinbase Wrapped Staked ETH', // name | ||
'cbETH', // symbol | ||
'', // currency | ||
18, // decimals | ||
signer.address, // Master Minter | ||
signer.address, // Pauser | ||
signer.address, // Blacklister | ||
signer.address // Owner | ||
)); | ||
} | ||
); | ||
|
||
// Deploy stETH / ETH SimplePriceFeed | ||
const stETHtoETHPriceFeed = await deploymentManager.deploy( | ||
'stETHToETH:simplePriceFeed', | ||
'test/SimplePriceFeed.sol', | ||
[ | ||
exp(0.98882408, 18), // Latest answer on mainnet at block 16170924 | ||
18 | ||
] | ||
); | ||
|
||
// Deploy cbETH / ETH SimplePriceFeed | ||
const cbETHtoETHPriceFeed = await deploymentManager.deploy( | ||
'cbETHToETH:simplePriceFeed', | ||
'test/SimplePriceFeed.sol', | ||
[ | ||
exp(0.97, 18), | ||
18 | ||
] | ||
); | ||
|
||
// Deploy WstETHPriceFeed | ||
const wstETHPriceFeed = await deploymentManager.deploy( | ||
'wstETH:priceFeed', | ||
'pricefeeds/WstETHPriceFeed.sol', | ||
[ | ||
stETHtoETHPriceFeed.address, // stETH / ETH price feed | ||
wstETH.address, // wstETH | ||
8 // decimals | ||
] | ||
); | ||
|
||
// Deploy constant price feed for WETH | ||
const wethConstantPriceFeed = await deploymentManager.deploy( | ||
'WETH:priceFeed', | ||
'pricefeeds/ConstantPriceFeed.sol', | ||
[ | ||
8, // decimals | ||
exp(1, 8) // constantPrice | ||
] | ||
); | ||
|
||
// Deploy scaling price feed for cbETH | ||
const cbETHScalingPriceFeed = await deploymentManager.deploy( | ||
'cbETH:priceFeed', | ||
'pricefeeds/ScalingPriceFeed.sol', | ||
[ | ||
cbETHtoETHPriceFeed.address, // cbETH / ETH price feed | ||
8 // decimals | ||
] | ||
); | ||
|
||
// Deploy all Comet-related contracts | ||
const deployed = await deployComet(deploymentManager, deploySpec); | ||
const { comet } = deployed; | ||
|
||
// Deploy Bulker | ||
const bulker = await deploymentManager.deploy( | ||
'bulker', | ||
'bulkers/MainnetBulker.sol', | ||
[ | ||
await comet.governor(), // admin_ | ||
WETH.address, // weth_ | ||
wstETH.address // wsteth_ | ||
] | ||
); | ||
|
||
return { ...deployed, bulker, fauceteer }; | ||
} | ||
|
||
async function mintTokens(deploymentManager: DeploymentManager) { | ||
const signer = await deploymentManager.getSigner(); | ||
const contracts = await deploymentManager.contracts(); | ||
const fauceteer = contracts.get('fauceteer')!; | ||
|
||
debug(`Attempting to mint as ${signer.address}...`); | ||
|
||
// If we haven't spidered new contracts (which we could before minting, but its slow), | ||
// then the proxy contract won't have the impl functions yet, so just do it explicitly | ||
const cbETHProxy = contracts.get('cbETH')!, cbETHImpl = contracts.get('cbETH:implementation')!; | ||
const cbETH = cbETHImpl.attach(cbETHProxy.address); | ||
await deploymentManager.idempotent( | ||
async () => (await cbETH.balanceOf(fauceteer.address)).eq(0), | ||
async () => { | ||
debug(`Minting 1M cbETH to fauceteer`); | ||
const amount = exp(1_000_000, await cbETH.decimals()); | ||
await wait(cbETH.connect(signer).configureMinter(signer.address, amount)); | ||
await wait(cbETH.connect(signer).mint(fauceteer.address, amount)); | ||
debug(`cbETH.balanceOf(${fauceteer.address}): ${await cbETH.balanceOf(fauceteer.address)}`); | ||
} | ||
); | ||
} |
96 changes: 96 additions & 0 deletions
96
deployments/sepolia/weth/migrations/1709094543_initialize_market.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { DeploymentManager, migration } from '../../../../plugins/deployment_manager'; | ||
import { exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; | ||
|
||
import { expect } from 'chai'; | ||
|
||
const COMPAddress = '0xA6c8D1c55951e8AC44a0EaA959Be5Fd21cc07531'; | ||
|
||
export default migration('1709094543_initialize_market', { | ||
prepare: async (deploymentManager: DeploymentManager) => { | ||
return {}; | ||
}, | ||
|
||
enact: async (deploymentManager: DeploymentManager) => { | ||
const trace = deploymentManager.tracer(); | ||
|
||
// Import shared contracts from cUSDCv3 | ||
const cometFactory = await deploymentManager.fromDep('cometFactory', 'sepolia', 'usdc'); | ||
|
||
const { | ||
governor, | ||
comet, | ||
configurator, | ||
cometAdmin, | ||
rewards, | ||
} = await deploymentManager.getContracts(); | ||
|
||
const configuration = await getConfigurationStruct(deploymentManager); | ||
|
||
const actions = [ | ||
// 1. Set the factory in the Configurator | ||
{ | ||
contract: configurator, | ||
signature: 'setFactory(address,address)', | ||
args: [comet.address, cometFactory.address], | ||
}, | ||
|
||
// 2. Set the configuration in the Configurator | ||
{ | ||
contract: configurator, | ||
signature: 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', | ||
args: [comet.address, configuration], | ||
}, | ||
|
||
// 3. Deploy and upgrade to a new version of Comet | ||
{ | ||
contract: cometAdmin, | ||
signature: "deployAndUpgradeTo(address,address)", | ||
args: [configurator.address, comet.address], | ||
}, | ||
|
||
// 4. Set the rewards configuration to COMP | ||
{ | ||
contract: rewards, | ||
signature: "setRewardConfig(address,address)", | ||
args: [comet.address, COMPAddress], | ||
}, | ||
]; | ||
const description = "# Initialize cWETHv3 on Sepolia" | ||
const txn = await deploymentManager.retry( | ||
async () => trace((await governor.propose(...await proposal(actions, description)))) | ||
); | ||
|
||
const event = txn.events.find(event => event.event === 'ProposalCreated'); | ||
const [proposalId] = event.args; | ||
|
||
trace(`Created proposal ${proposalId}.`); | ||
}, | ||
|
||
async enacted(deploymentManager: DeploymentManager): Promise<boolean> { | ||
return true; | ||
}, | ||
|
||
async verify(deploymentManager: DeploymentManager) { | ||
const { | ||
comet, | ||
rewards, | ||
wstETH, | ||
cbETH, | ||
} = await deploymentManager.getContracts(); | ||
// 2. & 3. | ||
expect(await comet.baseTrackingSupplySpeed()).to.be.equal(exp(1 / 86400, 15, 18)); // ~ 1 COMP / day | ||
expect(await comet.baseTrackingBorrowSpeed()).to.be.equal(0); | ||
|
||
const wstETHInfo = await comet.getAssetInfoByAddress(wstETH.address); | ||
expect(wstETHInfo.supplyCap).to.be.equal(exp(80_000, 18)); // ~ $100M / $1225 | ||
|
||
const cbETHInfo = await comet.getAssetInfoByAddress(cbETH.address); | ||
expect(cbETHInfo.supplyCap).to.be.equal(exp(9_000, 18)); // ~ $10M / $1091 | ||
|
||
// 4. | ||
const config = await rewards.rewardConfig(comet.address); | ||
expect(config.token).to.be.equal(COMPAddress); | ||
expect(config.rescaleFactor).to.be.equal(1000000000000n); | ||
expect(config.shouldUpscale).to.be.equal(true); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import baseRelationConfig from '../../relations'; | ||
|
||
export default { | ||
...baseRelationConfig, | ||
'wstETH': { | ||
artifact: 'contracts/bulkers/IWstETH.sol', | ||
relations: { | ||
stETH: { | ||
field: async (wstETH) => wstETH.stETH() | ||
} | ||
} | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"comet": "0x2943ac1216979aD8dB76D9147F64E61adc126e96", | ||
"configurator": "0xc28aD44975C614EaBe0Ed090207314549e1c6624", | ||
"rewards": "0x8bF5b658bdF0388E8b482ED51B14aef58f90abfD", | ||
"bulker": "0xaD0C044425D81a2E223f4CE699156900fead2Aaa", | ||
"fauceteer": "0x68793eA49297eB75DFB4610B68e076D2A5c7646C" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters