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

Refactor e2e tests #212

Merged
merged 7 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion core/celo_evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/ethereum/go-ethereum/params"
)

// XXYXX
func setCeloFieldsInBlockContext(blockContext *vm.BlockContext, header *types.Header, config *params.ChainConfig, statedb vm.StateDB) {
if !config.IsCel2(header.Time) {
return
Expand Down
11 changes: 3 additions & 8 deletions e2e_test/debug-fee-currency/deploy_and_send_tx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
#shellcheck disable=SC2034,SC2155,SC2086
set -xeo pipefail

export FEE_CURRENCY=$(\
forge create --root . --contracts . --private-key $ACC_PRIVKEY DebugFeeCurrency.sol:DebugFeeCurrency --constructor-args '100000000000000000000000000' $1 $2 $3 --json\
| jq .deployedTo -r)
source ./lib.sh

cast send --private-key $ACC_PRIVKEY $ORACLE3 'setExchangeRate(address, uint256, uint256)' $FEE_CURRENCY 2ether 1ether
cast send --private-key $ACC_PRIVKEY $FEE_CURRENCY_DIRECTORY_ADDR 'setCurrencyConfig(address, address, uint256)' $FEE_CURRENCY $ORACLE3 60000
echo Fee currency: $FEE_CURRENCY

(cd ../js-tests/ && ./send_tx.mjs "$(cast chain-id)" $ACC_PRIVKEY $FEE_CURRENCY)
fee_currency=$(deploy_fee_currency $1 $2 $3)
cip_64_tx $fee_currency
76 changes: 76 additions & 0 deletions e2e_test/debug-fee-currency/lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash
#shellcheck disable=SC2034,SC2155,SC2086
set -xeo pipefail

# args:
# $1: failOnDebit (bool):
# if true, this will make the DebugFeeCurrenc.DebitFees() call fail with a revert
# $2: failOnCredit (bool)
# if true, this will make the DebugFeeCurrenc.CreditFees() call fail with a revert
# $3: highGasOnCredit (bool)
# if true, this will make the DebugFeeCurrenc.CreditFees() call use
# a high amount of gas
# returns:
# deployed fee-currency address
function deploy_fee_currency() {
(
local fee_currency=$(
forge create --root "$SCRIPT_DIR/debug-fee-currency" --contracts "$SCRIPT_DIR/debug-fee-currency" --private-key $ACC_PRIVKEY DebugFeeCurrency.sol:DebugFeeCurrency --constructor-args '100000000000000000000000000' $1 $2 $3 --json | jq .deployedTo -r
)
if [ -z "${fee_currency}" ]; then
exit 1
fi
# this always resets the token address for the predeployed oracle3
cast send --private-key $ACC_PRIVKEY $ORACLE3 'setExchangeRate(address, uint256, uint256)' $fee_currency 2ether 1ether &>/dev/null
cast send --private-key $ACC_PRIVKEY $FEE_CURRENCY_DIRECTORY_ADDR 'setCurrencyConfig(address, address, uint256)' $fee_currency $ORACLE3 60000 &>/dev/null
echo "$fee_currency"
)
}

# args:
# $1: feeCurrency (address):
# deployed fee-currency address to be cleaned up
function cleanup_fee_currency() {
(
local fee_currency=$1
# HACK: this uses a static index 2, which relies on the fact that all non-predeployed currencies will be always cleaned up
# from the directory and the list never has more than 3 elements. Once there is the need for more dynamic removal we
# can parse the following call and find the index ourselves:
# local currencies=$(cast call "$FEE_CURRENCY_DIRECTORY_ADDR" 'getCurrencies() (address[] memory)')
cast send --private-key $ACC_PRIVKEY $FEE_CURRENCY_DIRECTORY_ADDR 'removeCurrencies(address, uint256)' $fee_currency 2 --json | jq 'if .status == "0x1" then 0 else 1 end' -r
)
}

# args:
# $1: feeCurrencyAddress (string):
# which fee-currency address to use for the default CIP-64 transaction
# $2: waitBlocks (num):
# how many blocks to wait until the lack of a receipt is considered a failure
# $3: replaceTransaction (bool):
# 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
}

# use this function to assert the cip_64_tx return value, by using a pipe like
# `cip_64_tx "$fee-currency" | assert_cip_64_tx true`
#
# args:
# $1: success (string):
# expected success value, "true" for when the cip-64 tx should have succeeded, "false" if not
# $2: error-regex (string):
# expected RPC return-error value regex to grep for, use "null", "" or unset value if no error is assumed.
function assert_cip_64_tx() {
local value
read -r value
local expected_error="$2"

if [ "$(echo "$value" | jq .success)" != "$1" ]; then
exit 1
fi
if [ -z "$expected_error" ]; then
expected_error="null"
fi
echo "$value" | jq .error | grep -qE "$expected_error"
}
154 changes: 123 additions & 31 deletions e2e_test/js-tests/send_tx.mjs
Original file line number Diff line number Diff line change
@@ -1,44 +1,136 @@
#!/usr/bin/env node
import {
createPublicClient,
createWalletClient,
http,
defineChain,
createWalletClient,
createPublicClient,
http,
defineChain,
TransactionReceiptNotFoundError,
} from "viem";
import { celoAlfajores } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

const [chainId, privateKey, feeCurrency] = process.argv.slice(2);
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"],
},
},
...celoAlfajores,
id: parseInt(chainId, 10),
name: "local dev chain",
network: "dev",
rpcUrls: {
default: {
http: ["http://127.0.0.1:8545"],
},
},
});

const account = privateKeyToAccount(privateKey);
const walletClient = createWalletClient({
account,
chain: devChain,
transport: http(),
});

const request = await walletClient.prepareTransactionRequest({
account,
to: "0x00000000000000000000000000000000DeaDBeef",
value: 2,
gas: 90000,
feeCurrency,
maxFeePerGas: 2000000000n,
maxPriorityFeePerGas: 0n,
const publicClient = createPublicClient({
account,
chain: devChain,
transport: http(),
});
const signature = await walletClient.signTransaction(request);
const hash = await walletClient.sendRawTransaction({
serializedTransaction: signature,
const walletClient = createWalletClient({
account,
chain: devChain,
transport: http(),
});
console.log(hash);
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function waitUntilBlock(blocknum) {
var next = await publicClient.getBlockNumber({ cacheTime: 0 });
while (next < blocknum) {
await sleep(500);
next = await publicClient.getBlockNumber({ cacheTime: 0 });
}
}

async function getTransactionReceipt(hash) {
try {
return await publicClient.getTransactionReceipt({ hash: hash });
} catch (e) {
if (e instanceof TransactionReceiptNotFoundError) {
return undefined;
}
throw e;
}
}

async function replaceTransaction(tx) {
const request = await walletClient.prepareTransactionRequest({
account: tx.account,
to: account.address,
value: 0n,
gas: 21000,
nonce: tx.nonce,
maxFeePerGas: tx.maxFeePerGas,
maxPriorityFeePerGas: tx.maxPriorityFeePerGas + 1000n,
});
const hash = await walletClient.sendRawTransaction({
serializedTransaction: await walletClient.signTransaction(request),
});
const receipt = await publicClient.waitForTransactionReceipt({
hash: hash,
confirmations: 1,
});
return receipt;
}

async function main() {
const request = await walletClient.prepareTransactionRequest({
account,
to: "0x00000000000000000000000000000000DeaDBeef",
value: 2n,
gas: 90000,
feeCurrency,
maxFeePerGas: 2000000000n,
maxPriorityFeePerGas: 0n,
});

var hash;

var blocknum = await publicClient.getBlockNumber({ cacheTime: 0 });
var replaced = false;
try {
hash = await walletClient.sendRawTransaction({
serializedTransaction: await walletClient.signTransaction(request),
});
} catch (e) {
// direct revert
console.log(
JSON.stringify({
success: false,
replaced: replaced,
error: e,
}),
);
return;
}

var success = true;
var waitBlocksForReceipt = parseInt(waitBlocks);
var receipt = await getTransactionReceipt(hash);
while (waitBlocksForReceipt > 0) {
await waitUntilBlock(blocknum + BigInt(1));
waitBlocksForReceipt--;
var receipt = await getTransactionReceipt(hash);
}
if (!receipt) {
if (replaceTxAfterWait == "true") {
receipt = await replaceTransaction(request);
}
success = false;
}
// print for bash script wrapper return value
console.log(
JSON.stringify({
success: success,
replaced: replaced,
error: null,
}),
);

return receipt;
}
await main();
2 changes: 1 addition & 1 deletion e2e_test/js-tests/test_viem_tx.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ describe("viem send tx", () => {
nativeCurrency,
false,
);
}).timeout(10_000);
}).timeout(20_000);

it("send tx with unregistered fee currency", async () => {
const request = await walletClient.prepareTransactionRequest({
Expand Down
41 changes: 15 additions & 26 deletions e2e_test/run_all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
set -eo pipefail

SCRIPT_DIR=$(readlink -f "$(dirname "$0")")
source "$SCRIPT_DIR/shared.sh"

TEST_GLOB=$1

## Start geth
cd "$SCRIPT_DIR/.." || exit 1
make geth
trap 'kill %%' EXIT # kill bg job at exit
build/bin/geth --dev --http --http.api eth,web3,net &> "$SCRIPT_DIR/geth.log" &
trap 'kill %%' EXIT # kill bg job at exit
build/bin/geth --dev --http --http.api eth,web3,net &>"$SCRIPT_DIR/geth.log" &

# Wait for geth to be ready
for _ in {1..10}
do
if cast block &> /dev/null
then
for _ in {1..10}; do
if cast block &>/dev/null; then
break
fi
sleep 0.2
Expand All @@ -27,38 +27,27 @@ cd "$SCRIPT_DIR" || exit 1
# There's a problem with geth return errors on the first transaction sent.
# See https://github.com/ethereum/web3.py/issues/3212
# To work around this, send a transaction before running tests
source ./shared.sh
cast send --json --private-key $ACC_PRIVKEY $TOKEN_ADDR 'transfer(address to, uint256 value) returns (bool)' 0x000000000000000000000000000000000000dEaD 100 --async
cast send --async --json --private-key "$ACC_PRIVKEY" "$TOKEN_ADDR" 'transfer(address to, uint256 value) returns (bool)' 0x000000000000000000000000000000000000dEaD 100

failures=0
tests=0
for f in test_*"$TEST_GLOB"*
do
# temporarily skip fee-currency related tests
if (echo "$f" | grep -q -e fee_currency )
then
for f in test_*"$TEST_GLOB"*; do
echo -e "\nRun $f"
if "./$f"; then
tput setaf 2 || true
echo "SKIP $f"
echo "PASS $f"
else
echo -e "\nRun $f"
if "./$f"
then
tput setaf 2 || true
echo "PASS $f"
else
tput setaf 1 || true
echo "FAIL $f ❌"
((failures++)) || true
fi
tput setaf 1 || true
echo "FAIL $f ❌"
((failures++)) || true
fi
tput sgr0 || true
((tests++)) || true
done

## Final summary
echo
if [[ $failures -eq 0 ]]
then
if [[ $failures -eq 0 ]]; then
tput setaf 2 || true
echo All $tests tests succeeded!
else
Expand Down
9 changes: 7 additions & 2 deletions e2e_test/shared.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/bin/bash
#shellcheck disable=SC2034 # unused vars make sense in a shared file

SCRIPT_DIR=$(readlink -f "$(dirname "$0")")
export SCRIPT_DIR
karlb marked this conversation as resolved.
Show resolved Hide resolved
export ETH_RPC_URL=http://127.0.0.1:8545

export ACC_ADDR=0x42cf1bbc38BaAA3c4898ce8790e21eD2738c6A4a
Expand All @@ -15,6 +17,9 @@ export ORACLE3=0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb0003
export FIXIDITY_1=1000000000000000000000000
export ZERO_ADDRESS=0x0000000000000000000000000000000000000000

prepare_node () {
(cd js-tests || exit 1; [[ -d node_modules ]] || npm install)
prepare_node() {
(
cd js-tests || exit 1
[[ -d node_modules ]] || npm install
)
}
5 changes: 4 additions & 1 deletion e2e_test/test_base_fee_recipient.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ base_fee=$(cast base-fee $block_number)
expected_balance_change=$((base_fee * gas_used))
balance_after=$(cast balance $FEE_HANDLER)
echo "Balance change: $balance_before -> $balance_after"
[[ $((balance_before + expected_balance_change)) -eq $balance_after ]] || (echo "Balance did not change as expected"; exit 1)
[[ $((balance_before + expected_balance_change)) -eq $balance_after ]] || (
echo "Balance did not change as expected"
exit 1
)
Loading