From 81beb5bbe1bf937ebb1ae52c8d0eefea9d3c7db5 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Thu, 17 Oct 2024 20:58:01 +0100 Subject: [PATCH 01/24] Add smoketest to e2e tests The smoketest tries all types of transaction for both sends and creates. --- e2e_test/js-tests/test_viem_smoketest.mjs | 170 ++++++++++++++++++++++ e2e_test/test_smoketest.sh | 9 ++ 2 files changed, 179 insertions(+) create mode 100644 e2e_test/js-tests/test_viem_smoketest.mjs create mode 100755 e2e_test/test_smoketest.sh diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs new file mode 100644 index 0000000000..8be8c15e26 --- /dev/null +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -0,0 +1,170 @@ +import { assert } from "chai"; +import "mocha"; +import { + createPublicClient, + createWalletClient, + http, + defineChain, +} from "viem"; +import { celoAlfajores } from "viem/chains"; +import { privateKeyToAccount } from "viem/accounts"; +import fs from "fs"; + +// Load compiled contract +const testContractJSON = JSON.parse(fs.readFileSync(process.env.COMPILED_TEST_CONTRACT, 'utf8')); + + +// Setup up chain +const devChain = defineChain({ + ...celoAlfajores, + id: 1337, + name: "local dev chain", + network: "dev", + rpcUrls: { + default: { + http: [process.env.ETH_RPC_URL], + }, + }, +}); + +const chain = (() => { + switch (process.env.NETWORK) { + case 'alfajores': + return celoAlfajores + default: + return devChain + }; +})(); + +// Set up clients/wallet +const publicClient = createPublicClient({ + chain: chain, + transport: http(), +}); +const account = privateKeyToAccount(process.env.ACC_PRIVKEY); +const walletClient = createWalletClient({ + account, + chain: chain, + transport: http(), +}); + +// check checks that the receipt has status success and that the transaction +// type matches the expected type, since viem sometimes mangles the type when +// building txs. +async function check(txHash, type) { + const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + const transaction = await publicClient.getTransaction({ hash: txHash }); + assert.equal(transaction.type, type, "transaction type does not match"); + assert.equal(receipt.status, "success", "receipt status 'failure'"); +} + +// sendTypedTransaction sends a transaction with the given type and an optional +// feeCurrency. +async function sendTypedTransaction(type, feeCurrency){ + return await walletClient.sendTransaction({ + to: "0x00000000000000000000000000000000DeaDBeef", + value: 1, + type: type, + feeCurrency: feeCurrency, + }); +} + +// sendTypedCreateTransaction sends a create transaction with the given type +// and an optional feeCurrency. +async function sendTypedCreateTransaction(type, feeCurrency){ + return await walletClient.deployContract({ + type: type, + feeCurrency: feeCurrency, + bytecode: testContractJSON.bytecode.object, + abi: testContractJSON.abi, + // The constructor args for the test contract at ../debug-fee-currency/DebugFeeCurrency.sol + args:[1n, true, true, true], + }); +} + +// verifyTypedTransactions is a helper function that submits a send and create +// transaction of the given type with optional feeCurrency and checks the +// results. +async function verifyTypedTransactions(type, feeCurrency){ + const send = await sendTypedTransaction(type, feeCurrency); + await check(send, type); + const create = await sendTypedCreateTransaction(type, feeCurrency); + await check(create, type); +} + +describe("viem smoke test", () => { + it("send legacy tx", async () => { + const type = "legacy"; + await verifyTypedTransactions(type); + }).timeout(30_000); + + it("send eip2930 tx", async () => { + const type = "eip2930"; + await verifyTypedTransactions(type); + }).timeout(10_000); + + it("send eip1559 tx", async () => { + const type = "eip1559"; + await verifyTypedTransactions(type); + }).timeout(10_000); + + it("send cip64 tx", async () => { + const type = "cip64"; + await verifyTypedTransactions(type, process.env.FEE_CURRENCY); + }).timeout(10_000); + + // This test is failing because the produced transaction is of type cip64. + // I guess this is a problem with the viem internals. + it.skip("cip42 not supported", async () => { + const type = "cip42"; + await verifyTypedTransactions(type); + }).timeout(10_000); + + it.only("legacy tx with fee currency not supported", async () => { + const type = "legacy"; + try { + const hash = await sendTypedTransaction(type,process.env.FEE_CURRENCY); + + // When using the devnet an exception is thrown from + // sendTypedTransaction, on alfajores the transaction is submitted so we + // get a hash but it's not included. So we validate here that the + // transaction was not included. + let blockNumber = await publicClient.getBlockNumber(); + const oldBlockNumber = blockNumber; + while(blockNumber == oldBlockNumber){ + blockNumber = await publicClient.getBlockNumber(); + } + const tx = await publicClient.getTransaction({ hash: hash }); + assert.isNull(tx); + } catch (error) { + // Expect error to be thrown + return + // exceptionThrown += 1; + } + assert.fail("Managed to send unsupported legacy tx with fee currency"); + }).timeout(10_000); + + it.only("legacy create tx with fee currency not supported", async () => { + const type = "legacy"; + try { + const hash = await sendTypedCreateTransaction(type,process.env.FEE_CURRENCY); + + // When using the devnet an exception is thrown from + // sendTypedTransaction, on alfajores the transaction is submitted so we + // get a hash but it's not included. So we validate here that the + // transaction was not included. + let blockNumber = await publicClient.getBlockNumber(); + const oldBlockNumber = blockNumber; + while(blockNumber == oldBlockNumber){ + blockNumber = await publicClient.getBlockNumber(); + } + const tx = await publicClient.getTransaction({ hash: hash }); + assert.isNull(tx); + } catch (error) { + // Expect error to be thrown + return + // exceptionThrown += 1; + } + assert.fail("Managed to send unsupported legacy tx with fee currency"); + }).timeout(10_000); +}); diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh new file mode 100755 index 0000000000..8760353630 --- /dev/null +++ b/e2e_test/test_smoketest.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -eo pipefail + +source shared.sh +prepare_node + +(cd debug-fee-currency && forge build .) +export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json +cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --exit From 013cf7ed544ed59ca2ae709a7c7d72255fe869e6 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Mon, 21 Oct 2024 12:09:52 +0100 Subject: [PATCH 02/24] Fix erroneous timeout --- e2e_test/js-tests/test_viem_smoketest.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 8be8c15e26..b34d451c64 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -96,7 +96,7 @@ describe("viem smoke test", () => { it("send legacy tx", async () => { const type = "legacy"; await verifyTypedTransactions(type); - }).timeout(30_000); + }).timeout(10_000); it("send eip2930 tx", async () => { const type = "eip2930"; From 54b3a9b3bf7a3520b7901db436c899d5979b0915 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Mon, 21 Oct 2024 12:11:23 +0100 Subject: [PATCH 03/24] Remove use of only (left over from local debugging) --- e2e_test/js-tests/test_viem_smoketest.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index b34d451c64..916fc239a1 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -120,7 +120,7 @@ describe("viem smoke test", () => { await verifyTypedTransactions(type); }).timeout(10_000); - it.only("legacy tx with fee currency not supported", async () => { + it("legacy tx with fee currency not supported", async () => { const type = "legacy"; try { const hash = await sendTypedTransaction(type,process.env.FEE_CURRENCY); @@ -144,7 +144,7 @@ describe("viem smoke test", () => { assert.fail("Managed to send unsupported legacy tx with fee currency"); }).timeout(10_000); - it.only("legacy create tx with fee currency not supported", async () => { + it("legacy create tx with fee currency not supported", async () => { const type = "legacy"; try { const hash = await sendTypedCreateTransaction(type,process.env.FEE_CURRENCY); From a65314e0ba54d4e8da2a0a7b963296ac6f368130 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Mon, 21 Oct 2024 12:11:38 +0100 Subject: [PATCH 04/24] Add a sleep to prevent spamming the server --- e2e_test/js-tests/test_viem_smoketest.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 916fc239a1..773164b853 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -132,6 +132,8 @@ describe("viem smoke test", () => { let blockNumber = await publicClient.getBlockNumber(); const oldBlockNumber = blockNumber; while(blockNumber == oldBlockNumber){ + // Sleep 100ms + await new Promise(r => setTimeout(r, 100)); blockNumber = await publicClient.getBlockNumber(); } const tx = await publicClient.getTransaction({ hash: hash }); From ab7836f0bba2df686efc325e98031a1047a298a5 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Mon, 21 Oct 2024 12:28:21 +0100 Subject: [PATCH 05/24] Set smoketest timeout globally Chose a timeout of 16 seconds since the first two tests were taking 8 seconds on Alfajores. --- e2e_test/js-tests/test_viem_smoketest.mjs | 14 +++++++------- e2e_test/test_smoketest.sh | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 773164b853..5e77eb4fc9 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -96,29 +96,29 @@ describe("viem smoke test", () => { it("send legacy tx", async () => { const type = "legacy"; await verifyTypedTransactions(type); - }).timeout(10_000); + }); it("send eip2930 tx", async () => { const type = "eip2930"; await verifyTypedTransactions(type); - }).timeout(10_000); + }); it("send eip1559 tx", async () => { const type = "eip1559"; await verifyTypedTransactions(type); - }).timeout(10_000); + }); it("send cip64 tx", async () => { const type = "cip64"; await verifyTypedTransactions(type, process.env.FEE_CURRENCY); - }).timeout(10_000); + }); // This test is failing because the produced transaction is of type cip64. // I guess this is a problem with the viem internals. it.skip("cip42 not supported", async () => { const type = "cip42"; await verifyTypedTransactions(type); - }).timeout(10_000); + }); it("legacy tx with fee currency not supported", async () => { const type = "legacy"; @@ -144,7 +144,7 @@ describe("viem smoke test", () => { // exceptionThrown += 1; } assert.fail("Managed to send unsupported legacy tx with fee currency"); - }).timeout(10_000); + }); it("legacy create tx with fee currency not supported", async () => { const type = "legacy"; @@ -168,5 +168,5 @@ describe("viem smoke test", () => { // exceptionThrown += 1; } assert.fail("Managed to send unsupported legacy tx with fee currency"); - }).timeout(10_000); + }); }); diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index 8760353630..d7c9485cce 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -6,4 +6,4 @@ prepare_node (cd debug-fee-currency && forge build .) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json -cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --exit +cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 16000 --exit From e89bad1358666a7d9498bf8088b834aaeb95ac06 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 12:36:31 +0100 Subject: [PATCH 06/24] Add smart contract interactions to smoke test --- e2e_test/js-tests/test_viem_smoketest.mjs | 22 ++++++++++++++++++++++ e2e_test/test_smoketest.sh | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 5e77eb4fc9..2eaf0568b0 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -5,6 +5,8 @@ import { createWalletClient, http, defineChain, + parseAbi, + encodeFunctionData, } from "viem"; import { celoAlfajores } from "viem/chains"; import { privateKeyToAccount } from "viem/accounts"; @@ -69,6 +71,24 @@ async function sendTypedTransaction(type, feeCurrency){ }); } +// sendTypedSmartContractTransaction initiates a token transfer with the given type +// and an optional feeCurrency. +async function sendTypedSmartContractTransaction(type, feeCurrency){ + const abi = parseAbi(['function transfer(address to, uint256 value) external returns (bool)']); + const data = encodeFunctionData({ + abi: abi, + functionName: 'transfer', + args: ['0x00000000000000000000000000000000DeaDBeef', 1n] + }); + const hash = await walletClient.sendTransaction({ + type: type, + to: process.env.TOKEN_ADDR, + feeCurrency: feeCurrency, + data:data, + }); + return hash; +} + // sendTypedCreateTransaction sends a create transaction with the given type // and an optional feeCurrency. async function sendTypedCreateTransaction(type, feeCurrency){ @@ -90,6 +110,8 @@ async function verifyTypedTransactions(type, feeCurrency){ await check(send, type); const create = await sendTypedCreateTransaction(type, feeCurrency); await check(create, type); + const contract = await sendTypedSmartContractTransaction(type, feeCurrency); + await check(contract, type); } describe("viem smoke test", () => { diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index d7c9485cce..d5d70a8837 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -6,4 +6,4 @@ prepare_node (cd debug-fee-currency && forge build .) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json -cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 16000 --exit +cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit From c1cfab5d922d10e3f40a8f032a1af533bbe0e99e Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 13:01:13 +0100 Subject: [PATCH 07/24] Use writeContract instead of sendTransaction --- e2e_test/js-tests/test_viem_smoketest.mjs | 70 +++++++++++------------ 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 2eaf0568b0..8eaf095bbe 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -62,56 +62,52 @@ async function check(txHash, type) { // sendTypedTransaction sends a transaction with the given type and an optional // feeCurrency. -async function sendTypedTransaction(type, feeCurrency){ - return await walletClient.sendTransaction({ - to: "0x00000000000000000000000000000000DeaDBeef", - value: 1, - type: type, - feeCurrency: feeCurrency, - }); +async function sendTypedTransaction(type, feeCurrency) { + return await walletClient.sendTransaction({ + to: "0x00000000000000000000000000000000DeaDBeef", + value: 1, + type: type, + feeCurrency: feeCurrency, + }); } // sendTypedSmartContractTransaction initiates a token transfer with the given type // and an optional feeCurrency. -async function sendTypedSmartContractTransaction(type, feeCurrency){ +async function sendTypedSmartContractTransaction(type, feeCurrency) { const abi = parseAbi(['function transfer(address to, uint256 value) external returns (bool)']); - const data = encodeFunctionData({ + return await walletClient.writeContract({ abi: abi, + address: process.env.TOKEN_ADDR, functionName: 'transfer', - args: ['0x00000000000000000000000000000000DeaDBeef', 1n] - }); - const hash = await walletClient.sendTransaction({ + args: ['0x00000000000000000000000000000000DeaDBeef', 1n], type: type, - to: process.env.TOKEN_ADDR, feeCurrency: feeCurrency, - data:data, }); - return hash; } // sendTypedCreateTransaction sends a create transaction with the given type // and an optional feeCurrency. -async function sendTypedCreateTransaction(type, feeCurrency){ - return await walletClient.deployContract({ - type: type, - feeCurrency: feeCurrency, - bytecode: testContractJSON.bytecode.object, - abi: testContractJSON.abi, - // The constructor args for the test contract at ../debug-fee-currency/DebugFeeCurrency.sol - args:[1n, true, true, true], - }); +async function sendTypedCreateTransaction(type, feeCurrency) { + return await walletClient.deployContract({ + type: type, + feeCurrency: feeCurrency, + bytecode: testContractJSON.bytecode.object, + abi: testContractJSON.abi, + // The constructor args for the test contract at ../debug-fee-currency/DebugFeeCurrency.sol + args: [1n, true, true, true], + }); } // verifyTypedTransactions is a helper function that submits a send and create // transaction of the given type with optional feeCurrency and checks the // results. -async function verifyTypedTransactions(type, feeCurrency){ - const send = await sendTypedTransaction(type, feeCurrency); - await check(send, type); - const create = await sendTypedCreateTransaction(type, feeCurrency); - await check(create, type); - const contract = await sendTypedSmartContractTransaction(type, feeCurrency); - await check(contract, type); +async function verifyTypedTransactions(type, feeCurrency) { + const send = await sendTypedTransaction(type, feeCurrency); + await check(send, type); + const create = await sendTypedCreateTransaction(type, feeCurrency); + await check(create, type); + const contract = await sendTypedSmartContractTransaction(type, feeCurrency); + await check(contract, type); } describe("viem smoke test", () => { @@ -145,7 +141,7 @@ describe("viem smoke test", () => { it("legacy tx with fee currency not supported", async () => { const type = "legacy"; try { - const hash = await sendTypedTransaction(type,process.env.FEE_CURRENCY); + const hash = await sendTypedTransaction(type, process.env.FEE_CURRENCY); // When using the devnet an exception is thrown from // sendTypedTransaction, on alfajores the transaction is submitted so we @@ -153,7 +149,7 @@ describe("viem smoke test", () => { // transaction was not included. let blockNumber = await publicClient.getBlockNumber(); const oldBlockNumber = blockNumber; - while(blockNumber == oldBlockNumber){ + while (blockNumber == oldBlockNumber) { // Sleep 100ms await new Promise(r => setTimeout(r, 100)); blockNumber = await publicClient.getBlockNumber(); @@ -165,13 +161,13 @@ describe("viem smoke test", () => { return // exceptionThrown += 1; } - assert.fail("Managed to send unsupported legacy tx with fee currency"); + assert.fail("Managed to send unsupported legacy tx with fee currency"); }); it("legacy create tx with fee currency not supported", async () => { const type = "legacy"; try { - const hash = await sendTypedCreateTransaction(type,process.env.FEE_CURRENCY); + const hash = await sendTypedCreateTransaction(type, process.env.FEE_CURRENCY); // When using the devnet an exception is thrown from // sendTypedTransaction, on alfajores the transaction is submitted so we @@ -179,7 +175,7 @@ describe("viem smoke test", () => { // transaction was not included. let blockNumber = await publicClient.getBlockNumber(); const oldBlockNumber = blockNumber; - while(blockNumber == oldBlockNumber){ + while (blockNumber == oldBlockNumber) { blockNumber = await publicClient.getBlockNumber(); } const tx = await publicClient.getTransaction({ hash: hash }); @@ -189,6 +185,6 @@ describe("viem smoke test", () => { return // exceptionThrown += 1; } - assert.fail("Managed to send unsupported legacy tx with fee currency"); + assert.fail("Managed to send unsupported legacy tx with fee currency"); }); }); From 34ea9bdbbb94b1d82fc95510a9ed1cac60dcd5ed Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 13:02:12 +0100 Subject: [PATCH 08/24] Remove trailing space --- e2e_test/test_smoketest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index d5d70a8837..2a394eb5a7 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -6,4 +6,4 @@ prepare_node (cd debug-fee-currency && forge build .) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json -cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit +cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit From dfbb5a3232aab9e7b39956d42be5cf7a93bf6084 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 14:14:33 +0100 Subject: [PATCH 09/24] Extract common viem setup code to separte file Note that in many cases we were able to remove explicit use of account in transaction creattion because it is "hoisted" in the walletClient. Also removed chain-id and ACC_PRIVKEY as arguments from send_tx.mjs because they are controlled by env vars, which are picked up by the mjs file. --- e2e_test/debug-fee-currency/lib.sh | 2 +- e2e_test/js-tests/send_tx.mjs | 44 +------------------ e2e_test/js-tests/test_viem_smoketest.mjs | 43 +------------------ e2e_test/js-tests/test_viem_tx.mjs | 52 +---------------------- e2e_test/js-tests/viem_setup.mjs | 44 +++++++++++++++++++ 5 files changed, 50 insertions(+), 135 deletions(-) create mode 100644 e2e_test/js-tests/viem_setup.mjs diff --git a/e2e_test/debug-fee-currency/lib.sh b/e2e_test/debug-fee-currency/lib.sh index 1bedb5a14c..e0239a8c5a 100755 --- a/e2e_test/debug-fee-currency/lib.sh +++ b/e2e_test/debug-fee-currency/lib.sh @@ -50,7 +50,7 @@ function cleanup_fee_currency() { # replace the transaction with a transaction of higher priority-fee when # there is no receipt after the `waitBlocks` time passed function cip_64_tx() { - $SCRIPT_DIR/js-tests/send_tx.mjs "$(cast chain-id)" $ACC_PRIVKEY $1 $2 $3 + $SCRIPT_DIR/js-tests/send_tx.mjs $1 $2 $3 } # use this function to assert the cip_64_tx return value, by using a pipe like diff --git a/e2e_test/js-tests/send_tx.mjs b/e2e_test/js-tests/send_tx.mjs index 483205c1c6..ed40b4408b 100755 --- a/e2e_test/js-tests/send_tx.mjs +++ b/e2e_test/js-tests/send_tx.mjs @@ -1,50 +1,10 @@ #!/usr/bin/env node import { - createWalletClient, - createPublicClient, - http, - defineChain, TransactionReceiptNotFoundError, } from "viem"; -import { celoAlfajores } from "viem/chains"; -import { privateKeyToAccount } from "viem/accounts"; +import {publicClient, walletClient, account} from "./viem_setup.mjs" -const [chainId, privateKey, feeCurrency, waitBlocks, replaceTxAfterWait] = - process.argv.slice(2); -const devChain = defineChain({ - ...celoAlfajores, - id: parseInt(chainId, 10), - name: "local dev chain", - network: "dev", - rpcUrls: { - default: { - http: ["http://127.0.0.1:8545"], - }, - }, -}); - -var chain; -switch(process.env.NETWORK) { - case "alfajores": - chain = celoAlfajores; - break; - default: - chain = devChain; - // Code to run if no cases match -}; - -const account = privateKeyToAccount(privateKey); - -const publicClient = createPublicClient({ - account, - chain: chain, - transport: http(), -}); -const walletClient = createWalletClient({ - account, - chain: chain, - transport: http(), -}); +const [feeCurrency, waitBlocks, replaceTxAfterWait] = process.argv.slice(2); function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 8eaf095bbe..5e02ab26ec 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -1,55 +1,14 @@ import { assert } from "chai"; import "mocha"; import { - createPublicClient, - createWalletClient, - http, - defineChain, parseAbi, - encodeFunctionData, } from "viem"; -import { celoAlfajores } from "viem/chains"; -import { privateKeyToAccount } from "viem/accounts"; import fs from "fs"; +import {publicClient, walletClient} from "./viem_setup.mjs" // Load compiled contract const testContractJSON = JSON.parse(fs.readFileSync(process.env.COMPILED_TEST_CONTRACT, 'utf8')); - -// Setup up chain -const devChain = defineChain({ - ...celoAlfajores, - id: 1337, - name: "local dev chain", - network: "dev", - rpcUrls: { - default: { - http: [process.env.ETH_RPC_URL], - }, - }, -}); - -const chain = (() => { - switch (process.env.NETWORK) { - case 'alfajores': - return celoAlfajores - default: - return devChain - }; -})(); - -// Set up clients/wallet -const publicClient = createPublicClient({ - chain: chain, - transport: http(), -}); -const account = privateKeyToAccount(process.env.ACC_PRIVKEY); -const walletClient = createWalletClient({ - account, - chain: chain, - transport: http(), -}); - // check checks that the receipt has status success and that the transaction // type matches the expected type, since viem sometimes mangles the type when // building txs. diff --git a/e2e_test/js-tests/test_viem_tx.mjs b/e2e_test/js-tests/test_viem_tx.mjs index 7c5fd2495c..41adea0aa7 100644 --- a/e2e_test/js-tests/test_viem_tx.mjs +++ b/e2e_test/js-tests/test_viem_tx.mjs @@ -1,48 +1,9 @@ import { assert } from "chai"; import "mocha"; import { - createPublicClient, - createWalletClient, - http, - defineChain, parseAbi, } from "viem"; -import { celoAlfajores } from "viem/chains"; -import { privateKeyToAccount } from "viem/accounts"; - -// Setup up chain -const devChain = defineChain({ - ...celoAlfajores, - id: 1337, - name: "local dev chain", - network: "dev", - rpcUrls: { - default: { - http: [process.env.ETH_RPC_URL], - }, - }, -}); - -const chain = (() => { - switch (process.env.NETWORK) { - case 'alfajores': - return celoAlfajores - default: - return devChain - }; -})(); - -// Set up clients/wallet -const publicClient = createPublicClient({ - chain: chain, - transport: http(), -}); -const account = privateKeyToAccount(process.env.ACC_PRIVKEY); -const walletClient = createWalletClient({ - account, - chain: chain, - transport: http(), -}); +import {publicClient, walletClient} from "./viem_setup.mjs" // Returns the base fee per gas for the current block multiplied by 2 to account for any increase in the subsequent block. async function getGasFees(publicClient, tip, feeCurrency) { @@ -60,13 +21,12 @@ const testNonceBump = async ( shouldReplace, ) => { const syncBarrierRequest = await walletClient.prepareTransactionRequest({ - account, + to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 22000, }); const firstTxHash = await walletClient.sendTransaction({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 171000, @@ -78,7 +38,6 @@ const testNonceBump = async ( var secondTxHash; try { secondTxHash = await walletClient.sendTransaction({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 3, gas: 171000, @@ -115,7 +74,6 @@ const testNonceBump = async ( describe("viem send tx", () => { it("send basic tx and check receipt", async () => { const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 1, gas: 21000, @@ -130,7 +88,6 @@ describe("viem send tx", () => { it("send basic tx using viem gas estimation and check receipt", async () => { const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 1, }); @@ -145,7 +102,6 @@ describe("viem send tx", () => { it("send fee currency tx with explicit gas fields and check receipt", async () => { const [maxFeePerGas, tip] = await getGasFees(publicClient, 2n, process.env.FEE_CURRENCY); const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 171000, @@ -163,7 +119,6 @@ describe("viem send tx", () => { it("test gas price difference for fee currency", async () => { const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 171000, @@ -220,7 +175,6 @@ describe("viem send tx", () => { it("send fee currency with gas estimation tx and check receipt", async () => { const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 2, feeCurrency: process.env.FEE_CURRENCY, @@ -286,7 +240,6 @@ describe("viem send tx", () => { it("send tx with unregistered fee currency", async () => { const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 171000, @@ -334,7 +287,6 @@ describe("viem send tx", () => { assert.fail(`Converted base fee (${convertedBaseFee}) not less than native base fee (${block.baseFeePerGas})`); } const request = await walletClient.prepareTransactionRequest({ - account, to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 171000, diff --git a/e2e_test/js-tests/viem_setup.mjs b/e2e_test/js-tests/viem_setup.mjs new file mode 100644 index 0000000000..664f1f75f2 --- /dev/null +++ b/e2e_test/js-tests/viem_setup.mjs @@ -0,0 +1,44 @@ +import { assert } from "chai"; +import "mocha"; +import { + createPublicClient, + createWalletClient, + http, + defineChain, +} from "viem"; +import { celoAlfajores } from "viem/chains"; +import { privateKeyToAccount } from "viem/accounts"; + +// Setup up chain +const devChain = defineChain({ + ...celoAlfajores, + id: 1337, + name: "local dev chain", + network: "dev", + rpcUrls: { + default: { + http: [process.env.ETH_RPC_URL], + }, + }, +}); + +const chain = (() => { + switch (process.env.NETWORK) { + case 'alfajores': + return celoAlfajores + default: + return devChain + }; +})(); + +// Set up clients/wallet +export const publicClient = createPublicClient({ + chain: chain, + transport: http(), +}); +export const account = privateKeyToAccount(process.env.ACC_PRIVKEY); +export const walletClient = createWalletClient({ + account, + chain: chain, + transport: http(), +}); \ No newline at end of file From 5158b37d213535696a636a7b8918a5866b1e7365 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 14:18:35 +0100 Subject: [PATCH 10/24] Correct formatting --- e2e_test/js-tests/send_tx.mjs | 2 +- e2e_test/js-tests/test_viem_smoketest.mjs | 2 +- e2e_test/js-tests/test_viem_tx.mjs | 23 ++++++++++++----------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/e2e_test/js-tests/send_tx.mjs b/e2e_test/js-tests/send_tx.mjs index ed40b4408b..bbf582d97d 100755 --- a/e2e_test/js-tests/send_tx.mjs +++ b/e2e_test/js-tests/send_tx.mjs @@ -2,7 +2,7 @@ import { TransactionReceiptNotFoundError, } from "viem"; -import {publicClient, walletClient, account} from "./viem_setup.mjs" +import { publicClient, walletClient, account } from "./viem_setup.mjs" const [feeCurrency, waitBlocks, replaceTxAfterWait] = process.argv.slice(2); diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 5e02ab26ec..c35c10780d 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -4,7 +4,7 @@ import { parseAbi, } from "viem"; import fs from "fs"; -import {publicClient, walletClient} from "./viem_setup.mjs" +import { publicClient, walletClient } from "./viem_setup.mjs" // Load compiled contract const testContractJSON = JSON.parse(fs.readFileSync(process.env.COMPILED_TEST_CONTRACT, 'utf8')); diff --git a/e2e_test/js-tests/test_viem_tx.mjs b/e2e_test/js-tests/test_viem_tx.mjs index 41adea0aa7..13a689b396 100644 --- a/e2e_test/js-tests/test_viem_tx.mjs +++ b/e2e_test/js-tests/test_viem_tx.mjs @@ -3,7 +3,7 @@ import "mocha"; import { parseAbi, } from "viem"; -import {publicClient, walletClient} from "./viem_setup.mjs" +import { publicClient, walletClient } from "./viem_setup.mjs" // Returns the base fee per gas for the current block multiplied by 2 to account for any increase in the subsequent block. async function getGasFees(publicClient, tip, feeCurrency) { @@ -54,7 +54,7 @@ const testNonceBump = async ( shouldReplace ) { throw err; // Only throw if unexpected error. - } + } } const syncBarrierSignature = await walletClient.signTransaction(syncBarrierRequest); @@ -163,8 +163,8 @@ describe("viem send tx", () => { // The expected value for the max fee should be the (baseFeePerGas * multiplier) + maxPriorityFeePerGas // Instead what is currently returned is (maxFeePerGas * multiplier) + maxPriorityFeePerGas const maxPriorityFeeInFeeCurrency = (maxPriorityFeePerGasNative * numerator) / denominator; - const maxFeeInFeeCurrency = ((block.baseFeePerGas +maxPriorityFeePerGasNative)*numerator) /denominator; - assert.equal(fees.maxFeePerGas, ((maxFeeInFeeCurrency*12n)/10n) + maxPriorityFeeInFeeCurrency); + const maxFeeInFeeCurrency = ((block.baseFeePerGas + maxPriorityFeePerGasNative) * numerator) / denominator; + assert.equal(fees.maxFeePerGas, ((maxFeeInFeeCurrency * 12n) / 10n) + maxPriorityFeeInFeeCurrency); assert.equal(fees.maxPriorityFeePerGas, maxPriorityFeeInFeeCurrency); // check that the prepared transaction request uses the @@ -286,6 +286,7 @@ describe("viem send tx", () => { if (convertedBaseFee >= block.baseFeePerGas) { assert.fail(`Converted base fee (${convertedBaseFee}) not less than native base fee (${block.baseFeePerGas})`); } + const maxFeePerGas = rate.toFeeCurrency(block.baseFeePerGas) + 2n; const request = await walletClient.prepareTransactionRequest({ to: "0x00000000000000000000000000000000DeaDBeef", value: 2, @@ -304,13 +305,13 @@ describe("viem send tx", () => { }); async function getRate(feeCurrencyAddress) { - const abi = parseAbi(['function getExchangeRate(address token) public view returns (uint256 numerator, uint256 denominator)']); - const [numerator, denominator] = await publicClient.readContract({ - address: process.env.FEE_CURRENCY_DIRECTORY_ADDR, - abi: abi, - functionName: 'getExchangeRate', - args: [feeCurrencyAddress], - }); + const abi = parseAbi(['function getExchangeRate(address token) public view returns (uint256 numerator, uint256 denominator)']); + const [numerator, denominator] = await publicClient.readContract({ + address: process.env.FEE_CURRENCY_DIRECTORY_ADDR, + abi: abi, + functionName: 'getExchangeRate', + args: [feeCurrencyAddress], + }); return { toFeeCurrency: (v) => (v * numerator) / denominator, toNative: (v) => (v * denominator) / numerator, From d8e72352250ba2bc95fbd172c52b1abc1c146f71 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 14:40:16 +0100 Subject: [PATCH 11/24] Move assertions next to fetching actions --- e2e_test/js-tests/test_viem_smoketest.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index c35c10780d..89eae2f05d 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -14,9 +14,9 @@ const testContractJSON = JSON.parse(fs.readFileSync(process.env.COMPILED_TEST_CO // building txs. async function check(txHash, type) { const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + assert.equal(receipt.status, "success", "receipt status 'failure'"); const transaction = await publicClient.getTransaction({ hash: txHash }); assert.equal(transaction.type, type, "transaction type does not match"); - assert.equal(receipt.status, "success", "receipt status 'failure'"); } // sendTypedTransaction sends a transaction with the given type and an optional From 3955e5f2e4d4ba3584d4e4eeea813c0bf7f52999 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 14:52:06 +0100 Subject: [PATCH 12/24] Parameterise viem smoketests --- e2e_test/js-tests/test_viem_smoketest.mjs | 55 +++++++++-------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 89eae2f05d..f688b53997 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -57,47 +57,32 @@ async function sendTypedCreateTransaction(type, feeCurrency) { }); } -// verifyTypedTransactions is a helper function that submits a send and create -// transaction of the given type with optional feeCurrency and checks the -// results. -async function verifyTypedTransactions(type, feeCurrency) { - const send = await sendTypedTransaction(type, feeCurrency); - await check(send, type); - const create = await sendTypedCreateTransaction(type, feeCurrency); - await check(create, type); - const contract = await sendTypedSmartContractTransaction(type, feeCurrency); - await check(contract, type); -} - -describe("viem smoke test", () => { - it("send legacy tx", async () => { - const type = "legacy"; - await verifyTypedTransactions(type); - }); - - it("send eip2930 tx", async () => { - const type = "eip2930"; - await verifyTypedTransactions(type); +["legacy", "eip2930", "eip1559", "cip64"].forEach(function (type) { + describe("viem smoke test, tx type " + type, () => { + const feeCurrency = type == "cip64" ? process.env.FEE_CURRENCY : undefined; + it("send tx", async () => { + const send = await sendTypedTransaction(type, feeCurrency); + await check(send, type); + }); + it("send create tx", async () => { + const create = await sendTypedCreateTransaction(type, feeCurrency); + await check(create, type); + }); + it("send contract interaction tx", async () => { + const contract = await sendTypedSmartContractTransaction(type, feeCurrency); + await check(contract, type); + }); }); - - it("send eip1559 tx", async () => { - const type = "eip1559"; - await verifyTypedTransactions(type); - }); - - it("send cip64 tx", async () => { - const type = "cip64"; - await verifyTypedTransactions(type, process.env.FEE_CURRENCY); - }); - +}); +describe("viem smoke test, unsupported txs", () => { // This test is failing because the produced transaction is of type cip64. // I guess this is a problem with the viem internals. - it.skip("cip42 not supported", async () => { + it.skip("cip42", async () => { const type = "cip42"; await verifyTypedTransactions(type); }); - it("legacy tx with fee currency not supported", async () => { + it("legacy tx with fee currency", async () => { const type = "legacy"; try { const hash = await sendTypedTransaction(type, process.env.FEE_CURRENCY); @@ -123,7 +108,7 @@ describe("viem smoke test", () => { assert.fail("Managed to send unsupported legacy tx with fee currency"); }); - it("legacy create tx with fee currency not supported", async () => { + it("legacy create tx with fee currency", async () => { const type = "legacy"; try { const hash = await sendTypedCreateTransaction(type, process.env.FEE_CURRENCY); From 1f87012e3e6b671abc226e21e62ab166a006b119 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 15:24:14 +0100 Subject: [PATCH 13/24] Fix just enough gas test --- e2e_test/js-tests/test_viem_tx.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/js-tests/test_viem_tx.mjs b/e2e_test/js-tests/test_viem_tx.mjs index 13a689b396..655bfeb437 100644 --- a/e2e_test/js-tests/test_viem_tx.mjs +++ b/e2e_test/js-tests/test_viem_tx.mjs @@ -286,12 +286,12 @@ describe("viem send tx", () => { if (convertedBaseFee >= block.baseFeePerGas) { assert.fail(`Converted base fee (${convertedBaseFee}) not less than native base fee (${block.baseFeePerGas})`); } - const maxFeePerGas = rate.toFeeCurrency(block.baseFeePerGas) + 2n; const request = await walletClient.prepareTransactionRequest({ to: "0x00000000000000000000000000000000DeaDBeef", value: 2, gas: 171000, feeCurrency: process.env.FEE_CURRENCY, + feeCurrency: fc, maxFeePerGas: convertedBaseFee +2n, maxPriorityFeePerGas: 2n, }); From 418e542b266c39946fafa7663b64c92700c40766 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Tue, 22 Oct 2024 15:40:54 +0100 Subject: [PATCH 14/24] Update skipped test to not reference missing function --- e2e_test/js-tests/test_viem_smoketest.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index f688b53997..7fe7b9a19d 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -79,7 +79,7 @@ describe("viem smoke test, unsupported txs", () => { // I guess this is a problem with the viem internals. it.skip("cip42", async () => { const type = "cip42"; - await verifyTypedTransactions(type); + await sendTypedTransaction(type); }); it("legacy tx with fee currency", async () => { From fcf6c8e6575d43c35168168b032cbefe6ffb83c5 Mon Sep 17 00:00:00 2001 From: piersy Date: Wed, 23 Oct 2024 13:11:15 +0100 Subject: [PATCH 15/24] Update e2e_test/test_smoketest.sh Co-authored-by: Karl Bartel --- e2e_test/test_smoketest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index 2a394eb5a7..cbada083f9 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -4,6 +4,6 @@ set -eo pipefail source shared.sh prepare_node -(cd debug-fee-currency && forge build .) +(cd debug-fee-currency && forge build) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit From bba72f797902ecd4adcdc2d359489a447b27e9fa Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 15:57:18 +0100 Subject: [PATCH 16/24] Move unsupported tx tests from viem to go Due to the way that viem is structured it is a bad idea for us to block transactions based on the supplied tx attributes, since they may be supported by downstream components such as optimism's custom viem functionality. So rather than trying to test unsupported txs via viem, we now test via golang which allows us full control of the sent transaction, thereby ensuring that rejection is happening at the node level. This commit also extends the error message for deprecated transactions to distinguish between celo legacy and plain legacy transactions. --- .../celo_transaction_signing_tx_funcs.go | 3 + e2e_test/js-tests/test_viem_smoketest.mjs | 58 ---------- .../unsupported_txs_test.go | 103 ++++++++++++++++++ e2e_test/test_smoketest.sh | 4 +- 4 files changed, 109 insertions(+), 59 deletions(-) create mode 100644 e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go diff --git a/core/types/celo_transaction_signing_tx_funcs.go b/core/types/celo_transaction_signing_tx_funcs.go index 8d53abff34..a0e55c72e9 100644 --- a/core/types/celo_transaction_signing_tx_funcs.go +++ b/core/types/celo_transaction_signing_tx_funcs.go @@ -18,6 +18,9 @@ var ( return nil, nil, nil, fmt.Errorf("%w %v", ErrDeprecatedTxType, tx.Type()) }, sender: func(tx *Transaction, hashFunc func(tx *Transaction, chainID *big.Int) common.Hash, signerChainID *big.Int) (common.Address, error) { + if tx.IsCeloLegacy() { + return common.Address{}, fmt.Errorf("%w %v %v", ErrDeprecatedTxType, tx.Type(), "(celo legacy)") + } return common.Address{}, fmt.Errorf("%w %v", ErrDeprecatedTxType, tx.Type()) }, } diff --git a/e2e_test/js-tests/test_viem_smoketest.mjs b/e2e_test/js-tests/test_viem_smoketest.mjs index 7fe7b9a19d..50b2d1a810 100644 --- a/e2e_test/js-tests/test_viem_smoketest.mjs +++ b/e2e_test/js-tests/test_viem_smoketest.mjs @@ -74,61 +74,3 @@ async function sendTypedCreateTransaction(type, feeCurrency) { }); }); }); -describe("viem smoke test, unsupported txs", () => { - // This test is failing because the produced transaction is of type cip64. - // I guess this is a problem with the viem internals. - it.skip("cip42", async () => { - const type = "cip42"; - await sendTypedTransaction(type); - }); - - it("legacy tx with fee currency", async () => { - const type = "legacy"; - try { - const hash = await sendTypedTransaction(type, process.env.FEE_CURRENCY); - - // When using the devnet an exception is thrown from - // sendTypedTransaction, on alfajores the transaction is submitted so we - // get a hash but it's not included. So we validate here that the - // transaction was not included. - let blockNumber = await publicClient.getBlockNumber(); - const oldBlockNumber = blockNumber; - while (blockNumber == oldBlockNumber) { - // Sleep 100ms - await new Promise(r => setTimeout(r, 100)); - blockNumber = await publicClient.getBlockNumber(); - } - const tx = await publicClient.getTransaction({ hash: hash }); - assert.isNull(tx); - } catch (error) { - // Expect error to be thrown - return - // exceptionThrown += 1; - } - assert.fail("Managed to send unsupported legacy tx with fee currency"); - }); - - it("legacy create tx with fee currency", async () => { - const type = "legacy"; - try { - const hash = await sendTypedCreateTransaction(type, process.env.FEE_CURRENCY); - - // When using the devnet an exception is thrown from - // sendTypedTransaction, on alfajores the transaction is submitted so we - // get a hash but it's not included. So we validate here that the - // transaction was not included. - let blockNumber = await publicClient.getBlockNumber(); - const oldBlockNumber = blockNumber; - while (blockNumber == oldBlockNumber) { - blockNumber = await publicClient.getBlockNumber(); - } - const tx = await publicClient.getTransaction({ hash: hash }); - assert.isNull(tx); - } catch (error) { - // Expect error to be thrown - return - // exceptionThrown += 1; - } - assert.fail("Managed to send unsupported legacy tx with fee currency"); - }); -}); diff --git a/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go b/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go new file mode 100644 index 0000000000..34001bd9e3 --- /dev/null +++ b/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go @@ -0,0 +1,103 @@ +package smoketestunsupportedtxs + +import ( + "context" + "crypto/ecdsa" + "flag" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +) + +var ( + privateKey string + opGethRpcURL string + feeCurrency string + deadAddr = common.HexToAddress("0x00000000000000000000000000000000DeaDBeef") +) + +func init() { + // Define your custom flag + flag.StringVar(&privateKey, "private-key", "", "private key of transaction sender") + flag.StringVar(&opGethRpcURL, "op-geth-url", "", "op-geth rpc url") + flag.StringVar(&feeCurrency, "fee-currency", "", "address of the fee currency to use") +} + +func TestTxSendingFails(t *testing.T) { + key, err := parsePrivateKey(privateKey) + require.NoError(t, err) + + feeCurrencyAddr := common.HexToAddress(feeCurrency) + + client, err := ethclient.Dial(opGethRpcURL) + require.NoError(t, err) + + chainId, err := client.ChainID(context.Background()) + require.NoError(t, err) + + // Get a signer that can sign deprecated txs, we need cel2 configured but not active yet. + cel2Time := uint64(1) + signer := types.MakeSigner(¶ms.ChainConfig{Cel2Time: &cel2Time, ChainID: chainId}, big.NewInt(0), 0) + + t.Run("CeloLegacy", func(t *testing.T) { + gasPrice, err := client.SuggestGasPriceForCurrency(context.Background(), &feeCurrencyAddr) + require.NoError(t, err) + + nonce, err := client.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(key.PublicKey)) + require.NoError(t, err) + + txdata := &types.LegacyTx{ + Nonce: nonce, + To: &deadAddr, + Gas: 100_000, + GasPrice: gasPrice, + FeeCurrency: &feeCurrencyAddr, + Value: big.NewInt(1), + CeloLegacy: true, + } + + tx, err := types.SignNewTx(key, signer, txdata) + require.NoError(t, err) + + // we expect this to fail because the tx is not supported. + err = client.SendTransaction(context.Background(), tx) + require.Error(t, err) + }) + + t.Run("CIP42", func(t *testing.T) { + gasFeeCap, err := client.SuggestGasPriceForCurrency(context.Background(), &feeCurrencyAddr) + require.NoError(t, err) + + nonce, err := client.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(key.PublicKey)) + require.NoError(t, err) + + txdata := &types.CeloDynamicFeeTx{ + Nonce: nonce, + To: &deadAddr, + Gas: 100_000, + GasFeeCap: gasFeeCap, + FeeCurrency: &feeCurrencyAddr, + Value: big.NewInt(1), + } + + tx, err := types.SignNewTx(key, signer, txdata) + require.NoError(t, err) + + // we expect this to fail because the tx is not supported. + err = client.SendTransaction(context.Background(), tx) + require.Error(t, err) + }) +} + +func parsePrivateKey(privateKey string) (*ecdsa.PrivateKey, error) { + if len(privateKey) >= 2 && privateKey[0] == '0' && (privateKey[1] == 'x' || privateKey[1] == 'X') { + privateKey = privateKey[2:] + } + return crypto.HexToECDSA(privateKey) +} diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index cbada083f9..33b1beec38 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -6,4 +6,6 @@ prepare_node (cd debug-fee-currency && forge build) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json -cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit +(cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit) +echo go test -v ./smoketest_unsupported -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY +go test -v ./smoketest_unsupported_txs -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY From 1960e679d0e06edd277987bfa6fdaff6060ed083 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 16:23:35 +0100 Subject: [PATCH 17/24] Don't run golang smoketest run with usual go tests --- e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go | 2 ++ e2e_test/test_smoketest.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go b/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go index 34001bd9e3..781e520b15 100644 --- a/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go +++ b/e2e_test/smoketest_unsupported_txs/unsupported_txs_test.go @@ -1,3 +1,5 @@ +//go:build smoketest + package smoketestunsupportedtxs import ( diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index 33b1beec38..8241e26891 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -8,4 +8,4 @@ prepare_node export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json (cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit) echo go test -v ./smoketest_unsupported -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY -go test -v ./smoketest_unsupported_txs -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY +go test -v ./smoketest_unsupported_txs -tags smoketest -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY From 3e50913911d891d34e0fa36a0f3928a5c053b773 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 17:19:10 +0100 Subject: [PATCH 18/24] Trigger e2e test runs on alfajores differently Adds a new workflow that triggers e2e test runs on alfajores once a day, and also in PRs whenever the e2e tests are updated. --- .github/workflows/ci.yaml | 4 -- .../workflows/e2e-test-deployed-network.yaml | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/e2e-test-deployed-network.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9bedc01c55..a322857132 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -45,10 +45,6 @@ jobs: shell: bash run: e2e_test/run_all_tests.sh - - name: Run e2e tests alfajores - shell: bash - run: NETWORK=alfajores e2e_test/run_all_tests.sh - Lint: runs-on: ["8-cpu","self-hosted","org"] steps: diff --git a/.github/workflows/e2e-test-deployed-network.yaml b/.github/workflows/e2e-test-deployed-network.yaml new file mode 100644 index 0000000000..04891b941f --- /dev/null +++ b/.github/workflows/e2e-test-deployed-network.yaml @@ -0,0 +1,42 @@ +name: e2e-test-deployed-network + +on: + schedule: + - cron: "0 14 * * *" + pull_request: + branches: + - master + - celo* + paths: + - 'e2e_test/**' + + workflow_dispatch: + +permissions: + contents: read + +jobs: + e2e-tests: + runs-on: ["8-cpu","self-hosted","org"] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + + - name: Build + run: make all + + - uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 + + - name: Run e2e tests alfajores + shell: bash + run: NETWORK=alfajores e2e_test/run_all_tests.sh From c76e8d16a45e8335b6d1177fd9cfddcc717d4b90 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 17:39:41 +0100 Subject: [PATCH 19/24] Add debug to see why file is not found --- e2e_test/test_smoketest.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index 8241e26891..f19945bab4 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -6,6 +6,9 @@ prepare_node (cd debug-fee-currency && forge build) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json + +echo "debug-fee-currency-tree" +tree debug-fee-currency (cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit) echo go test -v ./smoketest_unsupported -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY go test -v ./smoketest_unsupported_txs -tags smoketest -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY From 9e0cebabd1415de9ec2a0c38849de6c7779fe1a7 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 18:19:04 +0100 Subject: [PATCH 20/24] Ensure tree is installed --- .github/workflows/ci.yaml | 3 +++ .github/workflows/e2e-test-deployed-network.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a322857132..e9f3787f9c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -41,6 +41,9 @@ jobs: with: version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 + - name: Install tree + run: sudo apt-get install tree + - name: Run e2e tests local shell: bash run: e2e_test/run_all_tests.sh diff --git a/.github/workflows/e2e-test-deployed-network.yaml b/.github/workflows/e2e-test-deployed-network.yaml index 04891b941f..0178331d37 100644 --- a/.github/workflows/e2e-test-deployed-network.yaml +++ b/.github/workflows/e2e-test-deployed-network.yaml @@ -37,6 +37,9 @@ jobs: with: version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 + - name: Install tree + run: sudo apt-get install tree + - name: Run e2e tests alfajores shell: bash run: NETWORK=alfajores e2e_test/run_all_tests.sh From d8b70ef775a5287bace52d615920800bffceb693 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 18:28:39 +0100 Subject: [PATCH 21/24] Update before install --- .github/workflows/ci.yaml | 2 +- .github/workflows/e2e-test-deployed-network.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e9f3787f9c..2dbd44611d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,7 +42,7 @@ jobs: version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 - name: Install tree - run: sudo apt-get install tree + run: sudo apt-get update && sudo apt-get install tree - name: Run e2e tests local shell: bash diff --git a/.github/workflows/e2e-test-deployed-network.yaml b/.github/workflows/e2e-test-deployed-network.yaml index 0178331d37..add94396ff 100644 --- a/.github/workflows/e2e-test-deployed-network.yaml +++ b/.github/workflows/e2e-test-deployed-network.yaml @@ -38,7 +38,7 @@ jobs: version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 - name: Install tree - run: sudo apt-get install tree + run: sudo apt-get update && sudo apt-get install tree - name: Run e2e tests alfajores shell: bash From 34e47535cb02fea1d3cc232a2f9fd7db911eaf72 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 20:18:47 +0100 Subject: [PATCH 22/24] Update forge version and reinstate dot --- .github/workflows/ci.yaml | 2 +- .github/workflows/e2e-test-deployed-network.yaml | 2 +- e2e_test/test_smoketest.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2dbd44611d..e92365c377 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,7 +39,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 + version: nightly-143abd6a768eeb52a5785240b763d72a56987b4a - name: Install tree run: sudo apt-get update && sudo apt-get install tree diff --git a/.github/workflows/e2e-test-deployed-network.yaml b/.github/workflows/e2e-test-deployed-network.yaml index add94396ff..d7eb488d9f 100644 --- a/.github/workflows/e2e-test-deployed-network.yaml +++ b/.github/workflows/e2e-test-deployed-network.yaml @@ -35,7 +35,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 + version: nightly-143abd6a768eeb52a5785240b763d72a56987b4a - name: Install tree run: sudo apt-get update && sudo apt-get install tree diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index f19945bab4..399506ec04 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -4,7 +4,7 @@ set -eo pipefail source shared.sh prepare_node -(cd debug-fee-currency && forge build) +(cd debug-fee-currency && forge build .) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json echo "debug-fee-currency-tree" From dd60913e5dc11a838fad0380f1a4541227ed2a8a Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 20:43:53 +0100 Subject: [PATCH 23/24] Provide explicit paths to forge --- e2e_test/test_smoketest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index 399506ec04..fe7d9ecb86 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -4,7 +4,7 @@ set -eo pipefail source shared.sh prepare_node -(cd debug-fee-currency && forge build .) +(cd debug-fee-currency && echo "forge build --out $PWD $PWD" && forge build --out $PWD/out $PWD) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json echo "debug-fee-currency-tree" From ed2024c7346b25ced28a3fbccf965bc6069838fc Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Wed, 23 Oct 2024 21:00:46 +0100 Subject: [PATCH 24/24] Remove debug --- .github/workflows/ci.yaml | 3 --- .github/workflows/e2e-test-deployed-network.yaml | 3 --- e2e_test/test_smoketest.sh | 5 +---- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e92365c377..41106fcb2b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -41,9 +41,6 @@ jobs: with: version: nightly-143abd6a768eeb52a5785240b763d72a56987b4a - - name: Install tree - run: sudo apt-get update && sudo apt-get install tree - - name: Run e2e tests local shell: bash run: e2e_test/run_all_tests.sh diff --git a/.github/workflows/e2e-test-deployed-network.yaml b/.github/workflows/e2e-test-deployed-network.yaml index d7eb488d9f..6bf14d0127 100644 --- a/.github/workflows/e2e-test-deployed-network.yaml +++ b/.github/workflows/e2e-test-deployed-network.yaml @@ -37,9 +37,6 @@ jobs: with: version: nightly-143abd6a768eeb52a5785240b763d72a56987b4a - - name: Install tree - run: sudo apt-get update && sudo apt-get install tree - - name: Run e2e tests alfajores shell: bash run: NETWORK=alfajores e2e_test/run_all_tests.sh diff --git a/e2e_test/test_smoketest.sh b/e2e_test/test_smoketest.sh index fe7d9ecb86..7358d314a4 100755 --- a/e2e_test/test_smoketest.sh +++ b/e2e_test/test_smoketest.sh @@ -4,11 +4,8 @@ set -eo pipefail source shared.sh prepare_node -(cd debug-fee-currency && echo "forge build --out $PWD $PWD" && forge build --out $PWD/out $PWD) +(cd debug-fee-currency && forge build --out $PWD/out $PWD) export COMPILED_TEST_CONTRACT=../debug-fee-currency/out/DebugFeeCurrency.sol/DebugFeeCurrency.json - -echo "debug-fee-currency-tree" -tree debug-fee-currency (cd js-tests && ./node_modules/mocha/bin/mocha.js test_viem_smoketest.mjs --timeout 25000 --exit) echo go test -v ./smoketest_unsupported -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY go test -v ./smoketest_unsupported_txs -tags smoketest -op-geth-url $ETH_RPC_URL -private-key $ACC_PRIVKEY -fee-currency $FEE_CURRENCY