From e006fc0ae3a7cc997f9ff094e737a483f2d410f8 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Fri, 9 Aug 2024 17:22:26 -0300 Subject: [PATCH 01/11] feat: use loadTester.ts as skeleton --- utils/scripts/gasCalculations.ts | 178 +++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 utils/scripts/gasCalculations.ts diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts new file mode 100644 index 0000000..7f5569f --- /dev/null +++ b/utils/scripts/gasCalculations.ts @@ -0,0 +1,178 @@ +import { Wallet, Provider, utils } from "zksync-ethers"; +import { IERC20 } from "zksync-ethers/build/utils"; +import * as ethers from "ethers"; +import { env } from "process"; +import { parseArgs } from "util"; +import contractAbi from "./erc20_abi.json"; + +const { values, _positionals } = parseArgs({ + args: Bun.argv, + options: { + amount_to_pass: { + type: 'string', + }, + amount_to_bridge: { + type: 'string', + }, + l1_pk: { + type: 'string', + }, + l2_pk: { + type: 'string', + }, + sleep_ms: { + type: 'string', + }, + }, + strict: true, + allowPositionals: true, +}); + +if (Object.keys(values).length !== 0) { + console.log(values); +} + +// HTTP RPC endpoints +const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; +const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; + +const AMOUNT_TO_PASS = values.amount_to_pass || env.AMOUNT_TO_PASS || "0.1"; +const AMOUNT_TO_BRIDGE = values.amount_to_bridge || env.AMOUNT_TO_BRIDGE || "100"; +const AMOUNT_OF_WALLETS = "20"; + +const L1_RICH_PK = values.l1_pk || env.L1_RICH_PK || "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; + +const L1_RICH = { + addr: ethers.utils.computeAddress(L1_RICH_PK), + pk: L1_RICH_PK, +}; + +let wallets: [Wallet]; +for (let index = 0; index < AMOUNT_OF_WALLETS; index++) { + +} + + +const L2_ACCOUNT = { + addr: ethers.utils.computeAddress(L2_PK), + pk: L2_PK, +}; + +const getERC20Balance = async (address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { + await ERC20_L1.balanceOf(address) + .then((balance: number) => { + console.log(`L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}`); + }) + .catch(() => { + console.error("Error fetching ERC20 balance from L1"); + }); +} + +async function main() { + // Initialize the wallet. + const l1provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT) + const l2provider = new Provider(L2_RPC_ENDPOINT); + const wallet1 = new Wallet(L1_RICH.pk, l2provider, l1provider); + const wallet2 = new Wallet(L2_ACCOUNT.pk, l2provider, l1provider); + const wallet3Pk = Wallet.createRandom().privateKey; + const wallet3 = new Wallet(wallet3Pk, l2provider, l1provider); + + const sleep = Number(SLEEP_MS) || 100; + + console.log(`Running script to deposit ${AMOUNT_TO_BRIDGE}ETH in L2`); + console.log(`Deposit ${AMOUNT_TO_BRIDGE}ETH using ${L1_RICH.addr}`); + + console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); + console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); + + console.log("#####################################################\n"); + console.log(`L1 balance before deposit: ${ethers.utils.formatEther(await wallet1.getBalanceL1())}`); + console.log(`L2 balance before deposit: ${ethers.utils.formatEther(await wallet1.getBalance())}`); + console.log("\n#####################################################\n"); + + + const walletEthers = new ethers.Wallet(L1_RICH_PK, l1provider); + + const ERC20_L1 = new ethers.Contract(await l2provider.getBaseTokenContractAddress(), contractAbi, walletEthers); + const ERC20_SYMBOL: string = await ERC20_L1.symbol(); + const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); + + console.log("#####################################################\n"); + + // Used locally + await ERC20_L1.mint(await walletEthers.getAddress(), BigInt(10000 * ERC20_DECIMALS_MUL)); + await getERC20Balance(wallet1.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + + const tx = await wallet1.deposit({ + token: await l2provider.getBaseTokenContractAddress(), + to: await wallet1.getAddress(), + amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) * 2.05)), + approveBaseERC20: true, + approveERC20: true, + }); + const receipt = await tx.wait(); + console.log(`Tx: ${receipt.transactionHash}`); + + console.log("\n#####################################################\n") + console.log(`L1 balance after deposit: ${ethers.utils.formatEther(await wallet1.getBalanceL1())}`); + console.log(`L2 balance after deposit: ${ethers.utils.formatEther(await wallet1.getBalance())}`); + console.log("\n#####################################################\n") + + console.log(`Running script to generate transactions between two accounts in L2`); + console.log(`With an interval between txs of ${SLEEP_MS}[ms]`); + console.log(`Using ${AMOUNT_TO_PASS}ETH to send back and forth`); + console.log(`Using:\naddr(1): ${L1_RICH.addr}\naddr(2): ${L2_ACCOUNT.addr}`); + + console.log("\n#####################################################\n"); + + console.log("Send initial funds to the second wallet to pay the fees"); + + const tx0 = await wallet1.transfer({ + to: await wallet2.getAddress(), + amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) / 3)), + }); + const receipt1 = await tx0.wait(); + console.log(`Tx(0): ${receipt1.transactionHash}`); + + const tx02 = await wallet1.transfer({ + to: await wallet3.getAddress(), + amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) / 3)), + }); + const receipt02 = await tx02.wait(); + console.log(`Tx(0): ${receipt02.transactionHash}`); + + const txFeeWithdrawal = await wallet1.transfer({ + to: "0xf2248620e8E98628b4F4a82a3f6dfe4F5993ceBa", + amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) / 3)), + }); + const receiptFeeWithdrawal = await txFeeWithdrawal.wait(); + console.log(`Tx(0): ${receiptFeeWithdrawal.transactionHash}`); + await getERC20Balance("0xf2248620e8E98628b4F4a82a3f6dfe4F5993ceBa", ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + + while (true) { + const tx1 = await wallet2.transfer({ + to: await wallet3.getAddress(), + amount: ethers.utils.parseEther(AMOUNT_TO_PASS), + }); + const receipt1 = await tx1.wait(); + console.log(`Tx(1): ${receipt1.transactionHash}`); + + const tx2 = await wallet3.transfer({ + to: await wallet2.getAddress(), + amount: ethers.utils.parseEther(AMOUNT_TO_PASS), + }); + const receipt2 = await tx2.wait(); + console.log(`Tx(2): ${receipt2.transactionHash}`); + console.log(`addr(1): ${wallet3.address} balance: ${ethers.utils.formatEther(await wallet3.getBalance())}`); + console.log(`addr(2): ${wallet2.address} balance: ${ethers.utils.formatEther(await wallet2.getBalance())}`); + console.log("\n#####################################################\n") + await Bun.sleep(sleep); + } +} + +main() + .then() + .catch((error) => { + console.error(error); + env.exitCode = "1"; + }); From adf909c84e3304e17c1bf0c25a50d384ea53d979 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Fri, 9 Aug 2024 17:23:21 -0300 Subject: [PATCH 02/11] add erc20abi --- utils/scripts/erc20_abi.json | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 utils/scripts/erc20_abi.json diff --git a/utils/scripts/erc20_abi.json b/utils/scripts/erc20_abi.json new file mode 100644 index 0000000..44b88ed --- /dev/null +++ b/utils/scripts/erc20_abi.json @@ -0,0 +1,39 @@ +[ + { + "constant": false, + "inputs": [ + { "name": "_to", "type": "address" }, + { "name": "_amount", "type": "uint256" } + ], + "name": "mint", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "name": "_owner", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "name": "balance", "type": "uint256" }], + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] From 2c87b48a8fd1cd33a6bec3bdf2fc16c510385f0c Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Mon, 12 Aug 2024 12:10:29 -0300 Subject: [PATCH 03/11] wip --- utils/scripts/erc20_abi.json | 62 +++++++- utils/scripts/gasCalculations.ts | 263 ++++++++++++++++--------------- 2 files changed, 193 insertions(+), 132 deletions(-) diff --git a/utils/scripts/erc20_abi.json b/utils/scripts/erc20_abi.json index 44b88ed..66d8b88 100644 --- a/utils/scripts/erc20_abi.json +++ b/utils/scripts/erc20_abi.json @@ -1,28 +1,71 @@ [ { "constant": false, + "name": "transfer", "inputs": [ - { "name": "_to", "type": "address" }, - { "name": "_amount", "type": "uint256" } + { + "name": "_to", + "type": "address" + }, + { + "type": "uint256", + "name": "_tokens" + } + ], + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } ], "name": "mint", - "outputs": [{ "name": "", "type": "bool" }], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, - "inputs": [{ "name": "_owner", "type": "address" }], + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], "name": "balanceOf", - "outputs": [{ "name": "balance", "type": "uint256" }], + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", - "outputs": [{ "name": "", "type": "string" }], + "outputs": [ + { + "name": "", + "type": "string" + } + ], "payable": false, "stateMutability": "view", "type": "function" @@ -31,7 +74,12 @@ "constant": true, "inputs": [], "name": "decimals", - "outputs": [{ "name": "", "type": "uint8" }], + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], "payable": false, "stateMutability": "view", "type": "function" diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts index 7f5569f..9ad8f23 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/scripts/gasCalculations.ts @@ -1,175 +1,188 @@ import { Wallet, Provider, utils } from "zksync-ethers"; import { IERC20 } from "zksync-ethers/build/utils"; + import * as ethers from "ethers"; import { env } from "process"; -import { parseArgs } from "util"; import contractAbi from "./erc20_abi.json"; - -const { values, _positionals } = parseArgs({ - args: Bun.argv, - options: { - amount_to_pass: { - type: 'string', - }, - amount_to_bridge: { - type: 'string', - }, - l1_pk: { - type: 'string', - }, - l2_pk: { - type: 'string', - }, - sleep_ms: { - type: 'string', - }, - }, - strict: true, - allowPositionals: true, -}); - -if (Object.keys(values).length !== 0) { - console.log(values); -} +import { isNumberObject, isStringObject } from "util/types"; // HTTP RPC endpoints const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; -const AMOUNT_TO_PASS = values.amount_to_pass || env.AMOUNT_TO_PASS || "0.1"; -const AMOUNT_TO_BRIDGE = values.amount_to_bridge || env.AMOUNT_TO_BRIDGE || "100"; -const AMOUNT_OF_WALLETS = "20"; +const AMOUNT_TO_PASS = env.AMOUNT_TO_PASS || "0.1"; +const AMOUNT_TO_BRIDGE = env.AMOUNT_TO_BRIDGE || "100"; +const AMOUNT_OF_WALLETS = 1; -const L1_RICH_PK = values.l1_pk || env.L1_RICH_PK || "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; +const L1_RICH_PK = env.L1_RICH_PK || "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; const L1_RICH = { addr: ethers.utils.computeAddress(L1_RICH_PK), pk: L1_RICH_PK, }; -let wallets: [Wallet]; -for (let index = 0; index < AMOUNT_OF_WALLETS; index++) { - -} - - -const L2_ACCOUNT = { - addr: ethers.utils.computeAddress(L2_PK), - pk: L2_PK, -}; - const getERC20Balance = async (address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { await ERC20_L1.balanceOf(address) .then((balance: number) => { console.log(`L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}`); + return balance }) .catch(() => { console.error("Error fetching ERC20 balance from L1"); + return 0; }); + return 0; } -async function main() { - // Initialize the wallet. - const l1provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT) - const l2provider = new Provider(L2_RPC_ENDPOINT); - const wallet1 = new Wallet(L1_RICH.pk, l2provider, l1provider); - const wallet2 = new Wallet(L2_ACCOUNT.pk, l2provider, l1provider); - const wallet3Pk = Wallet.createRandom().privateKey; - const wallet3 = new Wallet(wallet3Pk, l2provider, l1provider); +const deposit = async (zkwallet: Wallet, token: string, amount: string) => { + const txEstimate = await zkwallet.getDepositTx({ + token, + amount: ethers.utils.parseEther(amount) + }) + const limit = await zkwallet.provider.estimateGas(txEstimate); + const gasLimit = Math.ceil(limit.toNumber() * 1.2); + const tx = await zkwallet.deposit({ + token, + amount: (ethers.utils.parseEther(amount)).sub(gasLimit), + approveERC20: true, + approveBaseERC20: true, + overrides: { + gasLimit + } + }); + const receipt = await tx.wait(); + console.log(`Tx: ${receipt.transactionHash}`); - const sleep = Number(SLEEP_MS) || 100; + console.log("\n#####################################################\n") + console.log(`L2 balance after deposit: ${ethers.utils.formatEther(await zkwallet.getBalance())}`) + console.log("\n#####################################################\n") +} - console.log(`Running script to deposit ${AMOUNT_TO_BRIDGE}ETH in L2`); - console.log(`Deposit ${AMOUNT_TO_BRIDGE}ETH using ${L1_RICH.addr}`); +const l1ERC20Transfer = async (ethwallet: ethers.Wallet, amount: string, address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { + const data = ERC20_L1.interface.encodeFunctionData("transfer", [address, ethers.utils.parseEther(amount)]) + const limit = await ethwallet.provider.estimateGas({ + to: ERC20_L1.address, + from: ethwallet.address, + data: data + }); + const gasLimit = Math.ceil(limit.toNumber() * 1.2); + const tx = await ethwallet.sendTransaction({ + to: ERC20_L1.address, + from: ethwallet.address, + data: data, + gasLimit, + }); + const receipt = await tx.wait(); - console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); - console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); + console.log("\n#####################################################\n") + console.log(`Wallet: ${address} || Tx hash: ${receipt.transactionHash}`) + await getERC20Balance(address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + console.log("\n#####################################################\n") +} - console.log("#####################################################\n"); - console.log(`L1 balance before deposit: ${ethers.utils.formatEther(await wallet1.getBalanceL1())}`); - console.log(`L2 balance before deposit: ${ethers.utils.formatEther(await wallet1.getBalance())}`); - console.log("\n#####################################################\n"); +async function sendMultipleTransactions(walletEthers, wallets: { address: string }[], amountForEach: string | number) { + const amount = isNumberObject(amountForEach) ? String(amountForEach) : amountForEach; + let nonce = await walletEthers.provider.getTransactionCount(walletEthers.address, 'latest'); + const transactionPromises: Promise[] = []; + + for (const w of wallets) { + const tx = { + to: w.address, + nonce: nonce++, + value: ethers.utils.parseEther(amount), + gasLimit: 21000 + }; + + const transactionPromise = walletEthers.sendTransaction(tx).then(async (response) => { + const receipt = await response.wait(); + console.log(`Transaction sent: ${response.hash}, confirmed in block: ${receipt.blockNumber}`); + return response; + }).catch((error) => { + console.error(`Error sending transaction to ${w.address}: ${error.message}`); + throw error; + }); + + transactionPromises.push(transactionPromise); + } + await Promise.all(transactionPromises); +} - const walletEthers = new ethers.Wallet(L1_RICH_PK, l1provider); +async function main() { + // Initialize the rich wallet, ERC20 contract and providers + const l1Provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT) + const l2Provider = new Provider(L2_RPC_ENDPOINT); + const richWallet = new Wallet(L1_RICH.pk, l2Provider, l1Provider); - const ERC20_L1 = new ethers.Contract(await l2provider.getBaseTokenContractAddress(), contractAbi, walletEthers); + const walletEthers = new ethers.Wallet(L1_RICH_PK, l1Provider); + const ERC20_L1 = new ethers.Contract(await l2Provider.getBaseTokenContractAddress(), contractAbi, walletEthers); const ERC20_SYMBOL: string = await ERC20_L1.symbol(); const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); - console.log("#####################################################\n"); - - // Used locally - await ERC20_L1.mint(await walletEthers.getAddress(), BigInt(10000 * ERC20_DECIMALS_MUL)); - await getERC20Balance(wallet1.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - - const tx = await wallet1.deposit({ - token: await l2provider.getBaseTokenContractAddress(), - to: await wallet1.getAddress(), - amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) * 2.05)), - approveBaseERC20: true, - approveERC20: true, - }); - const receipt = await tx.wait(); - console.log(`Tx: ${receipt.transactionHash}`); - - console.log("\n#####################################################\n") - console.log(`L1 balance after deposit: ${ethers.utils.formatEther(await wallet1.getBalanceL1())}`); - console.log(`L2 balance after deposit: ${ethers.utils.formatEther(await wallet1.getBalance())}`); - console.log("\n#####################################################\n") + let gasConsumed: ethers.BigNumber = 0; - console.log(`Running script to generate transactions between two accounts in L2`); - console.log(`With an interval between txs of ${SLEEP_MS}[ms]`); - console.log(`Using ${AMOUNT_TO_PASS}ETH to send back and forth`); - console.log(`Using:\naddr(1): ${L1_RICH.addr}\naddr(2): ${L2_ACCOUNT.addr}`); + // Initialize the rich wallet. + let wallets: Wallet[] = new Array(); + for (let index = 0; index < AMOUNT_OF_WALLETS; index++) { + const pk = Wallet.createRandom().privateKey; + const w = new Wallet(pk, l2Provider, l1Provider); + wallets.push(w) + } + const amountForEach = Number(AMOUNT_TO_BRIDGE) / wallets.length; + console.log("#####################################################\n"); + wallets.forEach((w, i) => { + console.log(`Wallet(${i.toString().padStart(2, '0')}) addr: ${w.address} || pk: ${w.privateKey}`); + }); + console.log("\n#####################################################\n"); + console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); + console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); console.log("\n#####################################################\n"); - console.log("Send initial funds to the second wallet to pay the fees"); - - const tx0 = await wallet1.transfer({ - to: await wallet2.getAddress(), - amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) / 3)), - }); - const receipt1 = await tx0.wait(); - console.log(`Tx(0): ${receipt1.transactionHash}`); + const erc20Balance: number = await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + if (erc20Balance <= Number(AMOUNT_TO_BRIDGE)) { + const response = await ERC20_L1.mint(walletEthers.address, AMOUNT_TO_BRIDGE); + const receipt = await response.wait(); + } - const tx02 = await wallet1.transfer({ - to: await wallet3.getAddress(), - amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) / 3)), + let consumedL1Gas = await walletEthers.provider.getBalance(walletEthers.address); + wallets.forEach(async w => { + await l1ERC20Transfer(walletEthers, amountForEach, w.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); }); - const receipt02 = await tx02.wait(); - console.log(`Tx(0): ${receipt02.transactionHash}`); + consumedL1Gas = consumedL1Gas.sub(await walletEthers.provider.getBalance(walletEthers.address)); - const txFeeWithdrawal = await wallet1.transfer({ - to: "0xf2248620e8E98628b4F4a82a3f6dfe4F5993ceBa", - amount: ethers.utils.parseEther(String(Number(AMOUNT_TO_BRIDGE) / 3)), - }); - const receiptFeeWithdrawal = await txFeeWithdrawal.wait(); - console.log(`Tx(0): ${receiptFeeWithdrawal.transactionHash}`); - await getERC20Balance("0xf2248620e8E98628b4F4a82a3f6dfe4F5993ceBa", ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - - while (true) { - const tx1 = await wallet2.transfer({ - to: await wallet3.getAddress(), - amount: ethers.utils.parseEther(AMOUNT_TO_PASS), - }); - const receipt1 = await tx1.wait(); - console.log(`Tx(1): ${receipt1.transactionHash}`); + console.log("ERC20 Sent on L1"); + console.log("#####################################################\n"); - const tx2 = await wallet3.transfer({ - to: await wallet2.getAddress(), - amount: ethers.utils.parseEther(AMOUNT_TO_PASS), - }); - const receipt2 = await tx2.wait(); - console.log(`Tx(2): ${receipt2.transactionHash}`); - console.log(`addr(1): ${wallet3.address} balance: ${ethers.utils.formatEther(await wallet3.getBalance())}`); - console.log(`addr(2): ${wallet2.address} balance: ${ethers.utils.formatEther(await wallet2.getBalance())}`); - console.log("\n#####################################################\n") - await Bun.sleep(sleep); - } + const BASE_TOKEN_ADDRESS = await l2Provider.getBaseTokenContractAddress(); + //let nonce = await l1Provider.getTransactionCount(walletEthers.address); + //let transactionPromises: Promise[] = []; + //for (const w of wallets) { + // const tx = { + // to: w.address, + // nonce: nonce++, + // value: ethers.utils.parseEther(String(amountForEach)), + // gasLimit: 21000, + // gasPrice: await l1Provider.getGasPrice(), + // }; + // + // const transactionPromise = walletEthers.sendTransaction(tx).then(async (response) => { + // const receipt = await response.wait(); + // console.log(`Transaction sent: ${response.hash}, confirmed in block: ${receipt.blockNumber}`); + // return response; + // }).catch((error) => { + // console.error(`Error sending transaction to ${w.address}: ${error.message}`); + // throw error; + // }); + // transactionPromises.push(transactionPromise); + // + //} + // + //await Promise.all(transactionPromises); + await sendMultipleTransactions(walletEthers, wallets, String(amountForEach)); } + main() .then() .catch((error) => { From 7b5d70248634eb7fce3bd1ab34e4246477b8a024 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Mon, 12 Aug 2024 14:48:41 -0300 Subject: [PATCH 04/11] wip: working on a way to send many txs non-blocking --- utils/scripts/gasCalculations.ts | 87 +++++++++++++++----------------- utils/scripts/geter20.ts | 49 ++++++++++++++++++ 2 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 utils/scripts/geter20.ts diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts index 9ad8f23..6d8b635 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/scripts/gasCalculations.ts @@ -22,28 +22,28 @@ const L1_RICH = { }; const getERC20Balance = async (address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { - await ERC20_L1.balanceOf(address) + return await ERC20_L1.balanceOf(address) .then((balance: number) => { console.log(`L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}`); - return balance + return balance / ERC20_DECIMALS_MUL; }) .catch(() => { console.error("Error fetching ERC20 balance from L1"); return 0; }); - return 0; } -const deposit = async (zkwallet: Wallet, token: string, amount: string) => { +const deposit = async (zkwallet: Wallet, token: string, amount: string | number) => { + const parsedAmount = (typeof (amount) == "number") ? amount.toString() : amount; const txEstimate = await zkwallet.getDepositTx({ token, - amount: ethers.utils.parseEther(amount) + amount: ethers.utils.parseEther(parsedAmount) }) const limit = await zkwallet.provider.estimateGas(txEstimate); const gasLimit = Math.ceil(limit.toNumber() * 1.2); const tx = await zkwallet.deposit({ token, - amount: (ethers.utils.parseEther(amount)).sub(gasLimit), + amount: (ethers.utils.parseEther(parsedAmount)).sub(gasLimit), approveERC20: true, approveBaseERC20: true, overrides: { @@ -58,30 +58,45 @@ const deposit = async (zkwallet: Wallet, token: string, amount: string) => { console.log("\n#####################################################\n") } -const l1ERC20Transfer = async (ethwallet: ethers.Wallet, amount: string, address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { - const data = ERC20_L1.interface.encodeFunctionData("transfer", [address, ethers.utils.parseEther(amount)]) +const l1ERC20Transfer = async (ethwallet: ethers.Wallet, amount: string | number, address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { + const parsedAmount = (typeof (amount) == "number") ? amount.toString() : amount; + const data = ERC20_L1.interface.encodeFunctionData("transfer", [address, ethers.utils.parseEther(parsedAmount)]) const limit = await ethwallet.provider.estimateGas({ to: ERC20_L1.address, from: ethwallet.address, data: data }); const gasLimit = Math.ceil(limit.toNumber() * 1.2); - const tx = await ethwallet.sendTransaction({ + + ethwallet.sendTransaction({ to: ERC20_L1.address, from: ethwallet.address, data: data, gasLimit, + }).then(async (response) => { + const receipt = await response.wait(); + console.log("\n#####################################################\n") + console.log(`Wallet: ${address}\nTx hash: ${receipt.transactionHash}`) + await getERC20Balance(address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + console.log("\n#####################################################\n") + return response; + }).catch((error) => { + throw error; }); - const receipt = await tx.wait(); +} - console.log("\n#####################################################\n") - console.log(`Wallet: ${address} || Tx hash: ${receipt.transactionHash}`) - await getERC20Balance(address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - console.log("\n#####################################################\n") +async function sendMultipleL1ERC20Transactions(walletEthers: ethers.Wallet, wallets: Wallet[], amountForEach: string | number, ERC20_L1: ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) { + const amount = (typeof (amountForEach) == "number") ? amountForEach.toString() : amountForEach; + const transactionPromises: Promise[] = []; + for (const w of wallets) { + const transactionPromise = l1ERC20Transfer(walletEthers, amount, w.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL) + transactionPromises.push(transactionPromise); + } + await Promise.all(transactionPromises); } -async function sendMultipleTransactions(walletEthers, wallets: { address: string }[], amountForEach: string | number) { - const amount = isNumberObject(amountForEach) ? String(amountForEach) : amountForEach; +async function sendMultipleL1Transactions(walletEthers: ethers.Wallet, wallets: Wallet[], amountForEach: string | number) { + const amount = (typeof (amountForEach) == "number") ? amountForEach.toString() : amountForEach; let nonce = await walletEthers.provider.getTransactionCount(walletEthers.address, 'latest'); const transactionPromises: Promise[] = []; @@ -90,7 +105,8 @@ async function sendMultipleTransactions(walletEthers, wallets: { address: string to: w.address, nonce: nonce++, value: ethers.utils.parseEther(amount), - gasLimit: 21000 + gasLimit: 21000, + gasPrice: await walletEthers.provider.getGasPrice() }; const transactionPromise = walletEthers.sendTransaction(tx).then(async (response) => { @@ -140,46 +156,23 @@ async function main() { console.log("\n#####################################################\n"); const erc20Balance: number = await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - if (erc20Balance <= Number(AMOUNT_TO_BRIDGE)) { - const response = await ERC20_L1.mint(walletEthers.address, AMOUNT_TO_BRIDGE); + if (erc20Balance >= Number(AMOUNT_TO_BRIDGE)) { + const response = await ERC20_L1.mint(walletEthers.address, BigInt(Number(AMOUNT_TO_BRIDGE) * ERC20_DECIMALS_MUL)); const receipt = await response.wait(); + console.log(`${AMOUNT_TO_BRIDGE} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}`); + await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); } + + await sendMultipleL1Transactions(walletEthers, wallets, amountForEach); let consumedL1Gas = await walletEthers.provider.getBalance(walletEthers.address); - wallets.forEach(async w => { - await l1ERC20Transfer(walletEthers, amountForEach, w.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - }); + await sendMultipleL1ERC20Transactions(walletEthers, wallets, amountForEach, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); consumedL1Gas = consumedL1Gas.sub(await walletEthers.provider.getBalance(walletEthers.address)); console.log("ERC20 Sent on L1"); console.log("#####################################################\n"); const BASE_TOKEN_ADDRESS = await l2Provider.getBaseTokenContractAddress(); - //let nonce = await l1Provider.getTransactionCount(walletEthers.address); - //let transactionPromises: Promise[] = []; - //for (const w of wallets) { - // const tx = { - // to: w.address, - // nonce: nonce++, - // value: ethers.utils.parseEther(String(amountForEach)), - // gasLimit: 21000, - // gasPrice: await l1Provider.getGasPrice(), - // }; - // - // const transactionPromise = walletEthers.sendTransaction(tx).then(async (response) => { - // const receipt = await response.wait(); - // console.log(`Transaction sent: ${response.hash}, confirmed in block: ${receipt.blockNumber}`); - // return response; - // }).catch((error) => { - // console.error(`Error sending transaction to ${w.address}: ${error.message}`); - // throw error; - // }); - // transactionPromises.push(transactionPromise); - // - //} - // - //await Promise.all(transactionPromises); - await sendMultipleTransactions(walletEthers, wallets, String(amountForEach)); } diff --git a/utils/scripts/geter20.ts b/utils/scripts/geter20.ts new file mode 100644 index 0000000..3b64dff --- /dev/null +++ b/utils/scripts/geter20.ts @@ -0,0 +1,49 @@ +import { Wallet, Provider, utils } from "zksync-ethers"; +import { IERC20 } from "zksync-ethers/build/utils"; +import * as ethers from "ethers"; +import { env } from "process"; +import { parseArgs } from "util"; +import contractAbi from "./erc20_abi.json"; + + +// HTTP RPC endpoints +const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; +const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; + +const getERC20Balance = async (address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { + await ERC20_L1.balanceOf(address) + .then((balance: number) => { + console.log(`L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}`); + }) + .catch(() => { + console.error("Error fetching ERC20 balance from L1"); + }); +} +const L1_RICH_PK = "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; +async function main() { + // Initialize the wallet. + const l1provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT) + const l2provider = new Provider(L2_RPC_ENDPOINT); + + console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); + console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); + + + const walletEthers = new ethers.Wallet(L1_RICH_PK, l1provider); + + const ERC20_L1 = new ethers.Contract(await l2provider.getBaseTokenContractAddress(), contractAbi, walletEthers); + const ERC20_SYMBOL: string = await ERC20_L1.symbol(); + const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); + + console.log("#####################################################\n"); + + await getERC20Balance("0xf2248620e8E98628b4F4a82a3f6dfe4F5993ceBa", ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); +} + +main() + .then() + .catch((error) => { + console.error(error); + env.exitCode = "1"; + }); From 4df4022ca98caf45cd0ab6ad17e5af0b55103d8e Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Mon, 12 Aug 2024 16:07:09 -0300 Subject: [PATCH 05/11] feat(l1-txs): erc20 txs and eth txs working --- utils/scripts/gasCalculations.ts | 240 +++++++++++++++++++++---------- 1 file changed, 166 insertions(+), 74 deletions(-) diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts index 6d8b635..6c9b5ac 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/scripts/gasCalculations.ts @@ -4,7 +4,7 @@ import { IERC20 } from "zksync-ethers/build/utils"; import * as ethers from "ethers"; import { env } from "process"; import contractAbi from "./erc20_abi.json"; -import { isNumberObject, isStringObject } from "util/types"; +import { TransactionResponse } from "zksync-ethers/build/types"; // HTTP RPC endpoints const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; @@ -12,93 +12,148 @@ const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; const AMOUNT_TO_PASS = env.AMOUNT_TO_PASS || "0.1"; const AMOUNT_TO_BRIDGE = env.AMOUNT_TO_BRIDGE || "100"; -const AMOUNT_OF_WALLETS = 1; +const AMOUNT_OF_WALLETS = 5; -const L1_RICH_PK = env.L1_RICH_PK || "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; +const L1_RICH_PK = + env.L1_RICH_PK || + "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; const L1_RICH = { addr: ethers.utils.computeAddress(L1_RICH_PK), pk: L1_RICH_PK, }; -const getERC20Balance = async (address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { +const getERC20Balance = async ( + address: string, + ERC20_L1: ethers.ethers.Contract, + ERC20_DECIMALS_MUL: number, + ERC20_SYMBOL: string +) => { return await ERC20_L1.balanceOf(address) .then((balance: number) => { - console.log(`L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}`); + console.log( + `L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}` + ); return balance / ERC20_DECIMALS_MUL; }) .catch(() => { console.error("Error fetching ERC20 balance from L1"); return 0; }); -} +}; -const deposit = async (zkwallet: Wallet, token: string, amount: string | number) => { - const parsedAmount = (typeof (amount) == "number") ? amount.toString() : amount; +const l2BaseTokenDeposit = async ( + zkwallet: Wallet, + token: string, + amount: string | number +) => { + const parsedAmount = typeof amount == "number" ? amount.toString() : amount; const txEstimate = await zkwallet.getDepositTx({ token, - amount: ethers.utils.parseEther(parsedAmount) - }) + amount: ethers.utils.parseEther(parsedAmount), + }); const limit = await zkwallet.provider.estimateGas(txEstimate); + // TODO: maybe it is not necessary to multiply the gasLimit in order to have some headroom + console.log(`[TODO: FIX gasLimit calculations`); const gasLimit = Math.ceil(limit.toNumber() * 1.2); const tx = await zkwallet.deposit({ token, - amount: (ethers.utils.parseEther(parsedAmount)).sub(gasLimit), + amount: ethers.utils.parseEther(parsedAmount).sub(gasLimit), approveERC20: true, approveBaseERC20: true, overrides: { - gasLimit - } + gasLimit, + }, }); const receipt = await tx.wait(); console.log(`Tx: ${receipt.transactionHash}`); - console.log("\n#####################################################\n") - console.log(`L2 balance after deposit: ${ethers.utils.formatEther(await zkwallet.getBalance())}`) - console.log("\n#####################################################\n") -} + console.log("\n#####################################################\n"); + console.log( + `L2 balance after deposit: ${ethers.utils.formatEther(await zkwallet.getBalance())}` + ); + console.log("\n#####################################################\n"); +}; -const l1ERC20Transfer = async (ethwallet: ethers.Wallet, amount: string | number, address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { - const parsedAmount = (typeof (amount) == "number") ? amount.toString() : amount; - const data = ERC20_L1.interface.encodeFunctionData("transfer", [address, ethers.utils.parseEther(parsedAmount)]) +const l1ERC20Transfer = async ( + ethwallet: ethers.Wallet, + nonce: number, + amount: string | number, + address: string, + ERC20_L1: ethers.ethers.Contract, +) => { + const parsedAmount = typeof amount == "number" ? amount.toString() : amount; + const data = ERC20_L1.interface.encodeFunctionData("transfer", [ + address, + ethers.utils.parseEther(parsedAmount), + ]); const limit = await ethwallet.provider.estimateGas({ to: ERC20_L1.address, from: ethwallet.address, - data: data - }); - const gasLimit = Math.ceil(limit.toNumber() * 1.2); - - ethwallet.sendTransaction({ - to: ERC20_L1.address, - from: ethwallet.address, + nonce, data: data, - gasLimit, - }).then(async (response) => { - const receipt = await response.wait(); - console.log("\n#####################################################\n") - console.log(`Wallet: ${address}\nTx hash: ${receipt.transactionHash}`) - await getERC20Balance(address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - console.log("\n#####################################################\n") - return response; - }).catch((error) => { - throw error; }); -} + const gasLimit = Math.ceil(limit.toNumber() * 1.2); -async function sendMultipleL1ERC20Transactions(walletEthers: ethers.Wallet, wallets: Wallet[], amountForEach: string | number, ERC20_L1: ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) { - const amount = (typeof (amountForEach) == "number") ? amountForEach.toString() : amountForEach; - const transactionPromises: Promise[] = []; + return ethwallet + .sendTransaction({ + to: ERC20_L1.address, + from: ethwallet.address, + nonce, + data: data, + gasLimit, + }) + .then(async (response) => { + const receipt = await response.wait(); + console.log("#####################################################"); + console.log(`Wallet: ${address}\nTx hash: ${receipt.transactionHash}`); + console.log("#####################################################"); + return response; + }) + .catch((error) => { + throw error; + }); +}; + +async function sendMultipleL1ERC20Transfers( + walletEthers: ethers.Wallet, + wallets: Wallet[], + amountForEach: string | number, + ERC20_L1: ethers.Contract, +) { + const amount = + typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; + const transactionPromises: Promise[] = []; + let nonce = await walletEthers.provider.getTransactionCount( + walletEthers.address, + "latest" + ); for (const w of wallets) { - const transactionPromise = l1ERC20Transfer(walletEthers, amount, w.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL) + const transactionPromise = l1ERC20Transfer( + walletEthers, + nonce++, + amount, + w.address, + ERC20_L1, + ); transactionPromises.push(transactionPromise); } await Promise.all(transactionPromises); } -async function sendMultipleL1Transactions(walletEthers: ethers.Wallet, wallets: Wallet[], amountForEach: string | number) { - const amount = (typeof (amountForEach) == "number") ? amountForEach.toString() : amountForEach; - let nonce = await walletEthers.provider.getTransactionCount(walletEthers.address, 'latest'); - const transactionPromises: Promise[] = []; +async function sendMultipleL1ETHTransfers( + walletEthers: ethers.Wallet, + wallets: Wallet[], + amountForEach: string | number +) { + const amount = + typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; + let nonce = await walletEthers.provider.getTransactionCount( + walletEthers.address, + "latest" + ); + const transactionPromises: Promise[] = + []; for (const w of wallets) { const tx = { @@ -106,76 +161,113 @@ async function sendMultipleL1Transactions(walletEthers: ethers.Wallet, wallets: nonce: nonce++, value: ethers.utils.parseEther(amount), gasLimit: 21000, - gasPrice: await walletEthers.provider.getGasPrice() + gasPrice: await walletEthers.provider.getGasPrice(), }; - const transactionPromise = walletEthers.sendTransaction(tx).then(async (response) => { - const receipt = await response.wait(); - console.log(`Transaction sent: ${response.hash}, confirmed in block: ${receipt.blockNumber}`); - return response; - }).catch((error) => { - console.error(`Error sending transaction to ${w.address}: ${error.message}`); - throw error; - }); + const transactionPromise = walletEthers + .sendTransaction(tx) + .then(async (response) => { + const receipt = await response.wait(); + console.log("#####################################################"); + console.log( + `Wallet: ${w.address}\nTx hash: ${receipt.transactionHash}` + ); + console.log("#####################################################"); + return response; + }) + .catch((error) => { + throw error; + }); transactionPromises.push(transactionPromise); } await Promise.all(transactionPromises); } - async function main() { // Initialize the rich wallet, ERC20 contract and providers - const l1Provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT) + const l1Provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT); const l2Provider = new Provider(L2_RPC_ENDPOINT); const richWallet = new Wallet(L1_RICH.pk, l2Provider, l1Provider); const walletEthers = new ethers.Wallet(L1_RICH_PK, l1Provider); - const ERC20_L1 = new ethers.Contract(await l2Provider.getBaseTokenContractAddress(), contractAbi, walletEthers); + const ERC20_L1 = new ethers.Contract( + await l2Provider.getBaseTokenContractAddress(), + contractAbi, + walletEthers + ); const ERC20_SYMBOL: string = await ERC20_L1.symbol(); const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); - let gasConsumed: ethers.BigNumber = 0; - // Initialize the rich wallet. let wallets: Wallet[] = new Array(); for (let index = 0; index < AMOUNT_OF_WALLETS; index++) { const pk = Wallet.createRandom().privateKey; const w = new Wallet(pk, l2Provider, l1Provider); - wallets.push(w) + wallets.push(w); } const amountForEach = Number(AMOUNT_TO_BRIDGE) / wallets.length; console.log("#####################################################\n"); wallets.forEach((w, i) => { - console.log(`Wallet(${i.toString().padStart(2, '0')}) addr: ${w.address} || pk: ${w.privateKey}`); + console.log( + `Wallet(${i.toString().padStart(2, "0")}) addr: ${w.address} || pk: ${w.privateKey}` + ); }); console.log("\n#####################################################\n"); console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); console.log("\n#####################################################\n"); - const erc20Balance: number = await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - if (erc20Balance >= Number(AMOUNT_TO_BRIDGE)) { - const response = await ERC20_L1.mint(walletEthers.address, BigInt(Number(AMOUNT_TO_BRIDGE) * ERC20_DECIMALS_MUL)); + const erc20Balance: number = await getERC20Balance( + walletEthers.address, + ERC20_L1, + ERC20_DECIMALS_MUL, + ERC20_SYMBOL + ); + if (erc20Balance <= Number(AMOUNT_TO_BRIDGE)) { + const response = await ERC20_L1.mint( + walletEthers.address, + BigInt(Number(AMOUNT_TO_BRIDGE) * ERC20_DECIMALS_MUL) + ); const receipt = await response.wait(); - console.log(`${AMOUNT_TO_BRIDGE} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}`); - await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); + console.log( + `${AMOUNT_TO_BRIDGE} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}` + ); + await getERC20Balance( + walletEthers.address, + ERC20_L1, + ERC20_DECIMALS_MUL, + ERC20_SYMBOL + ); } - - await sendMultipleL1Transactions(walletEthers, wallets, amountForEach); - let consumedL1Gas = await walletEthers.provider.getBalance(walletEthers.address); - await sendMultipleL1ERC20Transactions(walletEthers, wallets, amountForEach, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - consumedL1Gas = consumedL1Gas.sub(await walletEthers.provider.getBalance(walletEthers.address)); + let consumedL1Gas = await walletEthers.provider.getBalance( + walletEthers.address + ); + console.log("====================================================="); + console.log(`Send ETH on L1`); + await sendMultipleL1ETHTransfers(walletEthers, wallets, amountForEach) + console.log("====================================================="); + console.log("Send ERC20 on L1"); + await sendMultipleL1ERC20Transfers( + walletEthers, + wallets, + amountForEach, + ERC20_L1 + ); + console.log("====================================================="); + consumedL1Gas = consumedL1Gas.sub( + await walletEthers.provider.getBalance(walletEthers.address) + ); console.log("ERC20 Sent on L1"); - console.log("#####################################################\n"); + console.log(`[TODO: FIX gas consumption calculations] Consumed L1 Gas: ${ethers.utils.formatEther(consumedL1Gas.sub(ethers.utils.parseEther(AMOUNT_TO_BRIDGE)))}`); + const BASE_TOKEN_ADDRESS = await l2Provider.getBaseTokenContractAddress(); } - main() .then() .catch((error) => { From b13bafd76b5bf111835870da330c3e441d879f22 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Mon, 12 Aug 2024 17:21:34 -0300 Subject: [PATCH 06/11] refactor: move functions into separated files --- utils/scripts/gasCalculations.ts | 189 +++--------------------------- utils/scripts/geter20.ts | 49 -------- utils/scripts/helpers/L1-utils.ts | 131 +++++++++++++++++++++ utils/scripts/helpers/L2-utils.ts | 73 ++++++++++++ utils/scripts/helpers/index.ts | 15 +++ 5 files changed, 234 insertions(+), 223 deletions(-) delete mode 100644 utils/scripts/geter20.ts create mode 100644 utils/scripts/helpers/L1-utils.ts create mode 100644 utils/scripts/helpers/L2-utils.ts create mode 100644 utils/scripts/helpers/index.ts diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts index 6c9b5ac..ebca1d7 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/scripts/gasCalculations.ts @@ -1,18 +1,16 @@ -import { Wallet, Provider, utils } from "zksync-ethers"; -import { IERC20 } from "zksync-ethers/build/utils"; +import { Wallet, Provider } from "zksync-ethers"; import * as ethers from "ethers"; import { env } from "process"; import contractAbi from "./erc20_abi.json"; -import { TransactionResponse } from "zksync-ethers/build/types"; +import { helpers } from "./helpers"; // HTTP RPC endpoints const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; -const AMOUNT_TO_PASS = env.AMOUNT_TO_PASS || "0.1"; const AMOUNT_TO_BRIDGE = env.AMOUNT_TO_BRIDGE || "100"; -const AMOUNT_OF_WALLETS = 5; +const AMOUNT_OF_WALLETS = 1; const L1_RICH_PK = env.L1_RICH_PK || @@ -23,172 +21,11 @@ const L1_RICH = { pk: L1_RICH_PK, }; -const getERC20Balance = async ( - address: string, - ERC20_L1: ethers.ethers.Contract, - ERC20_DECIMALS_MUL: number, - ERC20_SYMBOL: string -) => { - return await ERC20_L1.balanceOf(address) - .then((balance: number) => { - console.log( - `L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}` - ); - return balance / ERC20_DECIMALS_MUL; - }) - .catch(() => { - console.error("Error fetching ERC20 balance from L1"); - return 0; - }); -}; - -const l2BaseTokenDeposit = async ( - zkwallet: Wallet, - token: string, - amount: string | number -) => { - const parsedAmount = typeof amount == "number" ? amount.toString() : amount; - const txEstimate = await zkwallet.getDepositTx({ - token, - amount: ethers.utils.parseEther(parsedAmount), - }); - const limit = await zkwallet.provider.estimateGas(txEstimate); - // TODO: maybe it is not necessary to multiply the gasLimit in order to have some headroom - console.log(`[TODO: FIX gasLimit calculations`); - const gasLimit = Math.ceil(limit.toNumber() * 1.2); - const tx = await zkwallet.deposit({ - token, - amount: ethers.utils.parseEther(parsedAmount).sub(gasLimit), - approveERC20: true, - approveBaseERC20: true, - overrides: { - gasLimit, - }, - }); - const receipt = await tx.wait(); - console.log(`Tx: ${receipt.transactionHash}`); - - console.log("\n#####################################################\n"); - console.log( - `L2 balance after deposit: ${ethers.utils.formatEther(await zkwallet.getBalance())}` - ); - console.log("\n#####################################################\n"); -}; - -const l1ERC20Transfer = async ( - ethwallet: ethers.Wallet, - nonce: number, - amount: string | number, - address: string, - ERC20_L1: ethers.ethers.Contract, -) => { - const parsedAmount = typeof amount == "number" ? amount.toString() : amount; - const data = ERC20_L1.interface.encodeFunctionData("transfer", [ - address, - ethers.utils.parseEther(parsedAmount), - ]); - const limit = await ethwallet.provider.estimateGas({ - to: ERC20_L1.address, - from: ethwallet.address, - nonce, - data: data, - }); - const gasLimit = Math.ceil(limit.toNumber() * 1.2); - - return ethwallet - .sendTransaction({ - to: ERC20_L1.address, - from: ethwallet.address, - nonce, - data: data, - gasLimit, - }) - .then(async (response) => { - const receipt = await response.wait(); - console.log("#####################################################"); - console.log(`Wallet: ${address}\nTx hash: ${receipt.transactionHash}`); - console.log("#####################################################"); - return response; - }) - .catch((error) => { - throw error; - }); -}; - -async function sendMultipleL1ERC20Transfers( - walletEthers: ethers.Wallet, - wallets: Wallet[], - amountForEach: string | number, - ERC20_L1: ethers.Contract, -) { - const amount = - typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; - const transactionPromises: Promise[] = []; - let nonce = await walletEthers.provider.getTransactionCount( - walletEthers.address, - "latest" - ); - for (const w of wallets) { - const transactionPromise = l1ERC20Transfer( - walletEthers, - nonce++, - amount, - w.address, - ERC20_L1, - ); - transactionPromises.push(transactionPromise); - } - await Promise.all(transactionPromises); -} - -async function sendMultipleL1ETHTransfers( - walletEthers: ethers.Wallet, - wallets: Wallet[], - amountForEach: string | number -) { - const amount = - typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; - let nonce = await walletEthers.provider.getTransactionCount( - walletEthers.address, - "latest" - ); - const transactionPromises: Promise[] = - []; - - for (const w of wallets) { - const tx = { - to: w.address, - nonce: nonce++, - value: ethers.utils.parseEther(amount), - gasLimit: 21000, - gasPrice: await walletEthers.provider.getGasPrice(), - }; - - const transactionPromise = walletEthers - .sendTransaction(tx) - .then(async (response) => { - const receipt = await response.wait(); - console.log("#####################################################"); - console.log( - `Wallet: ${w.address}\nTx hash: ${receipt.transactionHash}` - ); - console.log("#####################################################"); - return response; - }) - .catch((error) => { - throw error; - }); - - transactionPromises.push(transactionPromise); - } - await Promise.all(transactionPromises); -} - async function main() { // Initialize the rich wallet, ERC20 contract and providers const l1Provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT); const l2Provider = new Provider(L2_RPC_ENDPOINT); - const richWallet = new Wallet(L1_RICH.pk, l2Provider, l1Provider); + const zkWallet = new Wallet(L1_RICH.pk, l2Provider, l1Provider); const walletEthers = new ethers.Wallet(L1_RICH_PK, l1Provider); const ERC20_L1 = new ethers.Contract( @@ -219,7 +56,7 @@ async function main() { console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); console.log("\n#####################################################\n"); - const erc20Balance: number = await getERC20Balance( + const erc20Balance: number = await helpers.l1.getERC20Balance( walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, @@ -234,7 +71,7 @@ async function main() { console.log( `${AMOUNT_TO_BRIDGE} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}` ); - await getERC20Balance( + await helpers.l1.getERC20Balance( walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, @@ -247,10 +84,10 @@ async function main() { ); console.log("====================================================="); console.log(`Send ETH on L1`); - await sendMultipleL1ETHTransfers(walletEthers, wallets, amountForEach) + await helpers.l1.sendMultipleL1ETHTransfers(walletEthers, wallets, amountForEach); console.log("====================================================="); console.log("Send ERC20 on L1"); - await sendMultipleL1ERC20Transfers( + await helpers.l1.sendMultipleL1ERC20Transfers( walletEthers, wallets, amountForEach, @@ -262,10 +99,14 @@ async function main() { await walletEthers.provider.getBalance(walletEthers.address) ); console.log("ERC20 Sent on L1"); - console.log(`[TODO: FIX gas consumption calculations] Consumed L1 Gas: ${ethers.utils.formatEther(consumedL1Gas.sub(ethers.utils.parseEther(AMOUNT_TO_BRIDGE)))}`); - + console.log( + `[TODO: FIX gas consumption calculations] Consumed L1 Gas: ${ethers.utils.formatEther(consumedL1Gas.sub(ethers.utils.parseEther(AMOUNT_TO_BRIDGE)))}` + ); - const BASE_TOKEN_ADDRESS = await l2Provider.getBaseTokenContractAddress(); + console.log("====================================================="); + console.log("Deposit BaseToken L1->L2"); + await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, wallets, amountForEach / 2); + console.log("====================================================="); } main() diff --git a/utils/scripts/geter20.ts b/utils/scripts/geter20.ts deleted file mode 100644 index 3b64dff..0000000 --- a/utils/scripts/geter20.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Wallet, Provider, utils } from "zksync-ethers"; -import { IERC20 } from "zksync-ethers/build/utils"; -import * as ethers from "ethers"; -import { env } from "process"; -import { parseArgs } from "util"; -import contractAbi from "./erc20_abi.json"; - - -// HTTP RPC endpoints -const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; -const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; - -const getERC20Balance = async (address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string) => { - await ERC20_L1.balanceOf(address) - .then((balance: number) => { - console.log(`L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}`); - }) - .catch(() => { - console.error("Error fetching ERC20 balance from L1"); - }); -} -const L1_RICH_PK = "0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8"; -async function main() { - // Initialize the wallet. - const l1provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT) - const l2provider = new Provider(L2_RPC_ENDPOINT); - - console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); - console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); - - - const walletEthers = new ethers.Wallet(L1_RICH_PK, l1provider); - - const ERC20_L1 = new ethers.Contract(await l2provider.getBaseTokenContractAddress(), contractAbi, walletEthers); - const ERC20_SYMBOL: string = await ERC20_L1.symbol(); - const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); - - console.log("#####################################################\n"); - - await getERC20Balance("0xf2248620e8E98628b4F4a82a3f6dfe4F5993ceBa", ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); - await getERC20Balance(walletEthers.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL); -} - -main() - .then() - .catch((error) => { - console.error(error); - env.exitCode = "1"; - }); diff --git a/utils/scripts/helpers/L1-utils.ts b/utils/scripts/helpers/L1-utils.ts new file mode 100644 index 0000000..9dbb7ec --- /dev/null +++ b/utils/scripts/helpers/L1-utils.ts @@ -0,0 +1,131 @@ +import { Wallet } from "zksync-ethers"; +import * as ethers from "ethers"; + +export const getERC20Balance = async ( + address: string, + ERC20_L1: ethers.ethers.Contract, + ERC20_DECIMALS_MUL: number, + ERC20_SYMBOL: string +) => { + return await ERC20_L1.balanceOf(address) + .then((balance: number) => { + console.log( + `L1 ERC20 Balance: ${balance / ERC20_DECIMALS_MUL} ${ERC20_SYMBOL}` + ); + return balance / ERC20_DECIMALS_MUL; + }) + .catch(() => { + console.error("Error fetching ERC20 balance from L1"); + return 0; + }); +}; + +export const l1ERC20Transfer = async ( + ethwallet: ethers.Wallet, + nonce: number, + amount: string | number, + address: string, + ERC20_L1: ethers.ethers.Contract +) => { + const parsedAmount = typeof amount == "number" ? amount.toString() : amount; + const data = ERC20_L1.interface.encodeFunctionData("transfer", [ + address, + ethers.utils.parseEther(parsedAmount), + ]); + const limit = await ethwallet.provider.estimateGas({ + to: ERC20_L1.address, + from: ethwallet.address, + nonce, + data: data, + }); + const gasLimit = Math.ceil(limit.toNumber() * 1.2); + + return ethwallet + .sendTransaction({ + to: ERC20_L1.address, + from: ethwallet.address, + nonce, + data: data, + gasLimit, + }) + .then(async (response) => { + const receipt = await response.wait(); + console.log("#####################################################"); + console.log(`Wallet: ${address}\nTx hash: ${receipt.transactionHash}`); + console.log("#####################################################"); + return response; + }) + .catch((error) => { + throw error; + }); +}; + +export async function sendMultipleL1ERC20Transfers( + walletEthers: ethers.Wallet, + wallets: Wallet[], + amountForEach: string | number, + ERC20_L1: ethers.Contract +) { + const amount = + typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; + const transactionPromises: Promise[] = + []; + let nonce = await walletEthers.provider.getTransactionCount( + walletEthers.address, + "latest" + ); + for (const w of wallets) { + const transactionPromise = l1ERC20Transfer( + walletEthers, + nonce++, + amount, + w.address, + ERC20_L1 + ); + transactionPromises.push(transactionPromise); + } + await Promise.all(transactionPromises); +} + +export async function sendMultipleL1ETHTransfers( + walletEthers: ethers.Wallet, + wallets: Wallet[], + amountForEach: string | number +) { + const amount = + typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; + let nonce = await walletEthers.provider.getTransactionCount( + walletEthers.address, + "latest" + ); + const transactionPromises: Promise[] = + []; + + for (const w of wallets) { + const tx = { + to: w.address, + nonce: nonce++, + value: ethers.utils.parseEther(amount), + gasLimit: 21000, + gasPrice: await walletEthers.provider.getGasPrice(), + }; + + const transactionPromise = walletEthers + .sendTransaction(tx) + .then(async (response) => { + const receipt = await response.wait(); + console.log("#####################################################"); + console.log( + `Wallet: ${w.address}\nTx hash: ${receipt.transactionHash}` + ); + console.log("#####################################################"); + return response; + }) + .catch((error) => { + throw error; + }); + + transactionPromises.push(transactionPromise); + } + await Promise.all(transactionPromises); +} diff --git a/utils/scripts/helpers/L2-utils.ts b/utils/scripts/helpers/L2-utils.ts new file mode 100644 index 0000000..ffe4cd7 --- /dev/null +++ b/utils/scripts/helpers/L2-utils.ts @@ -0,0 +1,73 @@ +import { Wallet } from "zksync-ethers"; +import * as ethers from "ethers"; + +export const l1ToL2ERC20Deposit = async ( + zkWallet: Wallet, + nonce: number, + token: string, + amount: string | number +) => { + const parsedAmount = typeof amount == "number" ? amount.toString() : amount; + const txEstimate = await zkWallet.getDepositTx({ + token, + to: zkWallet.address, + amount: ethers.utils.parseEther(parsedAmount), + }); + const limit = await zkWallet.provider.estimateGas(txEstimate); + // TODO: maybe it is not necessary to multiply the gasLimit in order to have some headroom + console.log(`[TODO: FIX gasLimit calculations`); + const gasLimit = Math.ceil(limit.toNumber() * 1.2); + return zkWallet + .deposit({ + token, + amount: ethers.utils.parseEther(parsedAmount).sub(gasLimit), + approveERC20: true, + approveBaseERC20: true, + overrides: { + nonce, + }, + }) + .then(async (response) => { + const receipt = await response.wait(); + console.log("#####################################################"); + console.log( + `Wallet: ${zkWallet.address}\nTx hash: ${receipt.transactionHash}` + ); + console.log( + `L2 balance after deposit: ${ethers.utils.formatEther(await zkWallet.getBalance())}` + ); + console.log("#####################################################"); + return response; + }) + .catch((error) => { + throw error; + }); +}; + + + +export async function sendMultipleL2BaseTokenDeposits( + zkWallet: Wallet, + wallets: Wallet[], + amountForEach: string | number +) { + const amount = + typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; + let nonce = await zkWallet.providerL1!.getTransactionCount( + zkWallet.address, + "latest" + ); + const transactionPromises: Promise[] = + []; + const baseTokenAddress = await zkWallet.provider.getBaseTokenContractAddress(); + for (const w of wallets) { + const transactionPromise = l1ToL2ERC20Deposit( + w, + nonce++, + baseTokenAddress, + amount + ); + transactionPromises.push(transactionPromise); + } + await Promise.all(transactionPromises); +} diff --git a/utils/scripts/helpers/index.ts b/utils/scripts/helpers/index.ts new file mode 100644 index 0000000..e10130e --- /dev/null +++ b/utils/scripts/helpers/index.ts @@ -0,0 +1,15 @@ +import { getERC20Balance, sendMultipleL1ERC20Transfers, sendMultipleL1ETHTransfers, l1ERC20Transfer } from "./L1-utils"; +import { l1ToL2ERC20Deposit, sendMultipleL2BaseTokenDeposits } from "./L2-utils"; + +export const helpers = { + l1: { + getERC20Balance, + sendMultipleL1ERC20Transfers, + sendMultipleL1ETHTransfers, + l1ERC20Transfer + }, + l2: { + l1ToL2ERC20Deposit, + sendMultipleL2BaseTokenDeposits + } +} From af2ffd0c92bfd19029b1f188d6fcadd9d8a98664 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Mon, 12 Aug 2024 18:01:09 -0300 Subject: [PATCH 07/11] wip(l1-to-l2-deposit) --- utils/scripts/helpers/L1-utils.ts | 8 +++---- utils/scripts/helpers/L2-utils.ts | 40 +++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/utils/scripts/helpers/L1-utils.ts b/utils/scripts/helpers/L1-utils.ts index 9dbb7ec..45bceb5 100644 --- a/utils/scripts/helpers/L1-utils.ts +++ b/utils/scripts/helpers/L1-utils.ts @@ -1,12 +1,12 @@ import { Wallet } from "zksync-ethers"; import * as ethers from "ethers"; -export const getERC20Balance = async ( +export async function getERC20Balance( address: string, ERC20_L1: ethers.ethers.Contract, ERC20_DECIMALS_MUL: number, ERC20_SYMBOL: string -) => { +) { return await ERC20_L1.balanceOf(address) .then((balance: number) => { console.log( @@ -20,13 +20,13 @@ export const getERC20Balance = async ( }); }; -export const l1ERC20Transfer = async ( +export async function l1ERC20Transfer( ethwallet: ethers.Wallet, nonce: number, amount: string | number, address: string, ERC20_L1: ethers.ethers.Contract -) => { +) { const parsedAmount = typeof amount == "number" ? amount.toString() : amount; const data = ERC20_L1.interface.encodeFunctionData("transfer", [ address, diff --git a/utils/scripts/helpers/L2-utils.ts b/utils/scripts/helpers/L2-utils.ts index ffe4cd7..b6d131b 100644 --- a/utils/scripts/helpers/L2-utils.ts +++ b/utils/scripts/helpers/L2-utils.ts @@ -1,26 +1,52 @@ import { Wallet } from "zksync-ethers"; import * as ethers from "ethers"; +import { IERC1271, IERC20 } from "zksync-ethers/build/utils"; -export const l1ToL2ERC20Deposit = async ( +export async function l1ToL2ERC20Deposit( zkWallet: Wallet, nonce: number, token: string, - amount: string | number -) => { - const parsedAmount = typeof amount == "number" ? amount.toString() : amount; + amount: string +) { + // Check Allowance [wip] + const ERC20_L1 = new ethers.Contract(token, IERC20, zkWallet); + let allowance = ERC20_L1.allowance(token, zkWallet.address) + .then(async (allowance) => { + return allowance; + }) + .catch((_error) => { + return 0; + }); + + if (allowance <= amount) { + const approveTx = await ERC20_L1.approve(zkWallet.address, ethers.utils.parseEther(String(Number(amount) * 1.05))); + await approveTx.wait(); + } + + allowance = ERC20_L1.allowance(token, zkWallet.address) + .then(async (allowance) => { + return allowance; + }) + .catch((_error) => { + return 0; + }); + + console.log(`Current allowance: ${ethers.utils.formatEther(allowance)}`); + // -------------------------------- + const txEstimate = await zkWallet.getDepositTx({ token, to: zkWallet.address, - amount: ethers.utils.parseEther(parsedAmount), + amount: ethers.utils.parseEther(amount) }); - const limit = await zkWallet.provider.estimateGas(txEstimate); + const limit = await zkWallet.estimateGasDeposit(txEstimate); // TODO: maybe it is not necessary to multiply the gasLimit in order to have some headroom console.log(`[TODO: FIX gasLimit calculations`); const gasLimit = Math.ceil(limit.toNumber() * 1.2); return zkWallet .deposit({ token, - amount: ethers.utils.parseEther(parsedAmount).sub(gasLimit), + amount: ethers.utils.parseEther(amount).sub(gasLimit), approveERC20: true, approveBaseERC20: true, overrides: { From 712f47a1568738e387b194dc3958cdd07d44ef4c Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Tue, 13 Aug 2024 10:43:02 -0300 Subject: [PATCH 08/11] feat(deposits): deposits min requirements working --- utils/scripts/gasCalculations.ts | 24 +++++----- utils/scripts/helpers/L2-utils.ts | 76 +++++++++++++++---------------- 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts index ebca1d7..56e0707 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/scripts/gasCalculations.ts @@ -10,7 +10,7 @@ const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; const AMOUNT_TO_BRIDGE = env.AMOUNT_TO_BRIDGE || "100"; -const AMOUNT_OF_WALLETS = 1; +const AMOUNT_OF_WALLETS = 5; const L1_RICH_PK = env.L1_RICH_PK || @@ -27,11 +27,11 @@ async function main() { const l2Provider = new Provider(L2_RPC_ENDPOINT); const zkWallet = new Wallet(L1_RICH.pk, l2Provider, l1Provider); - const walletEthers = new ethers.Wallet(L1_RICH_PK, l1Provider); + const ethWallet = new ethers.Wallet(L1_RICH_PK, l1Provider); const ERC20_L1 = new ethers.Contract( await l2Provider.getBaseTokenContractAddress(), contractAbi, - walletEthers + ethWallet ); const ERC20_SYMBOL: string = await ERC20_L1.symbol(); const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); @@ -57,14 +57,14 @@ async function main() { console.log("\n#####################################################\n"); const erc20Balance: number = await helpers.l1.getERC20Balance( - walletEthers.address, + ethWallet.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL ); if (erc20Balance <= Number(AMOUNT_TO_BRIDGE)) { const response = await ERC20_L1.mint( - walletEthers.address, + ethWallet.address, BigInt(Number(AMOUNT_TO_BRIDGE) * ERC20_DECIMALS_MUL) ); const receipt = await response.wait(); @@ -72,23 +72,23 @@ async function main() { `${AMOUNT_TO_BRIDGE} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}` ); await helpers.l1.getERC20Balance( - walletEthers.address, + ethWallet.address, ERC20_L1, ERC20_DECIMALS_MUL, ERC20_SYMBOL ); } - let consumedL1Gas = await walletEthers.provider.getBalance( - walletEthers.address + let consumedL1Gas = await ethWallet.provider.getBalance( + ethWallet.address ); console.log("====================================================="); console.log(`Send ETH on L1`); - await helpers.l1.sendMultipleL1ETHTransfers(walletEthers, wallets, amountForEach); + await helpers.l1.sendMultipleL1ETHTransfers(ethWallet, wallets, amountForEach); console.log("====================================================="); console.log("Send ERC20 on L1"); await helpers.l1.sendMultipleL1ERC20Transfers( - walletEthers, + ethWallet, wallets, amountForEach, ERC20_L1 @@ -96,7 +96,7 @@ async function main() { console.log("====================================================="); consumedL1Gas = consumedL1Gas.sub( - await walletEthers.provider.getBalance(walletEthers.address) + await ethWallet.provider.getBalance(ethWallet.address) ); console.log("ERC20 Sent on L1"); console.log( @@ -105,7 +105,7 @@ async function main() { console.log("====================================================="); console.log("Deposit BaseToken L1->L2"); - await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, wallets, amountForEach / 2); + await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, ethWallet, wallets, amountForEach / 2); console.log("====================================================="); } diff --git a/utils/scripts/helpers/L2-utils.ts b/utils/scripts/helpers/L2-utils.ts index b6d131b..379bea9 100644 --- a/utils/scripts/helpers/L2-utils.ts +++ b/utils/scripts/helpers/L2-utils.ts @@ -4,54 +4,52 @@ import { IERC1271, IERC20 } from "zksync-ethers/build/utils"; export async function l1ToL2ERC20Deposit( zkWallet: Wallet, - nonce: number, + ethWallet: ethers.Wallet, // Used to get allowance token: string, amount: string ) { - // Check Allowance [wip] - const ERC20_L1 = new ethers.Contract(token, IERC20, zkWallet); - let allowance = ERC20_L1.allowance(token, zkWallet.address) - .then(async (allowance) => { - return allowance; - }) - .catch((_error) => { - return 0; - }); - - if (allowance <= amount) { - const approveTx = await ERC20_L1.approve(zkWallet.address, ethers.utils.parseEther(String(Number(amount) * 1.05))); - await approveTx.wait(); - } - - allowance = ERC20_L1.allowance(token, zkWallet.address) - .then(async (allowance) => { - return allowance; - }) - .catch((_error) => { - return 0; - }); - - console.log(`Current allowance: ${ethers.utils.formatEther(allowance)}`); + // Check Allowance [wip] - This breaks the nonce + //const ERC20_L1 = new ethers.Contract(token, IERC20, ethWallet); + //let allowance = await ERC20_L1.allowance(ethWallet.address, ethWallet.address) + // .then(async (allowance) => { + // return ethers.utils.formatEther(allowance); + // }) + // .catch((_error) => { + // return ethers.utils.formatEther(0); + // }); + // + //const value = ethers.utils.parseEther(String(Number(amount) * 1.01)); + //if (ethers.utils.parseEther(allowance).lt(value)) { + // const approveTx = await ERC20_L1.approve(ethWallet.address, value); + // await approveTx.wait(); + //} + // + // + //allowance = await ERC20_L1.allowance(ethWallet.address, ethWallet.address) + // .then(async (allowance) => { + // return ethers.utils.formatEther(allowance); + // }) + // .catch((_error) => { + // return ethers.utils.formatEther(0); + // }); + // + //console.log(`Current allowance: ${allowance}`); // -------------------------------- - + console.log(`[TODO: FIX gasLimit calculations]`); const txEstimate = await zkWallet.getDepositTx({ token, - to: zkWallet.address, - amount: ethers.utils.parseEther(amount) + amount: ethers.utils.parseEther(amount), }); - const limit = await zkWallet.estimateGasDeposit(txEstimate); + // When the gas is estimated, it fails + // const limit = await zkWallet.estimateGasDeposit(txEstimate); // TODO: maybe it is not necessary to multiply the gasLimit in order to have some headroom - console.log(`[TODO: FIX gasLimit calculations`); - const gasLimit = Math.ceil(limit.toNumber() * 1.2); + //const gasLimit = Math.ceil(limit.toNumber() * 1.2); return zkWallet .deposit({ token, - amount: ethers.utils.parseEther(amount).sub(gasLimit), + amount: ethers.utils.parseEther(amount), approveERC20: true, approveBaseERC20: true, - overrides: { - nonce, - }, }) .then(async (response) => { const receipt = await response.wait(); @@ -74,22 +72,20 @@ export async function l1ToL2ERC20Deposit( export async function sendMultipleL2BaseTokenDeposits( zkWallet: Wallet, + ethWallet: ethers.Wallet, wallets: Wallet[], amountForEach: string | number ) { const amount = typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; - let nonce = await zkWallet.providerL1!.getTransactionCount( - zkWallet.address, - "latest" - ); + const transactionPromises: Promise[] = []; const baseTokenAddress = await zkWallet.provider.getBaseTokenContractAddress(); for (const w of wallets) { const transactionPromise = l1ToL2ERC20Deposit( w, - nonce++, + ethWallet, baseTokenAddress, amount ); From 77c50be76852f2222b46dbe2e5a37d4ed983f95c Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Tue, 13 Aug 2024 11:54:06 -0300 Subject: [PATCH 09/11] feat(l2-transfers) --- utils/scripts/gasCalculations.ts | 11 +++++-- utils/scripts/helpers/L2-utils.ts | 53 ++++++++++++++++++++++++++++--- utils/scripts/helpers/index.ts | 5 +-- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/utils/scripts/gasCalculations.ts b/utils/scripts/gasCalculations.ts index 56e0707..791e6d3 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/scripts/gasCalculations.ts @@ -104,8 +104,15 @@ async function main() { ); console.log("====================================================="); - console.log("Deposit BaseToken L1->L2"); - await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, ethWallet, wallets, amountForEach / 2); + const amountForEachToDeposit = amountForEach / 2; + console.log("[L1->L2]: Deposit BaseToken"); + await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, ethWallet, wallets, amountForEachToDeposit); + console.log("====================================================="); + + console.log("====================================================="); + const amountForEachToTransfer = amountForEachToDeposit / 2; + console.log("[L2->L2]: Transfer BaseToken"); + await helpers.l2.sendMultipleL2Transfers(wallets, amountForEachToTransfer); console.log("====================================================="); } diff --git a/utils/scripts/helpers/L2-utils.ts b/utils/scripts/helpers/L2-utils.ts index 379bea9..29efb14 100644 --- a/utils/scripts/helpers/L2-utils.ts +++ b/utils/scripts/helpers/L2-utils.ts @@ -1,6 +1,5 @@ import { Wallet } from "zksync-ethers"; import * as ethers from "ethers"; -import { IERC1271, IERC20 } from "zksync-ethers/build/utils"; export async function l1ToL2ERC20Deposit( zkWallet: Wallet, @@ -50,8 +49,7 @@ export async function l1ToL2ERC20Deposit( amount: ethers.utils.parseEther(amount), approveERC20: true, approveBaseERC20: true, - }) - .then(async (response) => { + }).then(async (response) => { const receipt = await response.wait(); console.log("#####################################################"); console.log( @@ -62,8 +60,7 @@ export async function l1ToL2ERC20Deposit( ); console.log("#####################################################"); return response; - }) - .catch((error) => { + }).catch((error) => { throw error; }); }; @@ -93,3 +90,49 @@ export async function sendMultipleL2BaseTokenDeposits( } await Promise.all(transactionPromises); } + + +export async function sendMultipleL2Transfers( + wallets: Wallet[], + amountForEach: string | number +) { + const amount = + typeof amountForEach == "number" ? amountForEach.toString() : amountForEach; + + const transactionPromises: Promise[] = + []; + + const randomWallets: Wallet[] = []; + for (let index = 0; index < wallets.length; index++) { + const pk = Wallet.createRandom().privateKey; + const w = new Wallet(pk, wallets[0].provider, wallets[0].providerL1); + randomWallets.push(w); + } + + console.log("#####################################################\n"); + randomWallets.forEach((w, i) => { + console.log( + `Wallet(${i.toString().padStart(2, "0")}) addr: ${w.address} || pk: ${w.privateKey}` + ); + }); + + for (let i = 0; i < wallets.length; i++) { + console.log(`[TODO: ADD gasLimit calculations]`); + const transactionPromise = wallets[i].transfer({ + to: randomWallets[i].address, + amount: ethers.utils.parseEther(amount) + }).then(async (response) => { + const receipt = await response.wait(); + console.log("#####################################################"); + console.log( + `(to):\nWallet ${randomWallets[i].address}: ${ethers.utils.formatEther(await randomWallets[i].getBalance())}\nTx hash: ${receipt.transactionHash}` + ); + console.log("#####################################################"); + return response; + }).catch((error) => { + throw error; + }); + transactionPromises.push(transactionPromise); + } + await Promise.all(transactionPromises); +} diff --git a/utils/scripts/helpers/index.ts b/utils/scripts/helpers/index.ts index e10130e..dc7689c 100644 --- a/utils/scripts/helpers/index.ts +++ b/utils/scripts/helpers/index.ts @@ -1,5 +1,5 @@ import { getERC20Balance, sendMultipleL1ERC20Transfers, sendMultipleL1ETHTransfers, l1ERC20Transfer } from "./L1-utils"; -import { l1ToL2ERC20Deposit, sendMultipleL2BaseTokenDeposits } from "./L2-utils"; +import { l1ToL2ERC20Deposit, sendMultipleL2BaseTokenDeposits, sendMultipleL2Transfers } from "./L2-utils"; export const helpers = { l1: { @@ -10,6 +10,7 @@ export const helpers = { }, l2: { l1ToL2ERC20Deposit, - sendMultipleL2BaseTokenDeposits + sendMultipleL2BaseTokenDeposits, + sendMultipleL2Transfers } } From 544c18d0c2a5d1547490c8a77aa7ed86531ffa42 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Tue, 13 Aug 2024 13:34:59 -0300 Subject: [PATCH 10/11] refactor(cli): add loadtester as cmd --- utils/bun.lockb | Bin 32586 -> 32586 bytes utils/cli.ts | 15 +++- utils/commands/index.ts | 4 + .../loadTester/cmdLoadTest.ts} | 78 +++++++++--------- .../loadTester}/helpers/L1-utils.ts | 20 +++-- .../loadTester}/helpers/L2-utils.ts | 32 +++---- .../loadTester/helpers}/erc20_abi.json | 0 .../loadTester}/helpers/index.ts | 0 utils/package.json | 2 +- 9 files changed, 88 insertions(+), 63 deletions(-) rename utils/{scripts/gasCalculations.ts => commands/loadTester/cmdLoadTest.ts} (64%) rename utils/{scripts => commands/loadTester}/helpers/L1-utils.ts (83%) rename utils/{scripts => commands/loadTester}/helpers/L2-utils.ts (79%) rename utils/{scripts => commands/loadTester/helpers}/erc20_abi.json (100%) rename utils/{scripts => commands/loadTester}/helpers/index.ts (100%) diff --git a/utils/bun.lockb b/utils/bun.lockb index c76329aa234f63b109868afade5eda38e22a419c..11a14b2a3a0ab189aacfdc968139a43bd107bf58 100755 GIT binary patch delta 161 zcmV;S0AByf{sGGV0gx^r??VFPjuXxIS3+p^DDm954gV2vz6aPVe{HWLD$maXC%%&n>jfLoad Test. The cmd makes use of a rich pk in order to perform the tests.\n\t It creates random Wallets\n\t Sends some ERC20 (amount/wallets) on L1\n\t Each wallet performs a deposit on L2\n\t The ERC20 is the zkStack's BaseToken") + .option("--l1url ", "ETH chain URL, defaults to localhost dev env") + .option("--l2url ", "zkStack chain URL, defaults to localhost dev env") + .option("--pk ", "Rich PK, defaults to RETH's rich wallet") + .option("-a, --amount ", "ERC20 Amount to send, defaults to 100") + .option("-w, --wallets ", "Amount of wallets, defaults to 5") + .example("[dev-env] load-test") + .example("[real-env] load-test --l1url --l2url --pk --amount --wallets ") + .action( + async (options) => { + await cmd.test.loadTest(options.l1url, options.l2url, options.pk, options.wallets, options.amount); + } + ); + cli.help(); cli.parse(); } @@ -96,4 +110,3 @@ main() console.error(error); process.env.exitCode = "1"; }); - diff --git a/utils/commands/index.ts b/utils/commands/index.ts index f471adb..2a73079 100644 --- a/utils/commands/index.ts +++ b/utils/commands/index.ts @@ -2,6 +2,7 @@ import { getBalance } from "./cmdGetBalance"; import { sendBalance } from "./cmdSendBalance"; import { depositBalance } from "./cmdDeposit"; import { fixNonce } from "./cmdFixNonce"; +import { loadTest } from "./loadTester/cmdLoadTest"; export const cmd = { balance: { @@ -11,5 +12,8 @@ export const cmd = { }, maintenance: { fixNonce + }, + test: { + loadTest } } diff --git a/utils/scripts/gasCalculations.ts b/utils/commands/loadTester/cmdLoadTest.ts similarity index 64% rename from utils/scripts/gasCalculations.ts rename to utils/commands/loadTester/cmdLoadTest.ts index 791e6d3..0a1aa6e 100644 --- a/utils/scripts/gasCalculations.ts +++ b/utils/commands/loadTester/cmdLoadTest.ts @@ -1,15 +1,16 @@ import { Wallet, Provider } from "zksync-ethers"; - import * as ethers from "ethers"; + import { env } from "process"; -import contractAbi from "./erc20_abi.json"; +import contractAbi from "./helpers/erc20_abi.json"; import { helpers } from "./helpers"; // HTTP RPC endpoints -const L1_RPC_ENDPOINT = env.L1_RPC_URL || "http://127.0.0.1:8545"; -const L2_RPC_ENDPOINT = env.L2_RPC_URL || "http://127.0.0.1:3050"; +const L1_RPC_ENDPOINT = "http://127.0.0.1:8545"; +const L2_RPC_ENDPOINT = "http://127.0.0.1:3050"; -const AMOUNT_TO_BRIDGE = env.AMOUNT_TO_BRIDGE || "100"; +const AMOUNT_TO_BRIDGE = "100"; +const AMOUNT_OF_ETH = "0.05"; const AMOUNT_OF_WALLETS = 5; const L1_RICH_PK = @@ -21,13 +22,14 @@ const L1_RICH = { pk: L1_RICH_PK, }; -async function main() { +export async function loadTest(l1url: string, l2url: string, pk: string, numberOfWallets: number, amount: string) { + // Initialize the rich wallet, ERC20 contract and providers - const l1Provider = new ethers.providers.JsonRpcProvider(L1_RPC_ENDPOINT); - const l2Provider = new Provider(L2_RPC_ENDPOINT); - const zkWallet = new Wallet(L1_RICH.pk, l2Provider, l1Provider); + const l1Provider = new ethers.providers.JsonRpcProvider(l1url || L1_RPC_ENDPOINT); + const l2Provider = new Provider(l2url || L2_RPC_ENDPOINT); + const zkWallet = new Wallet(pk || L1_RICH.pk, l2Provider, l1Provider); - const ethWallet = new ethers.Wallet(L1_RICH_PK, l1Provider); + const ethWallet = new ethers.Wallet(pk || L1_RICH_PK, l1Provider); const ERC20_L1 = new ethers.Contract( await l2Provider.getBaseTokenContractAddress(), contractAbi, @@ -37,13 +39,16 @@ async function main() { const ERC20_DECIMALS_MUL = Math.pow(10, Number(await ERC20_L1.decimals())); // Initialize the rich wallet. + const amountOfWallets = numberOfWallets || AMOUNT_OF_WALLETS; let wallets: Wallet[] = new Array(); - for (let index = 0; index < AMOUNT_OF_WALLETS; index++) { + for (let index = 0; index < amountOfWallets; index++) { const pk = Wallet.createRandom().privateKey; const w = new Wallet(pk, l2Provider, l1Provider); wallets.push(w); } - const amountForEach = Number(AMOUNT_TO_BRIDGE) / wallets.length; + + const amountToBridge = Number(amount || AMOUNT_TO_BRIDGE); + const amountForEach = amountToBridge / wallets.length; console.log("#####################################################\n"); wallets.forEach((w, i) => { @@ -52,8 +57,8 @@ async function main() { ); }); console.log("\n#####################################################\n"); - console.log(`L1 Endpoint: ${L1_RPC_ENDPOINT}`); - console.log(`L2 Endpoint: ${L2_RPC_ENDPOINT}`); + console.log(`[L1] Endpoint: ${L1_RPC_ENDPOINT}`); + console.log(`[L2] Endpoint: ${L2_RPC_ENDPOINT}`); console.log("\n#####################################################\n"); const erc20Balance: number = await helpers.l1.getERC20Balance( @@ -62,14 +67,14 @@ async function main() { ERC20_DECIMALS_MUL, ERC20_SYMBOL ); - if (erc20Balance <= Number(AMOUNT_TO_BRIDGE)) { + if (erc20Balance <= amountToBridge) { const response = await ERC20_L1.mint( ethWallet.address, - BigInt(Number(AMOUNT_TO_BRIDGE) * ERC20_DECIMALS_MUL) + BigInt(amountToBridge * ERC20_DECIMALS_MUL) ); const receipt = await response.wait(); console.log( - `${AMOUNT_TO_BRIDGE} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}` + `${amountToBridge} Minted ${ERC20_SYMBOL}, txHash: ${receipt.transactionHash}` ); await helpers.l1.getERC20Balance( ethWallet.address, @@ -79,46 +84,45 @@ async function main() { ); } - let consumedL1Gas = await ethWallet.provider.getBalance( - ethWallet.address - ); + let consumedL1Gas = await ethWallet.provider.getBalance(ethWallet.address); + console.log("====================================================="); - console.log(`Send ETH on L1`); - await helpers.l1.sendMultipleL1ETHTransfers(ethWallet, wallets, amountForEach); + + console.log(`[L1 -> L1]: Send ETH`); + const amountOfEth = ethers.utils.parseEther(AMOUNT_OF_ETH).div(wallets.length); + await helpers.l1.sendMultipleL1ETHTransfers(ethWallet, wallets, ethers.utils.formatEther(amountOfEth)); + console.log("====================================================="); - console.log("Send ERC20 on L1"); + + console.log("[L1 -> L1]: Send ERC20"); await helpers.l1.sendMultipleL1ERC20Transfers( ethWallet, wallets, amountForEach, ERC20_L1 ); + console.log("====================================================="); - consumedL1Gas = consumedL1Gas.sub( + consumedL1Gas = consumedL1Gas.add(amountOfEth).sub( await ethWallet.provider.getBalance(ethWallet.address) ); - console.log("ERC20 Sent on L1"); - console.log( - `[TODO: FIX gas consumption calculations] Consumed L1 Gas: ${ethers.utils.formatEther(consumedL1Gas.sub(ethers.utils.parseEther(AMOUNT_TO_BRIDGE)))}` - ); + + console.log(`Consumed L1 Gas: ${ethers.utils.formatEther(consumedL1Gas)}`); console.log("====================================================="); + + console.log(`[TODO: ADD gasLimit calculations]`); + const amountForEachToDeposit = amountForEach / 2; console.log("[L1->L2]: Deposit BaseToken"); await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, ethWallet, wallets, amountForEachToDeposit); + console.log("====================================================="); - - console.log("====================================================="); + const amountForEachToTransfer = amountForEachToDeposit / 2; console.log("[L2->L2]: Transfer BaseToken"); await helpers.l2.sendMultipleL2Transfers(wallets, amountForEachToTransfer); + console.log("====================================================="); } - -main() - .then() - .catch((error) => { - console.error(error); - env.exitCode = "1"; - }); diff --git a/utils/scripts/helpers/L1-utils.ts b/utils/commands/loadTester/helpers/L1-utils.ts similarity index 83% rename from utils/scripts/helpers/L1-utils.ts rename to utils/commands/loadTester/helpers/L1-utils.ts index 45bceb5..b0780c3 100644 --- a/utils/scripts/helpers/L1-utils.ts +++ b/utils/commands/loadTester/helpers/L1-utils.ts @@ -50,9 +50,12 @@ export async function l1ERC20Transfer( }) .then(async (response) => { const receipt = await response.wait(); - console.log("#####################################################"); - console.log(`Wallet: ${address}\nTx hash: ${receipt.transactionHash}`); - console.log("#####################################################"); + const msg = + `##################################################### + Wallet: ${ethwallet.address} + Tx hash: ${receipt.transactionHash} + #####################################################`; + console.log(msg.split('\n').map(line => line.trim()).join('\n')); return response; }) .catch((error) => { @@ -114,11 +117,12 @@ export async function sendMultipleL1ETHTransfers( .sendTransaction(tx) .then(async (response) => { const receipt = await response.wait(); - console.log("#####################################################"); - console.log( - `Wallet: ${w.address}\nTx hash: ${receipt.transactionHash}` - ); - console.log("#####################################################"); + const msg = + `##################################################### + Wallet: ${w.address} + Tx hash: ${receipt.transactionHash} + #####################################################`; + console.log(msg.split('\n').map(line => line.trim()).join('\n')); return response; }) .catch((error) => { diff --git a/utils/scripts/helpers/L2-utils.ts b/utils/commands/loadTester/helpers/L2-utils.ts similarity index 79% rename from utils/scripts/helpers/L2-utils.ts rename to utils/commands/loadTester/helpers/L2-utils.ts index 29efb14..d1a00ef 100644 --- a/utils/scripts/helpers/L2-utils.ts +++ b/utils/commands/loadTester/helpers/L2-utils.ts @@ -34,7 +34,7 @@ export async function l1ToL2ERC20Deposit( // //console.log(`Current allowance: ${allowance}`); // -------------------------------- - console.log(`[TODO: FIX gasLimit calculations]`); + //console.log(`[TODO: FIX gasLimit calculations]`); const txEstimate = await zkWallet.getDepositTx({ token, amount: ethers.utils.parseEther(amount), @@ -51,14 +51,13 @@ export async function l1ToL2ERC20Deposit( approveBaseERC20: true, }).then(async (response) => { const receipt = await response.wait(); - console.log("#####################################################"); - console.log( - `Wallet: ${zkWallet.address}\nTx hash: ${receipt.transactionHash}` - ); - console.log( - `L2 balance after deposit: ${ethers.utils.formatEther(await zkWallet.getBalance())}` - ); - console.log("#####################################################"); + const msg = + `##################################################### + Wallet: ${zkWallet.address} + Tx hash: ${receipt.transactionHash} + L2 balance after deposit: ${ethers.utils.formatEther(await zkWallet.getBalance())} + #####################################################`; + console.log(msg.split('\n').map(line => line.trim()).join('\n')); return response; }).catch((error) => { throw error; @@ -109,25 +108,26 @@ export async function sendMultipleL2Transfers( randomWallets.push(w); } - console.log("#####################################################\n"); + console.log("\n#####################################################\n"); randomWallets.forEach((w, i) => { console.log( `Wallet(${i.toString().padStart(2, "0")}) addr: ${w.address} || pk: ${w.privateKey}` ); }); + console.log("\n#####################################################\n"); for (let i = 0; i < wallets.length; i++) { - console.log(`[TODO: ADD gasLimit calculations]`); const transactionPromise = wallets[i].transfer({ to: randomWallets[i].address, amount: ethers.utils.parseEther(amount) }).then(async (response) => { const receipt = await response.wait(); - console.log("#####################################################"); - console.log( - `(to):\nWallet ${randomWallets[i].address}: ${ethers.utils.formatEther(await randomWallets[i].getBalance())}\nTx hash: ${receipt.transactionHash}` - ); - console.log("#####################################################"); + const msg = + `##################################################### + (to): ${randomWallets[i].address} balance: ${ethers.utils.formatEther(await randomWallets[i].getBalance())} + Tx hash: ${receipt.transactionHash} + #####################################################`; + console.log(msg.split('\n').map(line => line.trim()).join('\n')); return response; }).catch((error) => { throw error; diff --git a/utils/scripts/erc20_abi.json b/utils/commands/loadTester/helpers/erc20_abi.json similarity index 100% rename from utils/scripts/erc20_abi.json rename to utils/commands/loadTester/helpers/erc20_abi.json diff --git a/utils/scripts/helpers/index.ts b/utils/commands/loadTester/helpers/index.ts similarity index 100% rename from utils/scripts/helpers/index.ts rename to utils/commands/loadTester/helpers/index.ts diff --git a/utils/package.json b/utils/package.json index 7ebf08e..7283e3f 100644 --- a/utils/package.json +++ b/utils/package.json @@ -3,7 +3,7 @@ "cac": "^6.7.14", "ethers": "~5.7.0", "pg": "^8.12.0", - "zksync-ethers": "5.9.0" + "zksync-ethers": "^5.9.2" }, "devDependencies": { "@types/node": "^20.14.9", From c1229812d5c301d2fa604a770bae7895db7796b6 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Tue, 13 Aug 2024 15:49:23 -0300 Subject: [PATCH 11/11] chore: rm unused code --- utils/commands/loadTester/cmdLoadTest.ts | 6 +-- utils/commands/loadTester/helpers/L2-utils.ts | 39 ------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/utils/commands/loadTester/cmdLoadTest.ts b/utils/commands/loadTester/cmdLoadTest.ts index 0a1aa6e..9470226 100644 --- a/utils/commands/loadTester/cmdLoadTest.ts +++ b/utils/commands/loadTester/cmdLoadTest.ts @@ -111,12 +111,10 @@ export async function loadTest(l1url: string, l2url: string, pk: string, numberO console.log(`Consumed L1 Gas: ${ethers.utils.formatEther(consumedL1Gas)}`); console.log("====================================================="); - - console.log(`[TODO: ADD gasLimit calculations]`); - + const amountForEachToDeposit = amountForEach / 2; console.log("[L1->L2]: Deposit BaseToken"); - await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, ethWallet, wallets, amountForEachToDeposit); + await helpers.l2.sendMultipleL2BaseTokenDeposits(zkWallet, wallets, amountForEachToDeposit); console.log("====================================================="); diff --git a/utils/commands/loadTester/helpers/L2-utils.ts b/utils/commands/loadTester/helpers/L2-utils.ts index d1a00ef..5ff15a7 100644 --- a/utils/commands/loadTester/helpers/L2-utils.ts +++ b/utils/commands/loadTester/helpers/L2-utils.ts @@ -3,46 +3,9 @@ import * as ethers from "ethers"; export async function l1ToL2ERC20Deposit( zkWallet: Wallet, - ethWallet: ethers.Wallet, // Used to get allowance token: string, amount: string ) { - // Check Allowance [wip] - This breaks the nonce - //const ERC20_L1 = new ethers.Contract(token, IERC20, ethWallet); - //let allowance = await ERC20_L1.allowance(ethWallet.address, ethWallet.address) - // .then(async (allowance) => { - // return ethers.utils.formatEther(allowance); - // }) - // .catch((_error) => { - // return ethers.utils.formatEther(0); - // }); - // - //const value = ethers.utils.parseEther(String(Number(amount) * 1.01)); - //if (ethers.utils.parseEther(allowance).lt(value)) { - // const approveTx = await ERC20_L1.approve(ethWallet.address, value); - // await approveTx.wait(); - //} - // - // - //allowance = await ERC20_L1.allowance(ethWallet.address, ethWallet.address) - // .then(async (allowance) => { - // return ethers.utils.formatEther(allowance); - // }) - // .catch((_error) => { - // return ethers.utils.formatEther(0); - // }); - // - //console.log(`Current allowance: ${allowance}`); - // -------------------------------- - //console.log(`[TODO: FIX gasLimit calculations]`); - const txEstimate = await zkWallet.getDepositTx({ - token, - amount: ethers.utils.parseEther(amount), - }); - // When the gas is estimated, it fails - // const limit = await zkWallet.estimateGasDeposit(txEstimate); - // TODO: maybe it is not necessary to multiply the gasLimit in order to have some headroom - //const gasLimit = Math.ceil(limit.toNumber() * 1.2); return zkWallet .deposit({ token, @@ -68,7 +31,6 @@ export async function l1ToL2ERC20Deposit( export async function sendMultipleL2BaseTokenDeposits( zkWallet: Wallet, - ethWallet: ethers.Wallet, wallets: Wallet[], amountForEach: string | number ) { @@ -81,7 +43,6 @@ export async function sendMultipleL2BaseTokenDeposits( for (const w of wallets) { const transactionPromise = l1ToL2ERC20Deposit( w, - ethWallet, baseTokenAddress, amount );