Ver Fonte

feat(contract_manager): upgrade deploy scripts to use wormhole store (#1523)

* upgrade deploy scripts to use wormhole store

* deploy not find

* deploy price feed and entropy to taiko

* rename type

* rename method

* address feedback

* update js docs

* deploy to olive testnet

* pre commit

* rename deploy config to base deploy config
Dev Kalra há 1 ano atrás
pai
commit
587a6fa524

+ 125 - 3
contract_manager/scripts/common.ts

@@ -1,11 +1,18 @@
-import { DefaultStore, EvmChain, EvmEntropyContract, PrivateKey } from "../src";
+import {
+  DefaultStore,
+  EvmChain,
+  EvmEntropyContract,
+  EvmWormholeContract,
+  getDefaultDeploymentConfig,
+  PrivateKey,
+} from "../src";
 import { existsSync, readFileSync, writeFileSync } from "fs";
 import { join } from "path";
 import Web3 from "web3";
 import { Contract } from "web3-eth-contract";
 import { InferredOptionType } from "yargs";
 
-interface DeployConfig {
+export interface BaseDeployConfig {
   gasMultiplier: number;
   gasPriceMultiplier: number;
   jsonOutputDir: string;
@@ -19,7 +26,7 @@ interface DeployConfig {
 export async function deployIfNotCached(
   cacheFile: string,
   chain: EvmChain,
-  config: DeployConfig,
+  config: BaseDeployConfig,
   artifactName: string,
   deployArgs: any[], // eslint-disable-line  @typescript-eslint/no-explicit-any
   cacheKey?: string
@@ -212,3 +219,118 @@ export function findEvmChain(chainName: string): EvmChain {
   }
   return chain;
 }
+
+/**
+ * Finds the wormhole contract for a given EVM chain.
+ * @param {EvmChain} chain The EVM chain to find the wormhole contract for.
+ * @returns If found, the wormhole contract for the given EVM chain. Else, undefined
+ */
+export function findWormholeContract(
+  chain: EvmChain
+): EvmWormholeContract | undefined {
+  for (const contract of Object.values(DefaultStore.wormhole_contracts)) {
+    if (
+      contract instanceof EvmWormholeContract &&
+      contract.getChain().getId() === chain.getId()
+    ) {
+      return contract;
+    }
+  }
+}
+
+export interface DeployWormholeReceiverContractsConfig
+  extends BaseDeployConfig {
+  saveContract: boolean;
+  type: "stable" | "beta";
+}
+/**
+ * Deploys the wormhole receiver contract for a given EVM chain.
+ * @param {EvmChain} chain The EVM chain to find the wormhole receiver contract for.
+ * @param {DeployWormholeReceiverContractsConfig} config The deployment configuration.
+ * @param {string} cacheFile The path to the cache file.
+ * @returns {EvmWormholeContract} The wormhole contract for the given EVM chain.
+ */
+export async function deployWormholeContract(
+  chain: EvmChain,
+  config: DeployWormholeReceiverContractsConfig,
+  cacheFile: string
+): Promise<EvmWormholeContract> {
+  const receiverSetupAddr = await deployIfNotCached(
+    cacheFile,
+    chain,
+    config,
+    "ReceiverSetup",
+    []
+  );
+
+  const receiverImplAddr = await deployIfNotCached(
+    cacheFile,
+    chain,
+    config,
+    "ReceiverImplementation",
+    []
+  );
+
+  // Craft the init data for the proxy contract
+  const setupContract = getWeb3Contract(
+    config.jsonOutputDir,
+    "ReceiverSetup",
+    receiverSetupAddr
+  );
+
+  const { wormholeConfig } = getDefaultDeploymentConfig(config.type);
+
+  const initData = setupContract.methods
+    .setup(
+      receiverImplAddr,
+      wormholeConfig.initialGuardianSet.map((addr: string) => "0x" + addr),
+      chain.getWormholeChainId(),
+      wormholeConfig.governanceChainId,
+      "0x" + wormholeConfig.governanceContract
+    )
+    .encodeABI();
+
+  const wormholeReceiverAddr = await deployIfNotCached(
+    cacheFile,
+    chain,
+    config,
+    "WormholeReceiver",
+    [receiverSetupAddr, initData]
+  );
+
+  const wormholeContract = new EvmWormholeContract(chain, wormholeReceiverAddr);
+
+  if (config.type === "stable") {
+    console.log(`Syncing mainnet guardian sets for ${chain.getId()}...`);
+    // TODO: Add a way to pass gas configs to this
+    await wormholeContract.syncMainnetGuardianSets(config.privateKey);
+    console.log(`✅ Synced mainnet guardian sets for ${chain.getId()}`);
+  }
+
+  if (config.saveContract) {
+    DefaultStore.wormhole_contracts[wormholeContract.getId()] =
+      wormholeContract;
+    DefaultStore.saveAllContracts();
+  }
+
+  return wormholeContract;
+}
+
+/**
+ * Returns the wormhole contract for a given EVM chain.
+ * If there was no wormhole contract deployed for the given chain, it will deploy the wormhole contract and save it to the default store.
+ * @param {EvmChain} chain The EVM chain to find the wormhole contract for.
+ * @param {DeployWormholeReceiverContractsConfig} config The deployment configuration.
+ * @param {string} cacheFile The path to the cache file.
+ * @returns {EvmWormholeContract} The wormhole contract for the given EVM chain.
+ */
+export async function getOrDeployWormholeContract(
+  chain: EvmChain,
+  config: DeployWormholeReceiverContractsConfig,
+  cacheFile: string
+): Promise<EvmWormholeContract> {
+  return (
+    findWormholeContract(chain) ??
+    (await deployWormholeContract(chain, config, cacheFile))
+  );
+}

+ 17 - 41
contract_manager/scripts/deploy_evm_entropy_contracts.ts

@@ -5,29 +5,23 @@ import { DefaultStore } from "../src/store";
 import {
   DeploymentType,
   EvmEntropyContract,
-  EvmPriceFeedContract,
   getDefaultDeploymentConfig,
-  PrivateKey,
   toDeploymentType,
   toPrivateKey,
-  EvmWormholeContract,
 } from "../src";
 import {
   COMMON_DEPLOY_OPTIONS,
   deployIfNotCached,
   getWeb3Contract,
+  getOrDeployWormholeContract,
+  BaseDeployConfig,
 } from "./common";
 import Web3 from "web3";
 
-type DeploymentConfig = {
+interface DeploymentConfig extends BaseDeployConfig {
   type: DeploymentType;
-  gasMultiplier: number;
-  gasPriceMultiplier: number;
-  privateKey: PrivateKey;
-  jsonOutputDir: string;
-  wormholeAddr: string;
   saveContract: boolean;
-};
+}
 
 const CACHE_FILE = ".cache-deploy-evm-entropy-contracts";
 const ENTROPY_DEFAULT_PROVIDER = {
@@ -51,7 +45,8 @@ const parser = yargs(hideBin(process.argv))
 
 async function deployExecutorContracts(
   chain: EvmChain,
-  config: DeploymentConfig
+  config: DeploymentConfig,
+  wormholeAddr: string
 ): Promise<string> {
   const executorImplAddr = await deployIfNotCached(
     CACHE_FILE,
@@ -72,7 +67,7 @@ async function deployExecutorContracts(
 
   const executorInitData = executorImplContract.methods
     .initialize(
-      config.wormholeAddr,
+      wormholeAddr,
       0, // lastExecutedSequence,
       chain.getWormholeChainId(),
       governanceDataSource.emitterChain,
@@ -161,19 +156,6 @@ async function topupProviderIfNecessary(
   }
 }
 
-async function findWormholeAddress(
-  chain: EvmChain
-): Promise<string | undefined> {
-  for (const contract of Object.values(DefaultStore.contracts)) {
-    if (
-      contract instanceof EvmPriceFeedContract &&
-      contract.getChain().getId() === chain.getId()
-    ) {
-      return (await contract.getWormholeContract()).address;
-    }
-  }
-}
-
 async function main() {
   const argv = await parser.argv;
 
@@ -185,12 +167,6 @@ async function main() {
     throw new Error(`Chain ${chainName} is not an EVM chain`);
   }
 
-  const wormholeAddr = await findWormholeAddress(chain);
-  if (!wormholeAddr) {
-    // TODO: deploy wormhole if necessary and maintain a wormhole store
-    throw new Error(`Wormhole contract not found for chain ${chain.getId()}`);
-  }
-
   const deploymentConfig: DeploymentConfig = {
     type: toDeploymentType(argv.deploymentType),
     gasMultiplier: argv.gasMultiplier,
@@ -198,18 +174,14 @@ async function main() {
     privateKey: toPrivateKey(argv.privateKey),
     jsonOutputDir: argv.stdOutputDir,
     saveContract: argv.saveContract,
-    wormholeAddr,
   };
-  const wormholeContract = new EvmWormholeContract(
+
+  const wormholeContract = await getOrDeployWormholeContract(
     chain,
-    deploymentConfig.wormholeAddr
+    deploymentConfig,
+    CACHE_FILE
   );
-  const wormholeChainId = await wormholeContract.getChainId();
-  if (chain.getWormholeChainId() != wormholeChainId) {
-    throw new Error(
-      `Wormhole chain id mismatch. Expected ${chain.getWormholeChainId()} but got ${wormholeChainId}`
-    );
-  }
+
   await topupProviderIfNecessary(chain, deploymentConfig);
 
   console.log(
@@ -218,7 +190,11 @@ async function main() {
 
   console.log(`Deploying entropy contracts on ${chain.getId()}...`);
 
-  const executorAddr = await deployExecutorContracts(chain, deploymentConfig);
+  const executorAddr = await deployExecutorContracts(
+    chain,
+    deploymentConfig,
+    wormholeContract.address
+  );
   const entropyAddr = await deployEntropyContracts(
     chain,
     deploymentConfig,

+ 9 - 70
contract_manager/scripts/deploy_evm_pricefeed_contracts.ts

@@ -6,27 +6,23 @@ import {
   DeploymentType,
   EvmPriceFeedContract,
   getDefaultDeploymentConfig,
-  PrivateKey,
   toDeploymentType,
   toPrivateKey,
-  EvmWormholeContract,
 } from "../src";
 import {
   COMMON_DEPLOY_OPTIONS,
   deployIfNotCached,
   getWeb3Contract,
+  getOrDeployWormholeContract,
+  BaseDeployConfig,
 } from "./common";
 
-type DeploymentConfig = {
+interface DeploymentConfig extends BaseDeployConfig {
   type: DeploymentType;
   validTimePeriodSeconds: number;
   singleUpdateFeeInWei: number;
-  gasMultiplier: number;
-  gasPriceMultiplier: number;
-  privateKey: PrivateKey;
-  jsonOutputDir: string;
   saveContract: boolean;
-};
+}
 
 const CACHE_FILE = ".cache-deploy-evm";
 
@@ -51,65 +47,6 @@ const parser = yargs(hideBin(process.argv))
     },
   });
 
-async function deployWormholeReceiverContracts(
-  chain: EvmChain,
-  config: DeploymentConfig
-): Promise<string> {
-  const receiverSetupAddr = await deployIfNotCached(
-    CACHE_FILE,
-    chain,
-    config,
-    "ReceiverSetup",
-    []
-  );
-
-  const receiverImplAddr = await deployIfNotCached(
-    CACHE_FILE,
-    chain,
-    config,
-    "ReceiverImplementation",
-    []
-  );
-
-  // Craft the init data for the proxy contract
-  const setupContract = getWeb3Contract(
-    config.jsonOutputDir,
-    "ReceiverSetup",
-    receiverSetupAddr
-  );
-
-  const { wormholeConfig } = getDefaultDeploymentConfig(config.type);
-
-  const initData = setupContract.methods
-    .setup(
-      receiverImplAddr,
-      wormholeConfig.initialGuardianSet.map((addr: string) => "0x" + addr),
-      chain.getWormholeChainId(),
-      wormholeConfig.governanceChainId,
-      "0x" + wormholeConfig.governanceContract
-    )
-    .encodeABI();
-
-  const wormholeReceiverAddr = await deployIfNotCached(
-    CACHE_FILE,
-    chain,
-    config,
-    "WormholeReceiver",
-    [receiverSetupAddr, initData]
-  );
-
-  const wormholeContract = new EvmWormholeContract(chain, wormholeReceiverAddr);
-
-  if (config.type === "stable") {
-    console.log(`Syncing mainnet guardian sets for ${chain.getId()}...`);
-    // TODO: Add a way to pass gas configs to this
-    await wormholeContract.syncMainnetGuardianSets(config.privateKey);
-    console.log(`✅ Synced mainnet guardian sets for ${chain.getId()}`);
-  }
-
-  return wormholeReceiverAddr;
-}
-
 async function deployPriceFeedContracts(
   chain: EvmChain,
   config: DeploymentConfig,
@@ -183,14 +120,16 @@ async function main() {
 
     console.log(`Deploying price feed contracts on ${chain.getId()}...`);
 
-    const wormholeAddr = await deployWormholeReceiverContracts(
+    const wormholeContract = await getOrDeployWormholeContract(
       chain,
-      deploymentConfig
+      deploymentConfig,
+      CACHE_FILE
     );
+
     const priceFeedAddr = await deployPriceFeedContracts(
       chain,
       deploymentConfig,
-      wormholeAddr
+      wormholeContract.address
     );
 
     if (deploymentConfig.saveContract) {

+ 5 - 0
contract_manager/store/chains/EvmChains.yaml

@@ -569,3 +569,8 @@
   rpcUrl: https://olive-network-testnet.rpc.caldera.xyz/http
   networkId: 8101902
   type: EvmChain
+- id: taiko_hekla
+  mainnet: false
+  rpcUrl: https://rpc.hekla.taiko.xyz/
+  networkId: 167009
+  type: EvmChain

+ 3 - 0
contract_manager/store/contracts/CosmWasmWormholeContracts.yaml

@@ -43,3 +43,6 @@
 - chain: injective
   address: inj17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9l2q74d
   type: CosmWasmWormholeContract
+- chain: xion_testnet
+  address: xion14ycw3tx0hpz3aawmzm6cufs6hx94d64ht5qawd0ej9ug9j2ffzsqmpecys
+  type: CosmWasmWormholeContract

+ 3 - 0
contract_manager/store/contracts/EvmEntropyContracts.yaml

@@ -61,3 +61,6 @@
 - chain: sei_evm_devnet
   address: "0x23f0e8FAeE7bbb405E7A7C3d60138FCfd43d7509"
   type: EvmEntropyContract
+- chain: taiko_hekla
+  address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603"
+  type: EvmEntropyContract

+ 4 - 1
contract_manager/store/contracts/EvmPriceFeedContracts.yaml

@@ -316,6 +316,9 @@
 - chain: flow_previewnet
   address: "0x2880aB155794e7179c9eE2e38200202908C17B43"
   type: EvmPriceFeedContract
-- chain: olive_testnet
+- chain: taiko_hekla
   address: "0x2880aB155794e7179c9eE2e38200202908C17B43"
   type: EvmPriceFeedContract
+- chain: olive_testnet
+  address: "0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c"
+  type: EvmPriceFeedContract

+ 6 - 0
contract_manager/store/contracts/EvmWormholeContracts.yaml

@@ -295,3 +295,9 @@
 - chain: linea_goerli
   address: "0xfA25E653b44586dBbe27eE9d252192F0e4956683"
   type: EvmWormholeContract
+- chain: taiko_hekla
+  address: "0xb27e5ca259702f209a29225d0eDdC131039C9933"
+  type: EvmWormholeContract
+- chain: olive_testnet
+  address: "0x74f09cb3c7e2A01865f424FD14F6dc9A14E3e94E"
+  type: EvmWormholeContract

+ 2 - 1
governance/xc_admin/packages/xc_admin_common/src/chains.ts

@@ -145,7 +145,8 @@ export const RECEIVER_CHAINS = {
   boba_sepolia: 50068,
   astar_zkyoto_testnet: 50069,
   xion_testnet: 50070,
-  olive_testnet: 50071,
+  taiko_hekla: 50071,
+  olive_testnet: 50072,
 };
 
 // If there is any overlapping value the receiver chain will replace the wormhole

+ 1 - 1
target_chains/ethereum/sdk/js/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@pythnetwork/pyth-evm-js",
-  "version": "1.45.0",
+  "version": "1.46.0",
   "description": "Pyth Network EVM Utils in JS",
   "homepage": "https://pyth.network",
   "author": {

+ 2 - 1
target_chains/ethereum/sdk/js/src/index.ts

@@ -103,7 +103,7 @@ export const CONTRACT_ADDR: Record<string, string> = {
   movement_evm_devnet: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729",
   mumbai: "0xFC6bd9F9f0c6481c6Af3A7Eb46b296A5B85ed379",
   neon_devnet: "0x0708325268dF9F66270F1401206434524814508b",
-  olive_testnet: "0x2880aB155794e7179c9eE2e38200202908C17B43",
+  olive_testnet: "0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c",
   optimism_celestia_raspberry: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729",
   optimism_goerli: "0xDd24F84d36BF92C65F92307595335bdFab5Bbd21",
   optimism_sepolia: "0x0708325268dF9F66270F1401206434524814508b",
@@ -116,6 +116,7 @@ export const CONTRACT_ADDR: Record<string, string> = {
   scroll_sepolia: "0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c",
   sepolia: "0xDd24F84d36BF92C65F92307595335bdFab5Bbd21",
   shimmer_testnet: "0x8D254a21b3C86D32F7179855531CE99164721933",
+  taiko_hekla: "0x2880aB155794e7179c9eE2e38200202908C17B43",
   viction_testnet: "0x5D289Ad1CE59fCC25b6892e7A303dfFf3a9f7167",
   wemix_testnet: "0x26DD80569a8B23768A1d80869Ed7339e07595E85",
   zetachain_testnet: "0x0708325268dF9F66270F1401206434524814508b",