From 485471a57ab0d0ed7f1e6efa6393c3f837bba6ed Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 19 Jul 2023 22:32:05 +0200 Subject: [PATCH] fix: templates (#18) --- tasks/omnichain.ts | 71 +------------------ templates/messaging/tasks/deploy.ts.hbs | 52 ++++++-------- templates/messaging/tasks/interact.ts.hbs | 6 +- .../contracts/{{contractName}}.sol.hbs | 2 + templates/omnichain/tasks/deploy.ts.hbs | 4 +- templates/omnichain/tasks/interact.ts.hbs | 29 ++------ 6 files changed, 39 insertions(+), 125 deletions(-) diff --git a/tasks/omnichain.ts b/tasks/omnichain.ts index a9c64292..ad515fbe 100644 --- a/tasks/omnichain.ts +++ b/tasks/omnichain.ts @@ -1,77 +1,12 @@ import * as fs from "fs"; -import * as handlebars from "handlebars"; import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import * as path from "path"; -const sanitizeSolidityFunctionName = (str: string): string => { - // Remove any character that's not alphanumeric or underscore - const cleaned = str.replace(/[^a-zA-Z0-9_]/g, ""); - - // If the first character is a digit, prepend with an underscore - return cleaned.match(/^\d/) ? `_${cleaned}` : cleaned; -}; - -const processTemplates = async ( - templateDir: string, - outputDir: string, - data: Record -): Promise => { - try { - templateDir = path.resolve(__dirname, templateDir); - - const files = fs.readdirSync(templateDir); - - for (const file of files) { - const templatePath = path.join(templateDir, file); - - // Compiling filename as a template - const filenameTemplate = handlebars.compile(file); - const filename = filenameTemplate(data); - - // Replacing .hbs extension if the file was a handlebars template - const outputPath = path.join(outputDir, filename.replace(".hbs", "")); - - fs.mkdirSync(path.dirname(outputPath), { recursive: true }); - - if (fs.lstatSync(templatePath).isDirectory()) { - // If file is a directory, recursively process it - await processTemplates(templatePath, outputPath, data); - } else if (path.extname(file) === ".hbs") { - const templateContent = fs.readFileSync(templatePath, "utf-8"); - const template = handlebars.compile(templateContent); - const outputContent = template(data); - fs.writeFileSync(outputPath, outputContent); - } else { - fs.copyFileSync(templatePath, outputPath); - } - } - } catch (error) { - console.error(`Error processing templates: ${error}`); - } -}; +import { processTemplates } from "../lib"; const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - const templateDir = path.resolve(__dirname, "..", "templates", "omnichain"); - const outputDir = path.resolve(process.cwd()); - const argsList = args.arguments || []; - const names = argsList.map((i: string) => i.split(":")[0]); - const types = argsList.map((i: string) => { - let parts = i.split(":"); - // If there's a type and it's not empty, use it; if not, default to "bytes32" - let t = - parts.length > 1 && parts[1].trim() !== "" ? parts[1].trim() : "bytes32"; - return t; - }); - const pairs = names.map((v: string, i: string) => [v, types[i]]); - - const data = { - args, - arguments: { names, pairs, types }, - contractName: sanitizeSolidityFunctionName(args.name), - }; - - processTemplates(templateDir, outputDir, data); + processTemplates("omnichain", args); const configPath = path.resolve(process.cwd(), "hardhat.config.ts"); let hardhatConfigContents = fs.readFileSync(configPath, "utf8"); @@ -89,7 +24,7 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { export const omnichainTask = task( "omnichain", - "Generate code for an omnichain smart contract", + "Generate code for an omnichain contract", main ) .addPositionalParam("name", "Name of the contract") diff --git a/templates/messaging/tasks/deploy.ts.hbs b/templates/messaging/tasks/deploy.ts.hbs index b120d932..283e1259 100644 --- a/templates/messaging/tasks/deploy.ts.hbs +++ b/templates/messaging/tasks/deploy.ts.hbs @@ -1,7 +1,8 @@ -import { getAddress, getChainId } from "@zetachain/addresses"; +import { getAddress } from "@zetachain/protocol-contracts"; import { ethers } from "ethers"; import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { getSupportedNetworks } from "@zetachain/networks"; const contractName = "{{contractName}}"; @@ -23,7 +24,7 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { // Initialize a wallet using a network configuration and a private key from // environment variables. const initWallet = (hre: HardhatRuntimeEnvironment, networkName: string) => { - const { url } = hre.config.networks[networkName]; + const { url } = hre.config.networks[networkName] as any; const provider = new ethers.providers.JsonRpcProvider(url); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY as string, provider); @@ -38,41 +39,30 @@ const deployContract = async ( networkName: string ) => { const wallet = initWallet(hre, networkName); - const zetaNetwork = "athens"; - const connectorAddress = getAddress({ - address: "connector", - networkName, - zetaNetwork, - }); - const zetaTokenAddress = getAddress({ - address: "zetaToken", - networkName, - zetaNetwork, - }); - const zetaTokenConsumerV2 = getAddress({ - address: "zetaTokenConsumerUniV2", - networkName, - zetaNetwork, - }); - const zetaTokenConsumerV3 = getAddress({ - address: "zetaTokenConsumerUniV3", - networkName, - zetaNetwork, - }); + + const connector = getAddress("connector", networkName as any); + const zetaToken = getAddress("zetaToken", networkName as any); + const zetaTokenConsumerUniV2 = getAddress( + "zetaTokenConsumerUniV2", + networkName as any + ); + const zetaTokenConsumerUniV3 = getAddress( + "zetaTokenConsumerUniV3", + networkName as any + ); const { abi, bytecode } = await hre.artifacts.readArtifact(contractName); const factory = new ethers.ContractFactory(abi, bytecode, wallet); const contract = await factory.deploy( - connectorAddress, - zetaTokenAddress, - zetaTokenConsumerV2 || zetaTokenConsumerV3 + connector, + zetaToken, + zetaTokenConsumerUniV2 || zetaTokenConsumerUniV3 ); await contract.deployed(); console.log(` 🚀 Successfully deployed contract on ${networkName}. -📜 Contract address: ${contract.address} -`); +📜 Contract address: ${contract.address}`); return contract.address; }; @@ -102,7 +92,7 @@ const setInteractors = async ( ["address"], [contracts[counterparty]] ); - const chainId = getChainId(counterparty as any); + const chainId = hre.config.networks[counterparty].chainId; await ( await contract.setInteractorByChainId(chainId, counterpartyContract) ).wait(); @@ -114,5 +104,7 @@ const setInteractors = async ( task("deploy", "Deploy the contract", main).addParam( "networks", - "Comma separated list of networks to deploy to" + `Comma separated list of networks to deploy to (e.g. ${getSupportedNetworks( + "ccm" + )})` ); diff --git a/templates/messaging/tasks/interact.ts.hbs b/templates/messaging/tasks/interact.ts.hbs index 3fadd3ba..e7bb025e 100644 --- a/templates/messaging/tasks/interact.ts.hbs +++ b/templates/messaging/tasks/interact.ts.hbs @@ -13,15 +13,15 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { const tx = await contract .connect(signer) - .sendHelloWorld(args.destination, { value: parseEther(args.amount) }); + .sendMessage(args.destination, { value: parseEther(args.amount) }); const receipt = await tx.wait(); - console.log(`✅ "sendHelloWorld" transaction has been broadcasted to ${hre.network.name} + console.log(`✅ The transaction has been broadcasted to ${hre.network.name} 📝 Transaction hash: ${receipt.transactionHash} Please, refer to ZetaChain's explorer for updates on the progress of the cross-chain transaction. -🌍 Explorer: https://explorer.zetachain.com/cc/tx/${receipt.transactionHash} +🌍 Explorer: https://athens3.explorer.zetachain.com/cc/tx/${receipt.transactionHash} `); }; diff --git a/templates/omnichain/contracts/{{contractName}}.sol.hbs b/templates/omnichain/contracts/{{contractName}}.sol.hbs index 86b8819e..f737cfc7 100644 --- a/templates/omnichain/contracts/{{contractName}}.sol.hbs +++ b/templates/omnichain/contracts/{{contractName}}.sol.hbs @@ -16,10 +16,12 @@ contract {{contractName}} is zContract { uint256 amount, bytes calldata message ) external virtual override { + {{#if arguments.pairs}} ({{#each arguments.pairs}}{{#if @index}}, {{/if}}{{this.[1]}} {{this.[0]}}{{/each}}) = abi.decode( message, ({{#each arguments.pairs}}{{#if @index}}, {{/if}}{{this.[1]}}{{/each}}) ); + {{/if}} // TODO: implement the logic } } diff --git a/templates/omnichain/tasks/deploy.ts.hbs b/templates/omnichain/tasks/deploy.ts.hbs index ff9d01aa..1f0994fc 100644 --- a/templates/omnichain/tasks/deploy.ts.hbs +++ b/templates/omnichain/tasks/deploy.ts.hbs @@ -5,9 +5,9 @@ const contractName = "{{contractName}}"; const SYSTEM_CONTRACT = "0x239e96c8f17C85c30100AC26F635Ea15f23E9c67"; const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - if (hre.network.name !== "athens") { + if (hre.network.name !== "zeta_testnet") { throw new Error( - '🚨 Please use the "athens" network to deploy to ZetaChain.' + '🚨 Please use the "zeta_testnet" network to deploy to ZetaChain.' ); } diff --git a/templates/omnichain/tasks/interact.ts.hbs b/templates/omnichain/tasks/interact.ts.hbs index 5ad85259..add8f1ad 100644 --- a/templates/omnichain/tasks/interact.ts.hbs +++ b/templates/omnichain/tasks/interact.ts.hbs @@ -2,32 +2,19 @@ import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { parseEther } from "@ethersproject/units"; import { getAddress } from "@zetachain/protocol-contracts"; +import { prepareData, trackCCTX } from "@zetachain/toolkit/helpers"; const main = async (args: any, hre: HardhatRuntimeEnvironment) => { const [signer] = await hre.ethers.getSigners(); console.log(`🔑 Using account: ${signer.address}\n`); - const prepareData = ( - contract: string, - typesList: string[], - argsList: string[] - ) => { - const abiCoder = hre.ethers.utils.defaultAbiCoder; - const params = abiCoder.encode(typesList, argsList); - return `${contract}${params.slice(2)}`; - }; - const network = hre.network.name; const data = prepareData( args.contract, [{{#each arguments.types}}"{{this}}", {{/each}}], - [{{#each arguments.names}}"{{this}}", {{/each}}] + [{{#each arguments.names}}args.{{this}}, {{/each}}] ); - const to = getAddress({ - address: "tss", - networkName: network, - zetaNetwork: "athens", - }); + const to = getAddress("tss", hre.network.name); const value = parseEther(args.amount); const tx = await signer.sendTransaction({ data, to, value }); @@ -35,16 +22,14 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => { console.log(` 🚀 Successfully broadcasted a token transfer transaction on ${network} network. 📝 Transaction hash: ${tx.hash} - -This transaction has been submitted to ${network}, but it may take some time -for it to be processed on ZetaChain. Please refer to ZetaChain's explorer -for updates on the progress of the cross-chain transaction. - -🌍 Explorer: https://explorer.zetachain.com/address/${args.contract}?tab=ccTxs `); + await trackCCTX(tx.hash); }; task("interact", "Interact with the contract") .addParam("contract", "The address of the withdraw contract on ZetaChain") .addParam("amount", "Amount of tokens to send") + {{#each arguments.names}} + .addParam("{{this}}") + {{/each}} .setAction(main);