From 587a6fa524543c46ae4f89daf5a899bd16f1a839 Mon Sep 17 00:00:00 2001 From: Dev Kalra Date: Thu, 2 May 2024 16:48:16 +0530 Subject: [PATCH] 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 --- contract_manager/scripts/common.ts | 128 +++++++++++++++++- .../scripts/deploy_evm_entropy_contracts.ts | 58 +++----- .../scripts/deploy_evm_pricefeed_contracts.ts | 79 ++--------- contract_manager/store/chains/EvmChains.yaml | 5 + .../contracts/CosmWasmWormholeContracts.yaml | 3 + .../store/contracts/EvmEntropyContracts.yaml | 3 + .../contracts/EvmPriceFeedContracts.yaml | 5 +- .../store/contracts/EvmWormholeContracts.yaml | 6 + .../packages/xc_admin_common/src/chains.ts | 3 +- target_chains/ethereum/sdk/js/package.json | 2 +- target_chains/ethereum/sdk/js/src/index.ts | 3 +- 11 files changed, 177 insertions(+), 118 deletions(-) diff --git a/contract_manager/scripts/common.ts b/contract_manager/scripts/common.ts index bf90e3f1..010c1e48 100644 --- a/contract_manager/scripts/common.ts +++ b/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 { + 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 { + return ( + findWormholeContract(chain) ?? + (await deployWormholeContract(chain, config, cacheFile)) + ); +} diff --git a/contract_manager/scripts/deploy_evm_entropy_contracts.ts b/contract_manager/scripts/deploy_evm_entropy_contracts.ts index 3c394830..d8ba5b87 100644 --- a/contract_manager/scripts/deploy_evm_entropy_contracts.ts +++ b/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 { 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 { - 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, diff --git a/contract_manager/scripts/deploy_evm_pricefeed_contracts.ts b/contract_manager/scripts/deploy_evm_pricefeed_contracts.ts index 8121dc4b..6f48074a 100644 --- a/contract_manager/scripts/deploy_evm_pricefeed_contracts.ts +++ b/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 { - 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) { diff --git a/contract_manager/store/chains/EvmChains.yaml b/contract_manager/store/chains/EvmChains.yaml index cab8f847..7b1d0431 100644 --- a/contract_manager/store/chains/EvmChains.yaml +++ b/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 diff --git a/contract_manager/store/contracts/CosmWasmWormholeContracts.yaml b/contract_manager/store/contracts/CosmWasmWormholeContracts.yaml index fce1d07a..67140690 100644 --- a/contract_manager/store/contracts/CosmWasmWormholeContracts.yaml +++ b/contract_manager/store/contracts/CosmWasmWormholeContracts.yaml @@ -43,3 +43,6 @@ - chain: injective address: inj17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9l2q74d type: CosmWasmWormholeContract +- chain: xion_testnet + address: xion14ycw3tx0hpz3aawmzm6cufs6hx94d64ht5qawd0ej9ug9j2ffzsqmpecys + type: CosmWasmWormholeContract diff --git a/contract_manager/store/contracts/EvmEntropyContracts.yaml b/contract_manager/store/contracts/EvmEntropyContracts.yaml index 6c4029e2..c4ae35b6 100644 --- a/contract_manager/store/contracts/EvmEntropyContracts.yaml +++ b/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 diff --git a/contract_manager/store/contracts/EvmPriceFeedContracts.yaml b/contract_manager/store/contracts/EvmPriceFeedContracts.yaml index ce99c476..2a271f19 100644 --- a/contract_manager/store/contracts/EvmPriceFeedContracts.yaml +++ b/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 diff --git a/contract_manager/store/contracts/EvmWormholeContracts.yaml b/contract_manager/store/contracts/EvmWormholeContracts.yaml index 1bf4e403..f3dde16e 100644 --- a/contract_manager/store/contracts/EvmWormholeContracts.yaml +++ b/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 diff --git a/governance/xc_admin/packages/xc_admin_common/src/chains.ts b/governance/xc_admin/packages/xc_admin_common/src/chains.ts index bdec200c..cd432eb4 100644 --- a/governance/xc_admin/packages/xc_admin_common/src/chains.ts +++ b/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 diff --git a/target_chains/ethereum/sdk/js/package.json b/target_chains/ethereum/sdk/js/package.json index b35486b6..2e66a9f2 100644 --- a/target_chains/ethereum/sdk/js/package.json +++ b/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": { diff --git a/target_chains/ethereum/sdk/js/src/index.ts b/target_chains/ethereum/sdk/js/src/index.ts index b12371b1..e0971eea 100644 --- a/target_chains/ethereum/sdk/js/src/index.ts +++ b/target_chains/ethereum/sdk/js/src/index.ts @@ -103,7 +103,7 @@ export const CONTRACT_ADDR: Record = { 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 = { scroll_sepolia: "0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c", sepolia: "0xDd24F84d36BF92C65F92307595335bdFab5Bbd21", shimmer_testnet: "0x8D254a21b3C86D32F7179855531CE99164721933", + taiko_hekla: "0x2880aB155794e7179c9eE2e38200202908C17B43", viction_testnet: "0x5D289Ad1CE59fCC25b6892e7A303dfFf3a9f7167", wemix_testnet: "0x26DD80569a8B23768A1d80869Ed7339e07595E85", zetachain_testnet: "0x0708325268dF9F66270F1401206434524814508b",