check_proposal.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import yargs from "yargs";
  2. import { hideBin } from "yargs/helpers";
  3. import { EvmChain } from "../src/chains";
  4. import { DefaultStore } from "../src/store";
  5. import {
  6. EvmUpgradeContract,
  7. getProposalInstructions,
  8. MultisigParser,
  9. WormholeMultisigInstruction,
  10. } from "xc_admin_common";
  11. import SquadsMesh from "@sqds/mesh";
  12. import {
  13. getPythClusterApiUrl,
  14. PythCluster,
  15. } from "@pythnetwork/client/lib/cluster";
  16. import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
  17. import { AccountMeta, Keypair, PublicKey } from "@solana/web3.js";
  18. import { EvmContract } from "../src/contracts/evm";
  19. const parser = yargs(hideBin(process.argv))
  20. .scriptName("check_proposal.ts")
  21. .usage("Usage: $0 --cluster <cluster_id> --proposal <proposal_address>")
  22. .options({
  23. cluster: {
  24. type: "string",
  25. demandOption: true,
  26. desc: "Multsig Cluster name to check proposal on can be one of [devnet, testnet, mainnet-beta]",
  27. },
  28. proposal: {
  29. type: "string",
  30. demandOption: true,
  31. desc: "The proposal address to check",
  32. },
  33. });
  34. async function main() {
  35. const argv = await parser.argv;
  36. const cluster = argv.cluster as PythCluster;
  37. const squad = SquadsMesh.endpoint(
  38. getPythClusterApiUrl(cluster),
  39. new NodeWallet(Keypair.generate()) // dummy wallet
  40. );
  41. const transaction = await squad.getTransaction(new PublicKey(argv.proposal));
  42. const instructions = await getProposalInstructions(squad, transaction);
  43. const multisigParser = MultisigParser.fromCluster(cluster);
  44. const parsedInstructions = instructions.map((instruction) => {
  45. return multisigParser.parseInstruction({
  46. programId: instruction.programId,
  47. data: instruction.data as Buffer,
  48. keys: instruction.keys as AccountMeta[],
  49. });
  50. });
  51. for (const instruction of parsedInstructions) {
  52. if (instruction instanceof WormholeMultisigInstruction) {
  53. if (instruction.governanceAction instanceof EvmUpgradeContract) {
  54. console.log(
  55. `Verifying EVM Upgrade Contract on ${instruction.governanceAction.targetChainId}`
  56. );
  57. for (const chain of Object.values(DefaultStore.chains)) {
  58. if (
  59. chain instanceof EvmChain &&
  60. chain.isMainnet() === (cluster === "mainnet-beta") &&
  61. chain.wormholeChainName ===
  62. instruction.governanceAction.targetChainId
  63. ) {
  64. const address = instruction.governanceAction.address;
  65. const contract = new EvmContract(chain, address);
  66. const code = await contract.getCodeDigestWithoutAddress();
  67. // this should be the same keccak256 of the deployedCode property generated by truffle
  68. console.log(`Address:${address} digest:${code}`);
  69. }
  70. }
  71. }
  72. }
  73. }
  74. }
  75. main();