Skip to content

Commit

Permalink
Create migration script to deploy a custom WBTC price feed and upgrad…
Browse files Browse the repository at this point in the history
…e Comet to use it
  • Loading branch information
kevincheng96 committed Jun 21, 2023
1 parent cec2870 commit 976e43a
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { expect } from 'chai';
import { diffState } from '../../../../plugins/deployment_manager';
import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager';
import { getCometConfig } from '../../../../plugins/deployment_manager/DiffState';
import { migration } from '../../../../plugins/deployment_manager/Migration';
import { proposal } from '../../../../src/deploy';

interface Vars {
newWBTCPriceFeed: string
};

export default migration('1686950699_update_wbtc_price_feed', {
prepare: async (deploymentManager: DeploymentManager) => {
// Deploy custom WBTC price feed
const WBTCPriceFeed = await deploymentManager.deploy(
'newWBTCPriceFeed',
'pricefeeds/WBTCPriceFeed.sol',
[
'0xfdFD9C85aD200c506Cf9e21F1FD8dd01932FBB23', // WBTCToBTCPriceFeed
'0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c', // BTCToUSDPriceFeed
8 // decimals
]
);
return { newWBTCPriceFeed: WBTCPriceFeed.address };
},

enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => {
const trace = deploymentManager.tracer();

const {
governor,
comet,
configurator,
cometAdmin,
WBTC,
} = await deploymentManager.getContracts();

const actions = [
// 1. Update WBTC price feed
{
contract: configurator,
signature: 'updateAssetPriceFeed(address,address,address)',
args: [comet.address, WBTC.address, vars.newWBTCPriceFeed],
},

// 2. Deploy and upgrade to a new version of Comet
{
contract: cometAdmin,
signature: 'deployAndUpgradeTo(address,address)',
args: [configurator.address, comet.address],
},
];
const description = 'TODO'
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 verify(deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number, vars: Vars) {
const {
comet,
} = await deploymentManager.getContracts();

// 1. & 2.
const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber);
expect(stateChanges).to.deep.equal({
WBTC: {
priceFeed: vars.newWBTCPriceFeed
}
})
}
});
2 changes: 1 addition & 1 deletion plugins/deployment_manager/Migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface Actions<T> {
prepare: (dm: DeploymentManager, govDm: DeploymentManager) => Promise<T>;
enact: (dm: DeploymentManager, govDm: DeploymentManager, t: T) => Promise<void>;
enacted?: (dm: DeploymentManager, govDm: DeploymentManager) => Promise<boolean>;
verify?: (dm: DeploymentManager, govDm: DeploymentManager, preMigrationBlockNumber: number) => Promise<void>;
verify?: (dm: DeploymentManager, govDm: DeploymentManager, preMigrationBlockNumber: number, t: T) => Promise<void>;
}

export class Migration<T> {
Expand Down
8 changes: 6 additions & 2 deletions plugins/deployment_manager/MigrationTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ import { migration } from '../../../../plugins/deployment_manager/Migration';
interface Vars {};
export default migration('${timestamp}_${name}', {
prepare: async (deploymentManager: DeploymentManager) => {
async prepare(deploymentManager: DeploymentManager) {
return {};
},
enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => {
async enact(deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) {
// No governance changes
},
async verify(deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number, vars: Vars) {
// Verify migration success
}
});\n`;
}
Expand Down
8 changes: 6 additions & 2 deletions plugins/deployment_manager/test/MigrationTemplateTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ import { migration } from '../../../../plugins/deployment_manager/Migration';
interface Vars {};
export default migration('1_cool', {
prepare: async (deploymentManager: DeploymentManager) => {
async prepare(deploymentManager: DeploymentManager) {
return {};
},
enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => {
async enact(deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) {
// No governance changes
},
async verify(deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number, vars: Vars) {
// Verify migration success
}
});
`;
Expand Down
1 change: 1 addition & 0 deletions scenario/constraints/MigrationConstraint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class MigrationConstraint<T extends CometContext> implements StaticConstr
for (const migrationData of migrations) {
const migration = migrationData.migration;
const artifact = await migration.actions.prepare(ctx.world.deploymentManager, govDeploymentManager);
await govDeploymentManager.storeArtifact(migration, artifact);
debug(`${label} Prepared migration ${migration.name}.\n Artifact\n-------\n\n${JSON.stringify(artifact, null, 2)}\n-------\n`);
if (await isEnacted(migration.actions, ctx.world.deploymentManager, govDeploymentManager)) {
migrationData.skipVerify = true;
Expand Down
8 changes: 6 additions & 2 deletions scenario/constraints/ProposalConstraint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ export class ProposalConstraint<T extends CometContext> implements StaticConstra
try {
// If there is a migration associated with this proposal, verify the migration
if (migrationData) {
const migrationArtifact = await deploymentManager.readArtifact(migrationData.migration);
await migrationData.migration.actions.verify(
ctx.world.deploymentManager,
govDeploymentManager,
preExecutionBlockNumber
preExecutionBlockNumber,
migrationArtifact
);
migrationData.verified = true;
debug(`${label} Verified migration "${migrationData.migration.name}"`);
Expand All @@ -101,10 +103,12 @@ export class ProposalConstraint<T extends CometContext> implements StaticConstra
if (ctx.migrations) {
for (const migrationData of ctx.migrations) {
if (migrationData.verified === true || migrationData.skipVerify === true) continue;
const migrationArtifact = await deploymentManager.readArtifact(migrationData.migration);
await migrationData.migration.actions.verify(
ctx.world.deploymentManager,
govDeploymentManager,
migrationData.preMigrationBlockNumber
migrationData.preMigrationBlockNumber,
migrationArtifact
);
migrationData.verified = true;
}
Expand Down

0 comments on commit 976e43a

Please sign in to comment.