upgrade_evm_entropy_contracts.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import yargs from "yargs";
  2. import { hideBin } from "yargs/helpers";
  3. import { DefaultStore } from "../src/node/utils/store";
  4. import { loadHotWallet } from "../src/node/utils/governance";
  5. import { toPrivateKey } from "../src/core/base";
  6. import { readFileSync } from "fs";
  7. import { PythCluster } from "@pythnetwork/client/lib/cluster";
  8. import {
  9. COMMON_UPGRADE_OPTIONS,
  10. getSelectedChains,
  11. makeCacheFunction,
  12. } from "./common";
  13. const EXECUTOR_CACHE_FILE = ".cache-upgrade-evm-executor-contract";
  14. const ENTROPY_CACHE_FILE = ".cache-upgrade-evm-entropy-contract";
  15. const parser = yargs(hideBin(process.argv))
  16. .usage(
  17. "Deploys a new Upgradeable contract for Executor or Entropy to a set of chains where Entropy is deployed and creates a governance proposal for it.\n" +
  18. `Uses a cache file to avoid deploying contracts twice\n` +
  19. "Usage: $0 --chain <chain_1> --chain <chain_2> --private-key <private_key> --ops-key-path <ops_key_path> --std-output <std_output>",
  20. )
  21. .options({
  22. ...COMMON_UPGRADE_OPTIONS,
  23. "contract-type": {
  24. type: "string",
  25. choices: ["executor", "entropy"],
  26. demandOption: true,
  27. },
  28. });
  29. // Override these URLs to use a different RPC node for mainnet / testnet.
  30. // TODO: extract these RPCs to a config file (?)
  31. const RPCS = {
  32. "mainnet-beta": "https://api.mainnet-beta.solana.com",
  33. testnet: "https://api.testnet.solana.com",
  34. devnet: "https://api.devnet.solana.com",
  35. } as Record<PythCluster, string>;
  36. function registry(cluster: PythCluster): string {
  37. return RPCS[cluster];
  38. }
  39. async function main() {
  40. const argv = await parser.argv;
  41. const cacheFile =
  42. argv["contract-type"] === "executor"
  43. ? EXECUTOR_CACHE_FILE
  44. : ENTROPY_CACHE_FILE;
  45. const runIfNotCached = makeCacheFunction(cacheFile);
  46. const selectedChains = getSelectedChains(argv);
  47. const vault =
  48. DefaultStore.vaults[
  49. "mainnet-beta_FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj"
  50. ];
  51. console.log("Using cache file", cacheFile);
  52. // Try to deploy on every chain, then collect any failures at the end. This logic makes it simpler to
  53. // identify deployment problems (e.g., not enough gas) on every chain where they occur.
  54. const payloads: Buffer[] = [];
  55. const failures: string[] = [];
  56. for (const contract of Object.values(DefaultStore.entropy_contracts)) {
  57. if (selectedChains.includes(contract.chain)) {
  58. const artifact = JSON.parse(readFileSync(argv["std-output"], "utf8"));
  59. console.log("Deploying contract to", contract.chain.getId());
  60. try {
  61. const address = await runIfNotCached(
  62. `deploy-${contract.chain.getId()}`,
  63. () => {
  64. return contract.chain.deploy(
  65. toPrivateKey(argv["private-key"]),
  66. artifact["abi"],
  67. artifact["bytecode"].object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
  68. [],
  69. 2,
  70. );
  71. },
  72. );
  73. console.log(
  74. `Deployed contract at ${address} on ${contract.chain.getId()}`,
  75. );
  76. const payload =
  77. argv["contract-type"] === "executor"
  78. ? await contract.generateUpgradeExecutorContractsPayload(address)
  79. : await contract.generateUpgradeEntropyContractPayload(address);
  80. console.log(payload.toString("hex"));
  81. payloads.push(payload);
  82. } catch (e) {
  83. console.log(`error deploying: ${e}`);
  84. failures.push(contract.chain.getId());
  85. }
  86. }
  87. }
  88. if (failures.length > 0) {
  89. throw new Error(
  90. `Some chains could not be deployed: ${failures.join(
  91. ", ",
  92. )}. Scroll up to see the errors from each chain.`,
  93. );
  94. }
  95. console.log("Using vault at for proposal", vault.getId());
  96. const wallet = await loadHotWallet(argv["ops-key-path"]);
  97. console.log("Using wallet ", wallet.publicKey.toBase58());
  98. vault.connect(wallet, registry);
  99. const proposal = await vault.proposeWormholeMessage(payloads);
  100. console.log("Proposal address", proposal.address.toBase58());
  101. }
  102. main();