From 278f2aa158724ac024da2baee9bbf598eb1e6020 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 6 Aug 2025 11:20:46 +0300 Subject: [PATCH 1/5] feat: Swap ocmmands --- examples/call/foundry.toml | 1 + examples/hello/foundry.toml | 1 + examples/messaging/foundry.toml | 1 + examples/nft/foundry.toml | 1 + examples/swap/commands/common.ts | 29 ++++++++++++ examples/swap/commands/deploy.ts | 80 ++++++++++++++++++++++++++++++++ examples/swap/commands/index.ts | 8 ++++ examples/swap/foundry.toml | 1 + examples/token/foundry.toml | 1 + 9 files changed, 123 insertions(+) create mode 100644 examples/swap/commands/common.ts create mode 100644 examples/swap/commands/deploy.ts create mode 100644 examples/swap/commands/index.ts diff --git a/examples/call/foundry.toml b/examples/call/foundry.toml index 1441b979..20685c96 100644 --- a/examples/call/foundry.toml +++ b/examples/call/foundry.toml @@ -3,6 +3,7 @@ src = 'contracts' out = 'out' viaIR = true libs = ['node_modules', "dependencies"] +evm_version = "paris" test = 'test' cache_path = 'cache_forge' verbosity = 3 diff --git a/examples/hello/foundry.toml b/examples/hello/foundry.toml index 1441b979..20685c96 100644 --- a/examples/hello/foundry.toml +++ b/examples/hello/foundry.toml @@ -3,6 +3,7 @@ src = 'contracts' out = 'out' viaIR = true libs = ['node_modules', "dependencies"] +evm_version = "paris" test = 'test' cache_path = 'cache_forge' verbosity = 3 diff --git a/examples/messaging/foundry.toml b/examples/messaging/foundry.toml index 1441b979..20685c96 100644 --- a/examples/messaging/foundry.toml +++ b/examples/messaging/foundry.toml @@ -3,6 +3,7 @@ src = 'contracts' out = 'out' viaIR = true libs = ['node_modules', "dependencies"] +evm_version = "paris" test = 'test' cache_path = 'cache_forge' verbosity = 3 diff --git a/examples/nft/foundry.toml b/examples/nft/foundry.toml index 1441b979..20685c96 100644 --- a/examples/nft/foundry.toml +++ b/examples/nft/foundry.toml @@ -3,6 +3,7 @@ src = 'contracts' out = 'out' viaIR = true libs = ['node_modules', "dependencies"] +evm_version = "paris" test = 'test' cache_path = 'cache_forge' verbosity = 3 diff --git a/examples/swap/commands/common.ts b/examples/swap/commands/common.ts new file mode 100644 index 00000000..92bd7df9 --- /dev/null +++ b/examples/swap/commands/common.ts @@ -0,0 +1,29 @@ +import path from "path"; +import fs from "fs"; + +/** + * Load contract artifacts (ABI & bytecode) compiled by Foundry (out/** path) + */ +export const loadContractArtifacts = ( + contractName: string, + sourceName?: string +) => { + const sourcePath = sourceName || `${contractName}.sol`; + const artifactPath = path.join( + __dirname, + `../out/${sourcePath}/${contractName}.json` + ); + + try { + const artifact = JSON.parse(fs.readFileSync(artifactPath, "utf8")); + return { + abi: artifact.abi, + bytecode: artifact.bytecode, + } as { abi: any; bytecode: string }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + throw new Error( + `Unable to load contract artifacts for ${contractName}: ${message}` + ); + } +}; diff --git a/examples/swap/commands/deploy.ts b/examples/swap/commands/deploy.ts new file mode 100644 index 00000000..e2b283e4 --- /dev/null +++ b/examples/swap/commands/deploy.ts @@ -0,0 +1,80 @@ +import { Command } from "commander"; +import { ethers } from "ethers"; +import { loadContractArtifacts } from "./common"; + +const main = async (opts: any) => { + const provider = new ethers.providers.JsonRpcProvider(opts.rpc); + const signer = new ethers.Wallet(opts.privateKey, provider); + + const network = await provider.getNetwork(); + const networkInfo = network.name ?? network.chainId; + + try { + const { abi, bytecode } = loadContractArtifacts(opts.name); + const factory = new ethers.ContractFactory(abi, bytecode, signer); + const implementation = await factory.deploy(); + await implementation.deployed(); + + const initData = new ethers.utils.Interface(abi).encodeFunctionData( + "initialize", + [opts.gateway, opts.uniswapRouter, opts.gasLimit, signer.address] + ); + + const { abi: proxyAbi, bytecode: proxyBytecode } = loadContractArtifacts( + "ERC1967Proxy", + "ERC1967Proxy.sol" + ); + + const proxyFactory = new ethers.ContractFactory( + proxyAbi, + proxyBytecode, + signer + ); + const proxy = await proxyFactory.deploy(implementation.address, initData); + await proxy.deployed(); + + console.log( + JSON.stringify({ + contractAddress: proxy.address, + implementationAddress: implementation.address, + deployer: signer.address, + network: networkInfo, + transactionHash: proxy.deployTransaction?.hash, + }) + ); + } catch (err) { + console.error( + "Deployment failed:", + err instanceof Error ? err.message : err + ); + process.exit(1); + } +}; + +export const deploy = new Command("deploy") + .description("Deploy a swap contract") + .requiredOption( + "-r, --rpc ", + "RPC URL (default: testnet)", + "https://zetachain-athens-evm.blockpi.network/v1/rpc/public" + ) + .requiredOption("-k, --private-key ", "Private key") + .option("-n, --name ", "Contract name", "Swap") + .requiredOption( + "-u, --uniswap-router
", + "Uniswap V2 Router address (default: testnet)", + "0x2ca7d64A7EFE2D62A725E2B35Cf7230D6677FfEe" + ) + .option( + "-g, --gateway
", + "Gateway address (default: testnet)", + "0x6c533f7fe93fae114d0954697069df33c9b74fd7" + ) + .option("--gas-limit ", "Gas limit for the transaction", "1000000") + .action((opts) => { + opts.gasLimit = Number(opts.gasLimit); + main(opts).catch((err) => { + console.error("Unhandled error:", err); + process.exit(1); + }); + }); diff --git a/examples/swap/commands/index.ts b/examples/swap/commands/index.ts new file mode 100644 index 00000000..c5fa02f4 --- /dev/null +++ b/examples/swap/commands/index.ts @@ -0,0 +1,8 @@ +#!/usr/bin/env npx tsx + +import { Command } from "commander"; +import { deploy } from "./deploy"; + +const program = new Command().addCommand(deploy); + +program.parse(); diff --git a/examples/swap/foundry.toml b/examples/swap/foundry.toml index 1441b979..20685c96 100644 --- a/examples/swap/foundry.toml +++ b/examples/swap/foundry.toml @@ -3,6 +3,7 @@ src = 'contracts' out = 'out' viaIR = true libs = ['node_modules', "dependencies"] +evm_version = "paris" test = 'test' cache_path = 'cache_forge' verbosity = 3 diff --git a/examples/token/foundry.toml b/examples/token/foundry.toml index 1441b979..20685c96 100644 --- a/examples/token/foundry.toml +++ b/examples/token/foundry.toml @@ -3,6 +3,7 @@ src = 'contracts' out = 'out' viaIR = true libs = ['node_modules', "dependencies"] +evm_version = "paris" test = 'test' cache_path = 'cache_forge' verbosity = 3 From 0dcc1865371bdb63393afcf59006526054c5a743 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 6 Aug 2025 11:33:39 +0300 Subject: [PATCH 2/5] move swap companion to test --- examples/swap/hardhat.config.ts | 1 - examples/swap/tasks/companionSwap.ts | 79 ------------ examples/swap/tasks/deploy.ts | 44 ------- examples/swap/tasks/deployCompanion.ts | 43 ------- examples/swap/tasks/evmSwap.ts | 117 ------------------ examples/swap/tasks/index.ts | 5 - examples/swap/tasks/zetachainSwap.ts | 44 ------- .../{contracts => test}/SwapCompanion.sol | 0 examples/swap/test/SwapTest.t.sol | 2 +- 9 files changed, 1 insertion(+), 334 deletions(-) delete mode 100644 examples/swap/tasks/companionSwap.ts delete mode 100644 examples/swap/tasks/deploy.ts delete mode 100644 examples/swap/tasks/deployCompanion.ts delete mode 100644 examples/swap/tasks/evmSwap.ts delete mode 100644 examples/swap/tasks/index.ts delete mode 100644 examples/swap/tasks/zetachainSwap.ts rename examples/swap/{contracts => test}/SwapCompanion.sol (100%) diff --git a/examples/swap/hardhat.config.ts b/examples/swap/hardhat.config.ts index fb11f815..da35ca2d 100644 --- a/examples/swap/hardhat.config.ts +++ b/examples/swap/hardhat.config.ts @@ -2,7 +2,6 @@ import "@nomicfoundation/hardhat-toolbox"; import { HardhatUserConfig } from "hardhat/config"; import * as dotenv from "dotenv"; -import "./tasks"; import "@zetachain/localnet/tasks"; import "@zetachain/toolkit/tasks"; import { getHardhatConfig } from "@zetachain/toolkit/utils"; diff --git a/examples/swap/tasks/companionSwap.ts b/examples/swap/tasks/companionSwap.ts deleted file mode 100644 index 490d953b..00000000 --- a/examples/swap/tasks/companionSwap.ts +++ /dev/null @@ -1,79 +0,0 @@ -import ERC20_ABI from "@openzeppelin/contracts/build/contracts/ERC20.json"; -import { task, types } from "hardhat/config"; -import type { HardhatRuntimeEnvironment } from "hardhat/types"; -import { isInputAmountSufficient } from "./evmSwap"; -import { ZetaChainClient } from "@zetachain/toolkit/client"; - -const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - const { ethers } = hre; - const [signer] = await ethers.getSigners(); - - const factory = (await hre.ethers.getContractFactory("SwapCompanion")) as any; - const contract = factory.attach(args.contract).connect(signer); - const recipient = hre.ethers.utils.isAddress(args.recipient) - ? args.recipient - : hre.ethers.utils.toUtf8Bytes(args.recipient); - - const client = new ZetaChainClient({ network: "testnet", signer }); - - if (!args.skipChecks) { - await isInputAmountSufficient({ - hre, - client, - amount: args.amount, - erc20: args.erc20, - target: args.target, - }); - } - - let tx; - if (args.erc20) { - const erc20Contract = new ethers.Contract( - args.erc20, - ERC20_ABI.abi, - signer - ); - const decimals = await erc20Contract.decimals(); - const value = hre.ethers.utils.parseUnits(args.amount, decimals); - const approveTx = await erc20Contract - .connect(signer) - .approve(args.contract, value); - await approveTx.wait(); - - tx = await contract.swapERC20( - args.universalContract, - args.target, - recipient, - value, - args.erc20, - args.withdraw - ); - } else { - const value = hre.ethers.utils.parseEther(args.amount); - tx = await contract.swapNativeGas( - args.universalContract, - args.target, - recipient, - args.withdraw, - { value } - ); - } - - await tx.wait(); - console.log(`Transaction hash: ${tx.hash}`); -}; - -task("companion-swap", "Swap native gas tokens", main) - .addParam("contract", "Contract address") - .addParam("universalContract", "Universal contract address") - .addOptionalParam( - "withdraw", - "Withdraw to destination or keep token on ZetaChain", - true, - types.boolean - ) - .addOptionalParam("erc20", "ERC-20 token address") - .addParam("target", "ZRC-20 address of the token to swap for") - .addParam("amount", "Amount of tokens to swap") - .addFlag("skipChecks", "Skip checks for minimum amount") - .addParam("recipient", "Recipient address"); diff --git a/examples/swap/tasks/deploy.ts b/examples/swap/tasks/deploy.ts deleted file mode 100644 index 1a4c680c..00000000 --- a/examples/swap/tasks/deploy.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { task, types } from "hardhat/config"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - const network = hre.network.name as any; - - const [signer] = await hre.ethers.getSigners(); - if (signer === undefined) { - throw new Error( - `Wallet not found. Please, run "npx hardhat account --save" or set PRIVATE_KEY env variable (for example, in a .env file)` - ); - } - - const factory = await hre.ethers.getContractFactory(args.name); - - const contract = await hre.upgrades.deployProxy( - factory as any, - [args.gateway, args.uniswapRouter, args.gasLimit, signer.address], - { kind: "uups" } - ); - - console.log( - JSON.stringify({ - contractAddress: contract.address, - deployer: signer.address, - network: network, - }) - ); -}; - -task("deploy", "Deploy the contract", main) - .addOptionalParam("name", "Contract to deploy", "Swap") - .addOptionalParam("uniswapRouter", "Uniswap v2 Router address") - .addOptionalParam( - "gateway", - "Gateway address (default: ZetaChain Gateway)", - "0x6c533f7fe93fae114d0954697069df33c9b74fd7" - ) - .addOptionalParam( - "gasLimit", - "Gas limit for the transaction", - 1000000, - types.int - ); diff --git a/examples/swap/tasks/deployCompanion.ts b/examples/swap/tasks/deployCompanion.ts deleted file mode 100644 index 10ee849a..00000000 --- a/examples/swap/tasks/deployCompanion.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { task, types } from "hardhat/config"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - const network = hre.network.name; - - const [signer] = await hre.ethers.getSigners(); - if (signer === undefined) { - throw new Error( - `Wallet not found. Please, run "npx hardhat account --save" or set PRIVATE_KEY env variable (for example, in a .env file)` - ); - } - - const factory = await hre.ethers.getContractFactory(args.name); - const contract = await (factory as any).deploy(args.gateway); - await contract.deployed(); - - if (args.json) { - console.log( - JSON.stringify({ - contractAddress: contract.address, - deployer: signer.address, - network: network, - transactionHash: contract.deployTransaction.hash, - }) - ); - } else { - console.log(`🔑 Using account: ${signer.address} - -🚀 Successfully deployed "${args.name}" contract on ${network}. -📜 Contract address: ${contract.address} -`); - } -}; - -task("deploy-companion", "Deploy the companion contract", main) - .addFlag("json", "Output in JSON") - .addOptionalParam("name", "Contract to deploy", "SwapCompanion") - .addOptionalParam( - "gateway", - "Gateway address (default: EVM Gateway on testnet)", - "0x0c487a766110c85d301d96e33579c5b317fa4995" - ); diff --git a/examples/swap/tasks/evmSwap.ts b/examples/swap/tasks/evmSwap.ts deleted file mode 100644 index 1959c94a..00000000 --- a/examples/swap/tasks/evmSwap.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { task, types } from "hardhat/config"; -import type { HardhatRuntimeEnvironment } from "hardhat/types"; - -import { ZetaChainClient } from "@zetachain/toolkit/client"; - -export const isInputAmountSufficient = async ({ - hre, - client, - erc20, - amount, - target, -}: any) => { - const inputZRC20 = await (erc20 - ? client.getZRC20FromERC20(erc20) - : client.getZRC20GasToken(hre.network.name)); - - const minAmount = await client.getWithdrawFeeInInputToken(inputZRC20, target); - - const minAmountFormatted = hre.ethers.utils.formatUnits( - minAmount.amount, - minAmount.decimals - ); - - const value = hre.ethers.utils.parseUnits(amount, minAmount.decimals); - - if (value.lt(minAmount.amount)) { - throw new Error( - `Input amount ${amount} is less than minimum amount ${minAmountFormatted} required for a withdrawal to the destination chain` - ); - } -}; - -export const evmDepositAndCall = async ( - args: any, - hre: HardhatRuntimeEnvironment -) => { - try { - const [signer] = await hre.ethers.getSigners(); - const client = new ZetaChainClient({ network: "testnet", signer }); - - if (!args.skipChecks) { - await isInputAmountSufficient({ - hre, - client, - amount: args.amount, - erc20: args.erc20, - target: args.target, - }); - } - - const tx = await client.evmDepositAndCall({ - amount: args.amount, - erc20: args.erc20, - gatewayEvm: args.gatewayEvm, - receiver: args.receiver, - revertOptions: { - callOnRevert: args.callOnRevert, - onRevertGasLimit: args.onRevertGasLimit, - revertAddress: args.revertAddress, - revertMessage: args.revertMessage, - }, - txOptions: { - gasLimit: args.gasLimit, - gasPrice: args.gasPrice, - }, - types: ["address", "bytes", "bool"], - values: [args.target, args.recipient, args.withdraw], - }); - if (tx) { - const receipt = await tx.wait(); - console.log("Transaction hash:", receipt.transactionHash); - } - } catch (e) { - console.error("Transaction error:", e); - } -}; - -task("evm-swap", "Swap tokens from EVM", evmDepositAndCall) - .addParam("receiver", "Receiver address on ZetaChain") - .addParam("gatewayEvm", "contract address of gateway on EVM") - .addFlag("callOnRevert", "Whether to call on revert") - .addOptionalParam( - "revertAddress", - "Revert address", - "0x0000000000000000000000000000000000000000", - types.string - ) - .addOptionalParam( - "gasPrice", - "The gas price for the transaction", - 50000000000, - types.int - ) - .addOptionalParam( - "gasLimit", - "The gas limit for the transaction", - 500000, - types.int - ) - .addOptionalParam( - "onRevertGasLimit", - "The gas limit for the revert transaction", - 50000, - types.int - ) - .addOptionalParam("revertMessage", "Revert message", "0x") - .addParam("amount", "amount of ETH to send with the transaction") - .addOptionalParam("erc20", "ERC-20 token address") - .addFlag("skipChecks", "Skip checks for minimum amount") - .addParam("target", "ZRC-20 address of the token to swap for") - .addParam("recipient", "Recipient address") - .addOptionalParam( - "withdraw", - "Withdraw to destination or keep token on ZetaChain", - true, - types.boolean - ); diff --git a/examples/swap/tasks/index.ts b/examples/swap/tasks/index.ts deleted file mode 100644 index f5948107..00000000 --- a/examples/swap/tasks/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import "./deploy"; -import "./companionSwap"; -import "./deployCompanion"; -import "./zetachainSwap"; -import "./evmSwap"; diff --git a/examples/swap/tasks/zetachainSwap.ts b/examples/swap/tasks/zetachainSwap.ts deleted file mode 100644 index 3c6c2dde..00000000 --- a/examples/swap/tasks/zetachainSwap.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { task, types } from "hardhat/config"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { parseEther } from "@ethersproject/units"; -import { ethers } from "ethers"; -import ZRC20 from "@zetachain/protocol-contracts/abi/ZRC20.sol/ZRC20.json"; - -const main = async (args: any, hre: HardhatRuntimeEnvironment) => { - const [signer] = await hre.ethers.getSigners(); - - const factory = await hre.ethers.getContractFactory("Swap"); - const contract = factory.attach(args.contract); - - const zrc20 = new ethers.Contract(args.zrc20, ZRC20.abi, signer); - - const amount = parseEther(args.amount); - - const approval = await zrc20.approve(args.contract, amount); - await approval.wait(); - - const tx = await contract.swap( - args.zrc20, - amount, - args.target, - ethers.utils.arrayify(args.recipient), - JSON.parse(args.withdraw) - ); - - await tx.wait(); - console.log(`Transaction hash: ${tx.hash}`); -}; - -task("zetachain-swap", "Swap tokens from ZetaChain", main) - .addFlag("json", "Output JSON") - .addParam("contract", "Contract address") - .addParam("amount", "Token amount to send") - .addParam("zrc20", "Input token address") - .addParam("target", "Target token address") - .addParam("recipient", "Recipient address") - .addOptionalParam( - "withdraw", - "Withdraw tokens to destination chain", - true, - types.boolean - ); diff --git a/examples/swap/contracts/SwapCompanion.sol b/examples/swap/test/SwapCompanion.sol similarity index 100% rename from examples/swap/contracts/SwapCompanion.sol rename to examples/swap/test/SwapCompanion.sol diff --git a/examples/swap/test/SwapTest.t.sol b/examples/swap/test/SwapTest.t.sol index 8cc15809..2e56e325 100644 --- a/examples/swap/test/SwapTest.t.sol +++ b/examples/swap/test/SwapTest.t.sol @@ -5,7 +5,7 @@ import "@zetachain/toolkit/contracts/testing/FoundrySetup.t.sol"; import "@zetachain/toolkit/contracts/testing/mock/ERC20Mock.sol"; import "@zetachain/toolkit/contracts/testing/mock/ZRC20Mock.sol"; import "../contracts/Swap.sol"; -import {SwapCompanion} from "../contracts/SwapCompanion.sol"; +import {SwapCompanion} from "./SwapCompanion.sol"; import {console} from "forge-std/console.sol"; contract SwapTest is FoundrySetup { From 74312e2b041f441419caccca42eb4472cda5d024 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 6 Aug 2025 13:55:32 +0300 Subject: [PATCH 3/5] wip --- examples/swap/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/swap/package.json b/examples/swap/package.json index 1095ea53..b9bf6c4f 100644 --- a/examples/swap/package.json +++ b/examples/swap/package.json @@ -60,4 +60,4 @@ "@zetachain/toolkit": "^16.0.0", "zetachain": "6.0.1" } -} +} \ No newline at end of file From 83cd53946cf0008ec1950f73ecd607e3b704668c Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 7 Aug 2025 13:38:09 +0300 Subject: [PATCH 4/5] update localnet --- examples/swap/scripts/localnet.sh | 150 +++++++++--------------------- 1 file changed, 45 insertions(+), 105 deletions(-) diff --git a/examples/swap/scripts/localnet.sh b/examples/swap/scripts/localnet.sh index ea75aa82..96cd237f 100755 --- a/examples/swap/scripts/localnet.sh +++ b/examples/swap/scripts/localnet.sh @@ -6,111 +6,51 @@ set -o pipefail yarn zetachain localnet start --force-kill --exit-on-error & -while [ ! -f "localnet.json" ]; do sleep 1; done - -npx hardhat compile --force --quiet - -ZRC20_ETHEREUM=$(jq -r '.addresses[] | select(.type=="ZRC-20 ETH on 11155112") | .address' localnet.json) -USDC_ETHEREUM=$(jq -r '.addresses[] | select(.type=="ERC-20 USDC" and .chain=="ethereum") | .address' localnet.json) -ZRC20_USDC=$(jq -r '.addresses[] | select(.type=="ZRC-20 USDC on 98") | .address' localnet.json) -ZRC20_BNB=$(jq -r '.addresses[] | select(.type=="ZRC-20 BNB on 98") | .address' localnet.json) -WZETA=$(jq -r '.addresses[] | select(.type=="wzeta" and .chain=="zetachain") | .address' localnet.json) -GATEWAY_ETHEREUM=$(jq -r '.addresses[] | select(.type=="gateway" and .chain=="ethereum") | .address' localnet.json) -GATEWAY_ZETACHAIN=$(jq -r '.addresses[] | select(.type=="gateway" and .chain=="zetachain") | .address' localnet.json) -UNISWAP_ROUTER=$(jq -r '.addresses[] | select(.type=="uniswapRouterInstance" and .chain=="zetachain") | .address' localnet.json) -SENDER=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 - -CONTRACT_SWAP=$(npx hardhat deploy --name Swap --network localhost --gateway "$GATEWAY_ZETACHAIN" --uniswap-router "$UNISWAP_ROUTER" | jq -r '.contractAddress') -COMPANION=$(npx hardhat deploy-companion --gateway "$GATEWAY_ETHEREUM" --network localhost --json | jq -r '.contractAddress') - -npx hardhat evm-swap \ - --network localhost \ - --receiver "$CONTRACT_SWAP" \ - --amount 0.1 \ - --target "$WZETA" \ - --gateway-evm "$GATEWAY_ETHEREUM" \ - --skip-checks \ - --withdraw false \ - --recipient "$SENDER" - -yarn zetachain localnet check - -npx hardhat evm-swap \ - --network localhost \ - --receiver "$CONTRACT_SWAP" \ - --amount 0.1 \ - --gateway-evm "$GATEWAY_ETHEREUM" \ - --target "$ZRC20_USDC" \ - --skip-checks \ - --recipient "$SENDER" - -yarn zetachain localnet check - -npx hardhat evm-swap \ - --network localhost \ - --receiver "$CONTRACT_SWAP" \ - --amount 0.1 \ - --target "$ZRC20_BNB" \ - --gateway-evm "$GATEWAY_ETHEREUM" \ - --skip-checks \ - --erc20 "$USDC_ETHEREUM" \ - --recipient "$SENDER" - -yarn zetachain localnet check - -npx hardhat evm-swap \ - --skip-checks \ - --network localhost \ - --receiver "$CONTRACT_SWAP" \ - --amount 0.1 \ - --gateway-evm "$GATEWAY_ETHEREUM" \ - --target "$ZRC20_BNB" \ - --recipient "$SENDER" - -yarn zetachain localnet check - -npx hardhat evm-swap \ - --skip-checks \ - --network localhost \ - --receiver "$CONTRACT_SWAP" \ - --amount 0.1 \ - --target "$ZRC20_BNB" \ - --gateway-evm "$GATEWAY_ETHEREUM" \ - --recipient "$SENDER" \ - --withdraw false - -yarn zetachain localnet check - -npx hardhat companion-swap \ - --network localhost \ - --skip-checks \ - --contract "$COMPANION" \ - --universal-contract "$CONTRACT_SWAP" \ - --amount 0.1 \ - --target "$ZRC20_BNB" \ - --recipient "$SENDER" - -yarn zetachain localnet check - -npx hardhat companion-swap \ - --skip-checks \ - --network localhost \ - --contract "$COMPANION" \ - --universal-contract "$CONTRACT_SWAP" \ - --amount 0.1 \ - --erc20 "$USDC_ETHEREUM" \ - --target "$ZRC20_BNB" \ - --recipient "$SENDER" - -yarn zetachain localnet check - -npx hardhat zetachain-swap \ - --network localhost \ - --contract "$CONTRACT_SWAP" \ - --amount 0.1 \ - --zrc20 "$ZRC20_BNB" \ - --target "$ZRC20_ETHEREUM" \ - --recipient "$SENDER" +while [ ! -f "$HOME/.zetachain/localnet/registry.json" ]; do sleep 1; done + +forge build + +ZRC20_BNB=$(jq -r '."98".chainInfo.gasZRC20' ~/.zetachain/localnet/registry.json) && echo $ZRC20_BNB +ZRC20_ETHEREUM=$(jq -r '."11155112".chainInfo.gasZRC20' ~/.zetachain/localnet/registry.json) && echo $ZRC20_ETHEREUM +USDC_ETHEREUM=$(jq -r '.["11155112"].contracts[] | select(.contractType == "ERC-20 USDC") | .address' ~/.zetachain/localnet/registry.json) && echo $USDC_ETHEREUM +GATEWAY_ETHEREUM=$(jq -r '.["11155112"].contracts[] | select(.contractType == "gateway") | .address' ~/.zetachain/localnet/registry.json) && echo $GATEWAY_ETHEREUM +GATEWAY_BNB=$(jq -r '."98".contracts[] | select(.contractType == "gateway") | .address' ~/.zetachain/localnet/registry.json) && echo $GATEWAY_BNB +GATEWAY_ZETACHAIN=$(jq -r '.["31337"].contracts[] | select(.contractType == "gateway") | .address' ~/.zetachain/localnet/registry.json) && echo $GATEWAY_ZETACHAIN +UNISWAP_ROUTER=$(jq -r '.["31337"].contracts[] | select(.contractType == "uniswapRouterInstance") | .address' ~/.zetachain/localnet/registry.json) && echo $UNISWAP_ROUTER +WZETA=$(jq -r '.["31337"].contracts[] | select(.contractType == "wzeta") | .address' ~/.zetachain/localnet/registry.json) && echo $WZETA +PRIVATE_KEY=$(jq -r '.private_keys[0]' ~/.zetachain/localnet/anvil.json) && echo $PRIVATE_KEY +RECIPIENT=$(cast wallet address $PRIVATE_KEY) && echo $RECIPIENT +RPC=http://localhost:8545 + +UNIVERSAL=$(npx ts-node commands/index.ts deploy \ + --private-key $PRIVATE_KEY \ + --gateway $GATEWAY_ZETACHAIN \ + --rpc $RPC \ + --uniswap-router $UNISWAP_ROUTER | jq -r .contractAddress) + +npx zetachain evm deposit-and-call \ + --rpc http://localhost:8545 \ + --chain-id 11155112 \ + --gateway $GATEWAY_ETHEREUM \ + --amount 0.001 \ + --types address bytes bool \ + --receiver $UNIVERSAL \ + --private-key $PRIVATE_KEY \ + --values $ZRC20_BNB $RECIPIENT true \ + --yes + +yarn zetachain localnet check + +npx zetachain evm deposit-and-call \ + --rpc http://localhost:8545 \ + --chain-id 11155112 \ + --gateway $GATEWAY_ETHEREUM \ + --amount 0.001 \ + --types address bytes bool \ + --receiver $UNIVERSAL \ + --private-key $PRIVATE_KEY \ + --values $WZETA $RECIPIENT false \ + --yes yarn zetachain localnet check From 5808da28b5bdc77bd31361deac91297281bd7f2f Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 7 Aug 2025 13:42:13 +0300 Subject: [PATCH 5/5] fix ci --- .github/workflows/localnet.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/localnet.yaml b/.github/workflows/localnet.yaml index 94ce1189..92a8ce01 100644 --- a/.github/workflows/localnet.yaml +++ b/.github/workflows/localnet.yaml @@ -51,5 +51,6 @@ jobs: run: | cd "${{ matrix.example-dir }}" yarn + forge soldeer update chmod +x ./scripts/localnet.sh ./scripts/localnet.sh start