소스 검색

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

Mohammad Amin Khashkhashi Moghaddam 2 년 전
부모
커밋
fafb786015
3개의 변경된 파일86개의 추가작업 그리고 2개의 파일을 삭제
  1. 79 0
      contract_manager/scripts/check_proposal.ts
  2. 0 0
      contract_manager/scripts/deploy_cosmwasm.ts
  3. 7 2
      contract_manager/src/contracts/evm.ts

+ 79 - 0
contract_manager/scripts/check_proposal.ts

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

+ 0 - 0
contract_manager/examples/deploy_cosmwasm.ts → contract_manager/scripts/deploy_cosmwasm.ts


+ 7 - 2
contract_manager/src/contracts/evm.ts

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