-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MATICx as collateral against polygon usdc (#777)
* initial migration script to add maticx as collateral for polygon usdc * add verify block * formatting: white spaces removal
- Loading branch information
1 parent
761028a
commit 2e47c43
Showing
2 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
167 changes: 167 additions & 0 deletions
167
deployments/polygon/usdc/migrations/1689168483_add_maticx_collateral.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,167 @@ | ||
import { expect } from "chai"; | ||
import { DeploymentManager } from "../../../../plugins/deployment_manager/DeploymentManager"; | ||
import { migration } from "../../../../plugins/deployment_manager/Migration"; | ||
import { calldata, exp, proposal } from "../../../../src/deploy"; | ||
import { utils } from "ethers"; | ||
|
||
interface Vars {} | ||
|
||
const MATICX_ADDRESS = "0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6"; | ||
const MATICX_PRICE_FEED_ADDRESS = "0x5d37E4b374E6907de8Fc7fb33EE3b0af403C7403"; | ||
|
||
export default migration("1689168483_add_maticx_collateral", { | ||
prepare: async (deploymentManager: DeploymentManager) => { | ||
return {}; | ||
}, | ||
|
||
enact: async ( | ||
deploymentManager: DeploymentManager, | ||
govDeploymentManager: DeploymentManager, | ||
vars: Vars | ||
) => { | ||
const trace = deploymentManager.tracer(); | ||
// const ethers = deploymentManager.hre.ethers; // ethers is not available | ||
// const { utils } = ethers; | ||
|
||
const maticx = await deploymentManager.existing( | ||
"MATICX", | ||
MATICX_ADDRESS, | ||
"polygon", | ||
"contracts/ERC20.sol:ERC20" | ||
); | ||
const maticxPricefeed = await deploymentManager.existing( | ||
"MATICX:priceFeed", | ||
MATICX_PRICE_FEED_ADDRESS, | ||
"polygon" | ||
); | ||
|
||
const { | ||
bridgeReceiver, | ||
comet, | ||
cometAdmin, | ||
configurator, | ||
} = await deploymentManager.getContracts(); | ||
|
||
const { fxRoot, governor } = await govDeploymentManager.getContracts(); | ||
|
||
const newAssetConfig = { | ||
asset: maticx.address, | ||
priceFeed: maticxPricefeed.address, | ||
decimals: await maticx.decimals(), | ||
borrowCollateralFactor: exp(0.55, 18), | ||
liquidateCollateralFactor: exp(0.65, 18), | ||
liquidationFactor: exp(0.9, 18), | ||
supplyCap: exp(6_000_000, 18), | ||
}; | ||
|
||
const addAssetCalldata = await calldata( | ||
configurator.populateTransaction.addAsset(comet.address, newAssetConfig) | ||
); | ||
const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( | ||
["address", "address"], | ||
[configurator.address, comet.address] | ||
); | ||
|
||
const l2ProposalData = utils.defaultAbiCoder.encode( | ||
["address[]", "uint256[]", "string[]", "bytes[]"], | ||
[ | ||
[configurator.address, cometAdmin.address], | ||
[0, 0], | ||
[ | ||
"addAsset(address,(address,address,uint8,uint64,uint64,uint64,uint128))", | ||
"deployAndUpgradeTo(address,address)", | ||
], | ||
[addAssetCalldata, deployAndUpgradeToCalldata], | ||
] | ||
); | ||
|
||
const mainnetActions = [ | ||
// 1. Set Comet configuration and deployAndUpgradeTo new Comet on Polygon. | ||
{ | ||
contract: fxRoot, | ||
signature: "sendMessageToChild(address,bytes)", | ||
args: [bridgeReceiver.address, l2ProposalData], | ||
}, | ||
]; | ||
|
||
const description = "TODO"; | ||
const txn = await govDeploymentManager.retry(async () => | ||
trace( | ||
await governor.propose(...(await proposal(mainnetActions, description))) | ||
) | ||
); | ||
|
||
const event = (await txn.wait()).events.find( | ||
(event) => event.event === "ProposalCreated" | ||
); | ||
const [proposalId] = event.args; | ||
trace(`Created proposal ${proposalId}.`); | ||
}, | ||
|
||
async verify(deploymentManager: DeploymentManager) { | ||
const { comet, configurator } = await deploymentManager.getContracts(); | ||
|
||
const maticxAssetIndex = 3; // TODO | ||
|
||
const maticxAssetConfig = { | ||
asset: MATICX_ADDRESS, | ||
priceFeed: MATICX_PRICE_FEED_ADDRESS, | ||
decimals: 18, | ||
borrowCollateralFactor: exp(0.55, 18), | ||
liquidateCollateralFactor: exp(0.65, 18), | ||
liquidationFactor: exp(0.9, 18), | ||
supplyCap: exp(6_000_000, 18), | ||
}; | ||
|
||
// 1. Compare proposed asset config with Comet asset info | ||
const cometMaticxAssetInfo = await comet.getAssetInfoByAddress( | ||
MATICX_ADDRESS | ||
); | ||
expect(maticxAssetIndex).to.be.equal(cometMaticxAssetInfo.offset); | ||
expect(maticxAssetConfig.asset).to.be.equal(cometMaticxAssetInfo.asset); | ||
expect(maticxAssetConfig.priceFeed).to.be.equal( | ||
cometMaticxAssetInfo.priceFeed | ||
); | ||
expect(exp(1, maticxAssetConfig.decimals)).to.be.equal( | ||
cometMaticxAssetInfo.scale | ||
); | ||
expect(maticxAssetConfig.borrowCollateralFactor).to.be.equal( | ||
cometMaticxAssetInfo.borrowCollateralFactor | ||
); | ||
expect(maticxAssetConfig.liquidateCollateralFactor).to.be.equal( | ||
cometMaticxAssetInfo.liquidateCollateralFactor | ||
); | ||
expect(maticxAssetConfig.liquidationFactor).to.be.equal( | ||
cometMaticxAssetInfo.liquidationFactor | ||
); | ||
expect(maticxAssetConfig.supplyCap).to.be.equal( | ||
cometMaticxAssetInfo.supplyCap | ||
); | ||
|
||
// 2. Compare proposed asset config with Configurator asset config | ||
const configuratorMaticxAssetConfig = ( | ||
await configurator.getConfiguration(comet.address) | ||
).assetConfigs[maticxAssetIndex]; | ||
expect(maticxAssetConfig.asset).to.be.equal( | ||
configuratorMaticxAssetConfig.asset | ||
); | ||
expect(maticxAssetConfig.priceFeed).to.be.equal( | ||
configuratorMaticxAssetConfig.priceFeed | ||
); | ||
expect(maticxAssetConfig.decimals).to.be.equal( | ||
configuratorMaticxAssetConfig.decimals | ||
); | ||
expect(maticxAssetConfig.borrowCollateralFactor).to.be.equal( | ||
configuratorMaticxAssetConfig.borrowCollateralFactor | ||
); | ||
expect(maticxAssetConfig.liquidateCollateralFactor).to.be.equal( | ||
configuratorMaticxAssetConfig.liquidateCollateralFactor | ||
); | ||
expect(maticxAssetConfig.liquidationFactor).to.be.equal( | ||
configuratorMaticxAssetConfig.liquidationFactor | ||
); | ||
expect(maticxAssetConfig.supplyCap).to.be.equal( | ||
configuratorMaticxAssetConfig.supplyCap | ||
); | ||
}, | ||
}); |
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,185 @@ | ||
import { scenario } from "./context/CometContext"; | ||
import { expect } from "chai"; | ||
import { utils } from "ethers"; | ||
import { exp } from "../test/helpers"; | ||
import { COMP_WHALES, calldata } from "../src/deploy"; | ||
import { impersonateAddress } from "../plugins/scenario/utils"; | ||
import { fastL2GovernanceExecute, matchesDeployment } from "./utils"; | ||
import { BaseBridgeReceiver } from "../build/types"; | ||
import { World } from "../plugins/scenario"; | ||
|
||
const MATICX_WHALES = { | ||
polygon: ["0x68B9220B8E617b7700aCAE1a5Ff43F3eb29257F3"], | ||
}; | ||
|
||
scenario.only( | ||
"add new asset maticx", | ||
{ | ||
filter: async (ctx) => | ||
matchesDeployment(ctx, [{ network: "polygon" }, { network: "mumbai" }]), | ||
tokenBalances: { | ||
$comet: { $base: ">= 1" }, | ||
}, | ||
}, | ||
async ( | ||
{ comet, configurator, proxyAdmin, actors, bridgeReceiver }, | ||
context | ||
) => { | ||
console.log("DEBUG::0"); | ||
const { albert } = actors; | ||
console.log("DEBUG::1"); | ||
const dm = context.world.deploymentManager; | ||
console.log("DEBUG::2"); | ||
const maticx = await dm.existing( | ||
"MATICX", | ||
"0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6", | ||
context.world.base.network, | ||
"contracts/ERC20.sol:ERC20" | ||
); | ||
console.log("DEBUG::3"); | ||
const maticxPricefeed = await dm.existing( | ||
"MATICX:priceFeed", | ||
"0x5d37E4b374E6907de8Fc7fb33EE3b0af403C7403", | ||
context.world.base.network | ||
); | ||
console.log("DEBUG::4"); | ||
|
||
// Allocate some tokens to Albert | ||
const maticxWhaleSigner = await impersonateAddress( | ||
dm, | ||
MATICX_WHALES.polygon[0] | ||
); | ||
console.log("DEBUG::5"); | ||
console.log( | ||
"whale balance:", | ||
await maticx.balanceOf(maticxWhaleSigner.address) | ||
); | ||
// console.log(await maticx.proxyOwner()); | ||
await maticx | ||
.connect(maticxWhaleSigner) | ||
.transfer(albert.address, exp(9000, 18).toString()); | ||
console.log("DEBUG::6"); | ||
|
||
// Execute a governance proposal to: | ||
// 1. Add new asset via Configurator | ||
// 2. Deploy and upgrade to new implementation of Comet | ||
const newAssetConfig = { | ||
asset: maticx.address, | ||
priceFeed: maticxPricefeed.address, | ||
decimals: await maticx.decimals(), | ||
borrowCollateralFactor: exp(0.55, 18), | ||
liquidateCollateralFactor: exp(0.65, 18), | ||
liquidationFactor: exp(0.9, 18), | ||
supplyCap: exp(6_000_000, 18), | ||
}; | ||
console.log("DEBUG::7"); | ||
|
||
const addAssetCalldata = await calldata( | ||
configurator.populateTransaction.addAsset(comet.address, newAssetConfig) | ||
); | ||
console.log("DEBUG::8"); | ||
|
||
const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( | ||
["address", "address"], | ||
[configurator.address, comet.address] | ||
); | ||
console.log("DEBUG::9"); | ||
|
||
const l2ProposalData = utils.defaultAbiCoder.encode( | ||
["address[]", "uint256[]", "string[]", "bytes[]"], | ||
[ | ||
[configurator.address, proxyAdmin.address], | ||
[0, 0], | ||
[ | ||
"addAsset(address,(address,address,uint8,uint64,uint64,uint64,uint128))", | ||
"deployAndUpgradeTo(address,address)", | ||
], | ||
[addAssetCalldata, deployAndUpgradeToCalldata], | ||
] | ||
); | ||
|
||
await fastL1ToPolygonGovernanceExecute( | ||
l2ProposalData, | ||
bridgeReceiver, | ||
context.world | ||
); | ||
console.log("DEBUG::10"); | ||
|
||
// Try to supply new token and borrow base | ||
const baseAssetAddress = await comet.baseToken(); | ||
console.log("DEBUG::11", baseAssetAddress); | ||
|
||
const borrowAmount = 1000n * (await comet.baseScale()).toBigInt(); | ||
console.log("DEBUG::12", borrowAmount.toString()); | ||
|
||
const supplyAmount = exp(9000, 18); | ||
console.log("DEBUG::13"); | ||
|
||
await maticx | ||
.connect(albert.signer) | ||
["approve(address,uint256)"](comet.address, supplyAmount); | ||
console.log("DEBUG::14"); | ||
|
||
await albert.supplyAsset({ asset: maticx.address, amount: supplyAmount }); | ||
console.log( | ||
"DEBUG::15", | ||
await albert.getCometCollateralBalance(maticx.address) | ||
); | ||
|
||
await albert.withdrawAsset({ | ||
asset: baseAssetAddress, | ||
amount: borrowAmount, | ||
}); | ||
console.log("DEBUG::16"); | ||
|
||
const cometMaticxAssetInfo = await comet.getAssetInfoByAddress( | ||
"0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6" | ||
); | ||
console.log("maticx index:", cometMaticxAssetInfo.offset); | ||
|
||
expect(await albert.getCometCollateralBalance(maticx.address)).to.be.equal( | ||
supplyAmount | ||
); | ||
expect(await albert.getCometBaseBalance()).to.be.equal(-borrowAmount); | ||
} | ||
); | ||
|
||
async function fastL1ToPolygonGovernanceExecute( | ||
l2ProposalData: string, | ||
bridgeReceiver: BaseBridgeReceiver, | ||
world: World | ||
) { | ||
const governanceDeploymentManager = world.auxiliaryDeploymentManager; | ||
if (!governanceDeploymentManager) { | ||
throw new Error( | ||
"cannot execute governance without governance deployment manager" | ||
); | ||
} | ||
|
||
const compWhale = | ||
world.base.network === "polygon" | ||
? COMP_WHALES.mainnet[0] | ||
: COMP_WHALES.testnet[0]; | ||
const proposer = await impersonateAddress( | ||
governanceDeploymentManager, | ||
compWhale, | ||
exp(1, 18) | ||
); // give them enough ETH to make the proposal | ||
|
||
const sendMessageToChildCalldata = utils.defaultAbiCoder.encode( | ||
["address", "bytes"], | ||
[bridgeReceiver.address, l2ProposalData] | ||
); | ||
|
||
const fxRoot = await governanceDeploymentManager.getContractOrThrow("fxRoot"); | ||
|
||
await fastL2GovernanceExecute( | ||
governanceDeploymentManager, | ||
world.deploymentManager, | ||
proposer, | ||
[fxRoot.address], | ||
[0], | ||
["sendMessageToChild(address,bytes)"], | ||
[sendMessageToChildCalldata] | ||
); | ||
} |