deploy_evm_pricefeed_contracts.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. DeploymentType,
  7. EvmPriceFeedContract,
  8. getDefaultDeploymentConfig,
  9. PrivateKey,
  10. toDeploymentType,
  11. toPrivateKey,
  12. EvmWormholeContract,
  13. } from "../src";
  14. import {
  15. COMMON_DEPLOY_OPTIONS,
  16. deployIfNotCached,
  17. getWeb3Contract,
  18. } from "./common";
  19. type DeploymentConfig = {
  20. type: DeploymentType;
  21. validTimePeriodSeconds: number;
  22. singleUpdateFeeInWei: number;
  23. gasMultiplier: number;
  24. gasPriceMultiplier: number;
  25. privateKey: PrivateKey;
  26. jsonOutputDir: string;
  27. saveContract: boolean;
  28. };
  29. const CACHE_FILE = ".cache-deploy-evm";
  30. const parser = yargs(hideBin(process.argv))
  31. .scriptName("deploy_evm_pricefeed_contracts.ts")
  32. .usage(
  33. "Usage: $0 --std-output-dir <path/to/std-output-dir/> --private-key <private-key> --chain <chain0> --chain <chain1>"
  34. )
  35. .options({
  36. ...COMMON_DEPLOY_OPTIONS,
  37. "valid-time-period-seconds": {
  38. type: "number",
  39. demandOption: false,
  40. default: 60,
  41. desc: "Valid time period in seconds for the price feed staleness",
  42. },
  43. "single-update-fee-in-wei": {
  44. type: "number",
  45. demandOption: false,
  46. default: 1,
  47. desc: "Single update fee in wei for the price feed",
  48. },
  49. });
  50. async function deployWormholeReceiverContracts(
  51. chain: EvmChain,
  52. config: DeploymentConfig
  53. ): Promise<string> {
  54. const receiverSetupAddr = await deployIfNotCached(
  55. CACHE_FILE,
  56. chain,
  57. config,
  58. "ReceiverSetup",
  59. []
  60. );
  61. const receiverImplAddr = await deployIfNotCached(
  62. CACHE_FILE,
  63. chain,
  64. config,
  65. "ReceiverImplementation",
  66. []
  67. );
  68. // Craft the init data for the proxy contract
  69. const setupContract = getWeb3Contract(
  70. config.jsonOutputDir,
  71. "ReceiverSetup",
  72. receiverSetupAddr
  73. );
  74. const { wormholeConfig } = getDefaultDeploymentConfig(config.type);
  75. const initData = setupContract.methods
  76. .setup(
  77. receiverImplAddr,
  78. wormholeConfig.initialGuardianSet.map((addr: string) => "0x" + addr),
  79. chain.getWormholeChainId(),
  80. wormholeConfig.governanceChainId,
  81. "0x" + wormholeConfig.governanceContract
  82. )
  83. .encodeABI();
  84. const wormholeReceiverAddr = await deployIfNotCached(
  85. CACHE_FILE,
  86. chain,
  87. config,
  88. "WormholeReceiver",
  89. [receiverSetupAddr, initData]
  90. );
  91. const wormholeContract = new EvmWormholeContract(chain, wormholeReceiverAddr);
  92. if (config.type === "stable") {
  93. console.log(`Syncing mainnet guardian sets for ${chain.getId()}...`);
  94. // TODO: Add a way to pass gas configs to this
  95. await wormholeContract.syncMainnetGuardianSets(config.privateKey);
  96. console.log(`✅ Synced mainnet guardian sets for ${chain.getId()}`);
  97. }
  98. return wormholeReceiverAddr;
  99. }
  100. async function deployPriceFeedContracts(
  101. chain: EvmChain,
  102. config: DeploymentConfig,
  103. wormholeAddr: string
  104. ): Promise<string> {
  105. const pythImplAddr = await deployIfNotCached(
  106. CACHE_FILE,
  107. chain,
  108. config,
  109. "PythUpgradable",
  110. []
  111. );
  112. // Craft the init data for the proxy contract
  113. const { dataSources, governanceDataSource } = getDefaultDeploymentConfig(
  114. config.type
  115. );
  116. const pythImplContract = getWeb3Contract(
  117. config.jsonOutputDir,
  118. "PythUpgradable",
  119. pythImplAddr
  120. );
  121. const pythInitData = pythImplContract.methods
  122. .initialize(
  123. wormholeAddr,
  124. dataSources.map((ds) => ds.emitterChain),
  125. dataSources.map((ds) => "0x" + ds.emitterAddress),
  126. governanceDataSource.emitterChain,
  127. "0x" + governanceDataSource.emitterAddress,
  128. 0, // governanceInitialSequence
  129. config.validTimePeriodSeconds,
  130. config.singleUpdateFeeInWei
  131. )
  132. .encodeABI();
  133. return await deployIfNotCached(CACHE_FILE, chain, config, "ERC1967Proxy", [
  134. pythImplAddr,
  135. pythInitData,
  136. ]);
  137. }
  138. async function main() {
  139. const argv = await parser.argv;
  140. const deploymentConfig: DeploymentConfig = {
  141. type: toDeploymentType(argv.deploymentType),
  142. validTimePeriodSeconds: argv.validTimePeriodSeconds,
  143. singleUpdateFeeInWei: argv.singleUpdateFeeInWei,
  144. gasMultiplier: argv.gasMultiplier,
  145. gasPriceMultiplier: argv.gasPriceMultiplier,
  146. privateKey: toPrivateKey(argv.privateKey),
  147. jsonOutputDir: argv.stdOutputDir,
  148. saveContract: argv.saveContract,
  149. };
  150. console.log(
  151. `Deployment config: ${JSON.stringify(deploymentConfig, null, 2)}\n`
  152. );
  153. const chainNames = argv.chain;
  154. for (const chainName of chainNames) {
  155. const chain = DefaultStore.chains[chainName];
  156. if (!chain) {
  157. throw new Error(`Chain ${chainName} not found`);
  158. } else if (!(chain instanceof EvmChain)) {
  159. throw new Error(`Chain ${chainName} is not an EVM chain`);
  160. }
  161. console.log(`Deploying price feed contracts on ${chain.getId()}...`);
  162. const wormholeAddr = await deployWormholeReceiverContracts(
  163. chain,
  164. deploymentConfig
  165. );
  166. const priceFeedAddr = await deployPriceFeedContracts(
  167. chain,
  168. deploymentConfig,
  169. wormholeAddr
  170. );
  171. if (deploymentConfig.saveContract) {
  172. console.log("Saving the contract in the store...");
  173. const contract = new EvmPriceFeedContract(chain, priceFeedAddr);
  174. DefaultStore.contracts[contract.getId()] = contract;
  175. DefaultStore.saveAllContracts();
  176. }
  177. console.log(
  178. `✅ Deployed price feed contracts on ${chain.getId()} at ${priceFeedAddr}\n\n`
  179. );
  180. }
  181. }
  182. main();