Add script for verification of evm contract upgrades (#982)

This commit is contained in:
Mohammad Amin Khashkhashi Moghaddam 2023-07-25 16:21:07 +02:00 committed by GitHub
parent 69182f29c2
commit fafb786015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 2 deletions

View File

@ -0,0 +1,79 @@
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { EvmChain } from "../src/chains";
import { DefaultStore } from "../src/store";
import {
EvmUpgradeContract,
getProposalInstructions,
MultisigParser,
WormholeMultisigInstruction,
} from "xc_admin_common";
import SquadsMesh from "@sqds/mesh";
import {
getPythClusterApiUrl,
PythCluster,
} from "@pythnetwork/client/lib/cluster";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { AccountMeta, Keypair, PublicKey } from "@solana/web3.js";
import { EvmContract } from "../src/contracts/evm";
const parser = yargs(hideBin(process.argv))
.scriptName("check_proposal.ts")
.usage("Usage: $0 --cluster <cluster_id> --proposal <proposal_address>")
.options({
cluster: {
type: "string",
demandOption: true,
desc: "Multsig Cluster name to check proposal on can be one of [devnet, testnet, mainnet-beta]",
},
proposal: {
type: "string",
demandOption: true,
desc: "The proposal address to check",
},
});
async function main() {
const argv = await parser.argv;
const cluster = argv.cluster as PythCluster;
const squad = SquadsMesh.endpoint(
getPythClusterApiUrl(cluster),
new NodeWallet(Keypair.generate()) // dummy wallet
);
const transaction = await squad.getTransaction(new PublicKey(argv.proposal));
const instructions = await getProposalInstructions(squad, transaction);
const multisigParser = MultisigParser.fromCluster(cluster);
const parsedInstructions = instructions.map((instruction) => {
return multisigParser.parseInstruction({
programId: instruction.programId,
data: instruction.data as Buffer,
keys: instruction.keys as AccountMeta[],
});
});
for (const instruction of parsedInstructions) {
if (instruction instanceof WormholeMultisigInstruction) {
if (instruction.governanceAction instanceof EvmUpgradeContract) {
console.log(
`Verifying EVM Upgrade Contract on ${instruction.governanceAction.targetChainId}`
);
for (const chain of Object.values(DefaultStore.chains)) {
if (
chain instanceof EvmChain &&
chain.isMainnet() === (cluster === "mainnet-beta") &&
chain.wormholeChainName ===
instruction.governanceAction.targetChainId
) {
const address = instruction.governanceAction.address;
const contract = new EvmContract(chain, address);
const code = await contract.getCodeDigestWithoutAddress();
// this should be the same keccak256 of the deployedCode property generated by truffle
console.log(`Address:${address} digest:${code}`);
}
}
}
}
}
}
main();

View File

@ -284,8 +284,13 @@ export class EvmContract extends Contract {
}
/**
* Returns the keccak256 digest of the contract bytecode after replacing any occurences of the contract addr in the bytecode with 0
* This is used to verify that the contract code is the same on all chains
* Returns the keccak256 digest of the contract bytecode after replacing any occurrences of the contract addr in
* the bytecode with 0.The bytecode stores the deployment address as an immutable variable.
* This behavior is inherited from OpenZeppelin's implementation of UUPSUpgradeable contract.
* You can read more about verification with immutable variables here:
* https://docs.sourcify.dev/docs/immutables/
* This function can be used to verify that the contract code is the same on all chains and matches
* with the deployedCode property generated by truffle builds
*/
async getCodeDigestWithoutAddress(): Promise<string> {
const code = await this.getCode();