Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add smoketest to e2e tests #261

Merged
merged 29 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
81beb5b
Add smoketest to e2e tests
piersy Oct 17, 2024
013cf7e
Fix erroneous timeout
piersy Oct 21, 2024
54b3a9b
Remove use of only (left over from local debugging)
piersy Oct 21, 2024
a65314e
Add a sleep to prevent spamming the server
piersy Oct 21, 2024
ab7836f
Set smoketest timeout globally
piersy Oct 21, 2024
e89bad1
Add smart contract interactions to smoke test
piersy Oct 22, 2024
c1cfab5
Use writeContract instead of sendTransaction
piersy Oct 22, 2024
34ea9bd
Remove trailing space
piersy Oct 22, 2024
dfbb5a3
Extract common viem setup code to separte file
piersy Oct 22, 2024
5158b37
Correct formatting
piersy Oct 22, 2024
d8e7235
Move assertions next to fetching actions
piersy Oct 22, 2024
3955e5f
Parameterise viem smoketests
piersy Oct 22, 2024
1f87012
Fix just enough gas test
piersy Oct 22, 2024
418e542
Update skipped test to not reference missing function
piersy Oct 22, 2024
fcf6c8e
Update e2e_test/test_smoketest.sh
piersy Oct 23, 2024
bba72f7
Move unsupported tx tests from viem to go
piersy Oct 23, 2024
1960e67
Don't run golang smoketest run with usual go tests
piersy Oct 23, 2024
3e50913
Trigger e2e test runs on alfajores differently
piersy Oct 23, 2024
c76e8d1
Add debug to see why file is not found
piersy Oct 23, 2024
9e0ceba
Ensure tree is installed
piersy Oct 23, 2024
d8b70ef
Update before install
piersy Oct 23, 2024
34e4753
Update forge version and reinstate dot
piersy Oct 23, 2024
dd60913
Provide explicit paths to forge
piersy Oct 23, 2024
ed2024c
Remove debug
piersy Oct 23, 2024
00e325e
Merge branch 'celo10' into piersy/smoketest
piersy Oct 23, 2024
effa0fe
Merge branch 'celo10' into piersy/smoketest
piersy Oct 24, 2024
acb90f1
Merge remote-tracking branch 'origin/celo10' into piersy/smoketest
piersy Nov 25, 2024
6622671
Merge branch 'celo10' into piersy/smoketest
piersy Nov 25, 2024
8a205ae
Merge branch 'celo10' into piersy/smoketest
piersy Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e_test/debug-fee-currency/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 2 additions & 42 deletions e2e_test/js-tests/send_tx.mjs
Original file line number Diff line number Diff line change
@@ -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));
Expand Down
134 changes: 134 additions & 0 deletions e2e_test/js-tests/test_viem_smoketest.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { assert } from "chai";
import "mocha";
import {
parseAbi,
} from "viem";
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'));

// 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 });
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");
}

// 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,
piersy marked this conversation as resolved.
Show resolved Hide resolved
feeCurrency: 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)']);
return await walletClient.writeContract({
abi: abi,
address: process.env.TOKEN_ADDR,
functionName: 'transfer',
args: ['0x00000000000000000000000000000000DeaDBeef', 1n],
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],
});
}

["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);
});
});
});
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
piersy marked this conversation as resolved.
Show resolved Hide resolved
// 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");
});
});
73 changes: 13 additions & 60 deletions e2e_test/js-tests/test_viem_tx.mjs
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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,
Expand All @@ -78,7 +38,6 @@ const testNonceBump = async (
var secondTxHash;
try {
secondTxHash = await walletClient.sendTransaction({
account,
to: "0x00000000000000000000000000000000DeaDBeef",
value: 3,
gas: 171000,
Expand All @@ -95,7 +54,7 @@ const testNonceBump = async (
shouldReplace
) {
throw err; // Only throw if unexpected error.
}
}
}
const syncBarrierSignature =
await walletClient.signTransaction(syncBarrierRequest);
Expand All @@ -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,
Expand All @@ -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,
});
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -208,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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -334,11 +287,11 @@ 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,
feeCurrency: process.env.FEE_CURRENCY,
feeCurrency: fc,
maxFeePerGas: convertedBaseFee +2n,
maxPriorityFeePerGas: 2n,
});
Expand All @@ -352,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,
Expand Down
Loading
Loading