Add script for verification of evm contract upgrades (#982)
This commit is contained in:
parent
69182f29c2
commit
fafb786015
|
@ -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();
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue