Skip to content

Commit

Permalink
Add MATICx as collateral against polygon usdc (#777)
Browse files Browse the repository at this point in the history
* initial migration script to add maticx as collateral for polygon usdc

* add verify block

* formatting: white spaces removal
  • Loading branch information
Manoj Patra authored Jul 13, 2023
1 parent 66527f8 commit 81230ff
Show file tree
Hide file tree
Showing 2 changed files with 352 additions and 0 deletions.
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
);
},
});
185 changes: 185 additions & 0 deletions scenario/AddMaticxCollateralScenario.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { scenario } from "./context/CometContext";

Check warning on line 1 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { expect } from "chai";

Check warning on line 2 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { utils } from "ethers";

Check warning on line 3 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { exp } from "../test/helpers";

Check warning on line 4 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { COMP_WHALES, calldata } from "../src/deploy";

Check warning on line 5 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { impersonateAddress } from "../plugins/scenario/utils";

Check warning on line 6 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { fastL2GovernanceExecute, matchesDeployment } from "./utils";

Check warning on line 7 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { BaseBridgeReceiver } from "../build/types";

Check warning on line 8 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
import { World } from "../plugins/scenario";

Check warning on line 9 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote

const MATICX_WHALES = {
polygon: ["0x68B9220B8E617b7700aCAE1a5Ff43F3eb29257F3"],

Check warning on line 12 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Strings must use singlequote
};

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);

Check failure on line 120 in scenario/AddMaticxCollateralScenario.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Unexpected newline between object and [ of property access
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]
);
}

0 comments on commit 81230ff

Please sign in to comment.