diff --git a/scripts/earthly-ci b/scripts/earthly-ci index 8d667fddc5d4..789b5e52e5a9 100755 --- a/scripts/earthly-ci +++ b/scripts/earthly-ci @@ -23,13 +23,15 @@ export FORCE_COLOR=1 export EARTHLY_CONFIG=$(git rev-parse --show-toplevel)/.github/earthly-ci-config.yml function wipe_non_cache_docker_state { - echo "Detected corrupted docker images. Wiping and trying again." - # Based on https://stackoverflow.com/a/75849307 - # wipe everything but volumes where we have earthly cache - sudo service docker stop - sudo bash -c 'rm -rf /var/lib/docker/{buildkit,containers,image,network,overlay2,plugins.runtimes,swarm,tmp,trust}/*' || true - # restart docker - might take down builds, but we need to recover anyway - sudo service docker restart + flock -n "$HOME/wipe_docker_state.lock" bash -c ' + echo "Detected corrupted docker images. Wiping and trying again." + # Based on https://stackoverflow.com/a/75849307 + # wipe everything but volumes where we have earthly cache + sudo service docker stop + sudo bash -c '"'"'rm -rf /var/lib/docker/{buildkit,containers,image,network,overlay2,plugins,runtimes,swarm,tmp,trust}/*'"'"' || true + # restart docker - might take down builds, but we need to recover anyway + sudo service docker restart + ' } EARTHLY_RUN_STATS_JSON="earthly-run-stats.json" @@ -108,10 +110,12 @@ while [ $ATTEMPT_COUNT -lt $MAX_ATTEMPTS ]; do fi sleep 20 elif grep 'status 125: docker: Error response from daemon: layer does not exist.' $OUTPUT_FILE >/dev/null \ + || grep 'could not start container "earthly-buildkitd"' $OUTPUT_FILE >/dev/null \ || grep 'could not determine buildkit address - is Docker or Podman running?' $OUTPUT_FILE >/dev/null \ || grep 'please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host' $OUTPUT_FILE >/dev/null \ || grep 'docker: failed to register layer' $OUTPUT_FILE >/dev/null \ || grep 'docker: error during connect:' $OUTPUT_FILE >/dev/null \ + || grep 'docker: failed to write digest data' >/dev/null \ || grep 'docker: unexpected EOF' $OUTPUT_FILE >/dev/null ; then wipe_non_cache_docker_state # wait for other docker restarts diff --git a/scripts/run_interleaved.sh b/scripts/run_interleaved.sh index 854c80e4bd90..8a52bc840910 100755 --- a/scripts/run_interleaved.sh +++ b/scripts/run_interleaved.sh @@ -27,19 +27,18 @@ colors=( "\e[91m" # Bright Red ) +FINISHED=false main_cmd="$1" shift -# pattern from https://stackoverflow.com/questions/28238952/how-to-kill-a-running-bash-function-from-terminal -function cleanup_function() { - kill $(jobs -p) 2>/dev/null || true - return +function cleanup() { + # kill everything in our process group except our process + trap - SIGTERM && kill $(pgrep -g $$ | grep -v $$) 2>/dev/null || true } +trap cleanup SIGINT SIGTERM EXIT # Function to run a command and prefix the output with color function run_command() { - # pattern from https://stackoverflow.com/questions/28238952/how-to-kill-a-running-bash-function-from-terminal - trap cleanup_function INT EXIT local cmd="$1" local color="$2" $cmd 2>&1 | while IFS= read -r line; do @@ -50,9 +49,10 @@ function run_command() { # Run background commands without logging output i=0 for cmd in "$@"; do - run_command "$cmd" "${colors[$((i % ${#colors[@]}))]}" & + (run_command "$cmd" "${colors[$((i % ${#colors[@]}))]}" || [ $FINISHED = true ] || (echo "$cmd causing terminate" && kill 0) ) & ((i++)) || true # annoyingly considered a failure based on result done # Run the main command synchronously, piping output through the run_command function with green color -run_command "$main_cmd" "\e[32m" \ No newline at end of file +run_command "$main_cmd" "\e[32m" || (echo "$main_cmd causing terminate" && kill 0) +FINISHED=true \ No newline at end of file diff --git a/scripts/run_native_testnet.sh b/scripts/run_native_testnet.sh index be9902b65734..c4be98de940d 100755 --- a/scripts/run_native_testnet.sh +++ b/scripts/run_native_testnet.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -eu + : ' This script sets up and runs a native testnet for the Aztec network. @@ -24,28 +26,29 @@ Options: see display_help() below ' +# Default values +TEST_SCRIPT=./test-transfer.sh +PROVER_SCRIPT="\"./prover-node.sh 8078 false\"" +NUM_VALIDATORS=3 +INTERLEAVED=false + # Function to display help message display_help() { echo "Usage: $0 [options]" echo echo "Options:" echo " -h Display this help message" - echo " -t Specify the test script file (default: ./test-transfer.sh)" - echo " -val Specify the number of validators (default: 3)" + echo " -t Specify the test file (default: $TEST_FILE)" + echo " -p Specify the prover command (default: $PROVER_SCRIPT)" + echo " -val Specify the number of validators (default: $NUM_VALIDATORS)" echo " -v Set logging level to verbose" echo " -vv Set logging level to debug" - echo " -i Run interleaved (default: false)" + echo " -i Run interleaved (default: $INTERLEAVED)" echo echo "Example:" - echo " $0 -t ./custom-test.sh -val 5 -v" + echo " $0 -t ./test-4epochs.sh -val 5 -v" } -# Default values -TEST_SCRIPT="./test-transfer.sh" -NUM_VALIDATORS=3 -LOG_LEVEL="info" -INTERLEAVED=false - # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in @@ -57,6 +60,10 @@ while [[ $# -gt 0 ]]; do TEST_SCRIPT="$2" shift 2 ;; + -p) + PROVER_SCRIPT="$2" + shift 2 + ;; -val) NUM_VALIDATORS="$2" shift 2 @@ -88,6 +95,9 @@ done ## Set log level for all child commands export LOG_LEVEL +# Go to repo root +cd $(git rev-parse --show-toplevel) + # Base command BASE_CMD="INTERLEAVED=$INTERLEAVED ./yarn-project/end-to-end/scripts/native_network_test.sh \ $TEST_SCRIPT \ @@ -95,10 +105,10 @@ BASE_CMD="INTERLEAVED=$INTERLEAVED ./yarn-project/end-to-end/scripts/native_netw ./deploy-l2-contracts.sh \ ./boot-node.sh \ ./ethereum.sh \ - \"./prover-node.sh 8078 false\" \ + \"./validators.sh $NUM_VALIDATORS\" \ + $PROVER_SCRIPT \ ./pxe.sh \ - ./transaction-bot.sh \ - \"./validators.sh $NUM_VALIDATORS\"" + ./transaction-bot.sh" # Execute the command eval $BASE_CMD diff --git a/yarn-project/canary/scripts/cond_run_script b/yarn-project/canary/scripts/cond_run_script deleted file mode 100755 index 84c03bd4574a..000000000000 --- a/yarn-project/canary/scripts/cond_run_script +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# Conditionally runs a script if any dependent code has changed between -# the last successful run and the present commit. -# -# It's expected to be run from the project directory, and that there be a directory called `scripts` -# containing the given named script to execute. -# -# This script is only useful if there is nothing to do in the event there is no rebuild. This is fine -# for running a suite of tests for example, but is not useful for performing a build, as even if a -# build has nothing to do, the previous images are retagged with the new commit hash for upstream jobs. -# -# Arguments are: -# 1. REPOSITORY: The project repository name in ECR. Used to determine if there are changes since last success. -# 2. SUCCESS_TAG: To track if this job needs to be run, the repository image is tagged with a success tag after a -# successful run. The script will only run if there were relevant code changes since the last successful commit. -# 3... ARGS: Script to run and args. -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -REPOSITORY=$1 -shift -SUCCESS_TAG=$1 -shift -SCRIPT_TO_RUN=$1 -shift - -CONTENT_HASH=$(calculate_content_hash $REPOSITORY) -echo "Content hash tag: cache-$CONTENT_HASH-$SUCCESS_TAG" -echo "Script to run is $SCRIPT_TO_RUN $@" - -if ! check_rebuild cache-$CONTENT_HASH-$SUCCESS_TAG $REPOSITORY; then - "$SCRIPT_TO_RUN" "$@" - retry tag_remote_image $REPOSITORY cache-$CONTENT_HASH cache-$CONTENT_HASH-$SUCCESS_TAG -fi diff --git a/yarn-project/end-to-end/scripts/native-network/pxe.sh b/yarn-project/end-to-end/scripts/native-network/pxe.sh index e1ec0eab112e..e02133cf9433 100755 --- a/yarn-project/end-to-end/scripts/native-network/pxe.sh +++ b/yarn-project/end-to-end/scripts/native-network/pxe.sh @@ -18,8 +18,6 @@ echo "Waiting for Aztec Node..." until curl -s http://127.0.0.1:8080/status >/dev/null ; do sleep 1 done -echo "Done waiting." - # We need to also wait for the validator, as the initial node cannot # Produce blocks on it's own echo "Waiting for Validator 0..." diff --git a/yarn-project/end-to-end/scripts/native-network/test.sh b/yarn-project/end-to-end/scripts/native-network/test-4epochs.sh similarity index 93% rename from yarn-project/end-to-end/scripts/native-network/test.sh rename to yarn-project/end-to-end/scripts/native-network/test-4epochs.sh index ac034cfe99ed..98393c402139 100755 --- a/yarn-project/end-to-end/scripts/native-network/test.sh +++ b/yarn-project/end-to-end/scripts/native-network/test-4epochs.sh @@ -2,7 +2,6 @@ set -eu -TEST=$1 # Get the name of the script without the path and extension SCRIPT_NAME=$(basename "$0" .sh) @@ -31,6 +30,6 @@ echo "Done waiting." export DEBUG="aztec:*" export LOG_LEVEL=${LOG_LEVEL:-"debug"} export PXE_URL=http://localhost:8079 -export ETHEREUM_HOST=http://localhost:8545 +export ETHEREUM_HOST=http://127.0.0.1:8545 cd $(git rev-parse --show-toplevel)/yarn-project/end-to-end -yarn test "$TEST" +yarn test src/spartan/4epochs.test.ts \ No newline at end of file diff --git a/yarn-project/end-to-end/scripts/network_test.sh b/yarn-project/end-to-end/scripts/network_test.sh index 0b0bf8165622..f85a22cded25 100755 --- a/yarn-project/end-to-end/scripts/network_test.sh +++ b/yarn-project/end-to-end/scripts/network_test.sh @@ -62,8 +62,13 @@ function show_status_until_pxe_ready() { } show_status_until_pxe_ready & -SHOW_STATUS_PID=$! +function cleanup() { + # kill everything in our process group except our process + kill $(pgrep -g $$ | grep -v $$) || true + kill $(jobs -p) || true +} +trap cleanup SIGINT SIGTERM EXIT # Install the Helm chart helm upgrade --install spartan "$REPO/spartan/aztec-network/" \ --namespace "$NAMESPACE" \ @@ -79,15 +84,6 @@ kubectl wait pod -l app==pxe --for=condition=Ready -n "$NAMESPACE" --timeout=10m # tunnel in to get access directly to our PXE service in k8s (kubectl port-forward --namespace $NAMESPACE svc/spartan-aztec-network-pxe 9082:8080 2>/dev/null >/dev/null || true) & -PORT_FORWARD_PID=$! - -cleanup() { - echo "Cleaning up..." - kill $PORT_FORWARD_PID || true - kill $SHOW_STATUS_PID || true -} - -trap cleanup EXIT SIGINT SIGTERM docker run --rm --network=host \ -e PXE_URL=http://localhost:9082 \ diff --git a/yarn-project/end-to-end/src/spartan/4epochs.test.ts b/yarn-project/end-to-end/src/spartan/4epochs.test.ts new file mode 100644 index 000000000000..c58d31211112 --- /dev/null +++ b/yarn-project/end-to-end/src/spartan/4epochs.test.ts @@ -0,0 +1,90 @@ +import { EthCheatCodes, readFieldCompressedString } from '@aztec/aztec.js'; +import { AZTEC_SLOT_DURATION } from '@aztec/circuits.js'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { TokenContract } from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { RollupCheatCodes } from '../../../aztec.js/src/utils/cheat_codes.js'; +import { type TestWallets, setupTestWalletsWithTokens } from './setup_test_wallets.js'; + +const { PXE_URL, ETHEREUM_HOST } = process.env; +if (!PXE_URL) { + throw new Error('PXE_URL env variable must be set'); +} +if (!ETHEREUM_HOST) { + throw new Error('ETHEREUM_HOST env variable must be set'); +} + +describe('token transfer test', () => { + jest.setTimeout(10 * 60 * 2000); // 20 minutes + + const logger = createDebugLogger(`aztec:spartan:4epochs`); + // We want plenty of minted tokens for a lot of slots that fill up multiple epochs + const MINT_AMOUNT = 2000000n; + const TEST_EPOCHS = 4; + const ROUNDS = BigInt(AZTEC_SLOT_DURATION * TEST_EPOCHS); + + let testWallets: TestWallets; + + beforeAll(async () => { + testWallets = await setupTestWalletsWithTokens(PXE_URL, MINT_AMOUNT, logger); + expect(ROUNDS).toBeLessThanOrEqual(MINT_AMOUNT); + }); + + it('can get info', async () => { + const name = readFieldCompressedString(await testWallets.tokenAdminWallet.methods.private_get_name().simulate()); + expect(name).toBe(testWallets.tokenName); + }); + + it('transfer tokens for 4 epochs', async () => { + const ethCheatCodes = new EthCheatCodes(ETHEREUM_HOST); + // Get 4 epochs + const rollupCheatCodes = new RollupCheatCodes( + ethCheatCodes, + await testWallets.pxe.getNodeInfo().then(n => n.l1ContractAddresses), + ); + const recipient = testWallets.recipientWallet.getAddress(); + const transferAmount = 1n; + + testWallets.wallets.forEach(async w => { + expect(MINT_AMOUNT).toBe(await testWallets.tokenAdminWallet.methods.balance_of_public(w.getAddress()).simulate()); + }); + + expect(0n).toBe(await testWallets.tokenAdminWallet.methods.balance_of_public(recipient).simulate()); + + // For each round, make both private and public transfers + const startSlot = await rollupCheatCodes.getSlot(); + for (let i = 1n; i <= ROUNDS; i++) { + const interactions = await Promise.all([ + ...testWallets.wallets.map(async w => + ( + await TokenContract.at(testWallets.tokenAddress, w) + ).methods.transfer_public(w.getAddress(), recipient, transferAmount, 0), + ), + ]); + + const txs = await Promise.all(interactions.map(async i => await i.prove())); + + await Promise.all(txs.map(t => t.send().wait({ timeout: 600 }))); + const currentSlot = await rollupCheatCodes.getSlot(); + expect(currentSlot).toBe(startSlot + i); + const startEpoch = await rollupCheatCodes.getEpoch(); + logger.debug( + `Successfully reached slot ${currentSlot} (iteration ${ + currentSlot - startSlot + }/${ROUNDS}) (Epoch ${startEpoch})`, + ); + } + + testWallets.wallets.forEach(async w => { + expect(MINT_AMOUNT - ROUNDS * transferAmount).toBe( + await testWallets.tokenAdminWallet.methods.balance_of_public(w.getAddress()).simulate(), + ); + }); + + expect(ROUNDS * transferAmount * BigInt(testWallets.wallets.length)).toBe( + await testWallets.tokenAdminWallet.methods.balance_of_public(recipient).simulate(), + ); + }); +}); diff --git a/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts b/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts new file mode 100644 index 000000000000..99121d5f664e --- /dev/null +++ b/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts @@ -0,0 +1,78 @@ +import { getSchnorrAccount } from '@aztec/accounts/schnorr'; +import { type AccountWalletWithSecretKey, type AztecAddress, type PXE, createCompatibleClient } from '@aztec/aztec.js'; +import { type Logger } from '@aztec/foundation/log'; +import { TokenContract } from '@aztec/noir-contracts.js'; + +import { addAccounts } from '../fixtures/snapshot_manager.js'; + +export interface TestWallets { + pxe: PXE; + wallets: AccountWalletWithSecretKey[]; + tokenAdminWallet: TokenContract; + tokenName: string; + recipientWallet: AccountWalletWithSecretKey; + tokenAddress: AztecAddress; +} + +export async function setupTestWalletsWithTokens( + pxeUrl: string, + mintAmount: bigint, + logger: Logger, +): Promise { + const TOKEN_NAME = 'USDC'; + const TOKEN_SYMBOL = 'USD'; + const TOKEN_DECIMALS = 18n; + + const WALLET_COUNT = 1; // TODO fix this to allow for 16 wallets again + + let recipientWallet: AccountWalletWithSecretKey; + + const pxe = await createCompatibleClient(pxeUrl, logger); + + { + const { accountKeys } = await addAccounts(1, logger, false)({ pxe }); + const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); + + const partialAddress = accountManagers[0].getCompleteAddress().partialAddress; + await pxe.registerAccount(accountKeys[0][0], partialAddress); + recipientWallet = await accountManagers[0].getWallet(); + logger.verbose(`Recipient Wallet address: ${recipientWallet.getAddress()} registered`); + } + + const { accountKeys } = await addAccounts(WALLET_COUNT, logger, false)({ pxe }); + const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); + + const wallets = await Promise.all( + accountManagers.map(async (a, i) => { + const partialAddress = a.getCompleteAddress().partialAddress; + await pxe.registerAccount(accountKeys[i][0], partialAddress); + const wallet = await a.getWallet(); + logger.verbose(`Wallet ${i} address: ${wallet.getAddress()} registered`); + return wallet; + }), + ); + + logger.verbose(`Deploying TokenContract...`); + const tokenContract = await TokenContract.deploy( + wallets[0], + wallets[0].getAddress(), + TOKEN_NAME, + TOKEN_SYMBOL, + TOKEN_DECIMALS, + ) + .send() + .deployed({ timeout: 600 }); + + const tokenAddress = tokenContract.address; + const tokenAdminWallet = await TokenContract.at(tokenAddress, wallets[0]); + + logger.verbose(`Minting ${mintAmount} public assets to the ${wallets.length} wallets...`); + + await Promise.all( + wallets.map(w => tokenAdminWallet.methods.mint_public(w.getAddress(), mintAmount).send().wait({ timeout: 600 })), + ); + + logger.verbose(`Minting complete.`); + + return { pxe, wallets, tokenAdminWallet, tokenName: TOKEN_NAME, tokenAddress, recipientWallet }; +} diff --git a/yarn-project/end-to-end/src/spartan/transfer.test.ts b/yarn-project/end-to-end/src/spartan/transfer.test.ts index 066dfb355bae..ebbc84b70699 100644 --- a/yarn-project/end-to-end/src/spartan/transfer.test.ts +++ b/yarn-project/end-to-end/src/spartan/transfer.test.ts @@ -1,17 +1,10 @@ -import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { - type AccountWalletWithSecretKey, - type AztecAddress, - type PXE, - createCompatibleClient, - readFieldCompressedString, -} from '@aztec/aztec.js'; +import { readFieldCompressedString } from '@aztec/aztec.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { TokenContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; -import { addAccounts } from '../fixtures/snapshot_manager.js'; +import { type TestWallets, setupTestWalletsWithTokens } from './setup_test_wallets.js'; const { PXE_URL } = process.env; if (!PXE_URL) { @@ -22,92 +15,38 @@ describe('token transfer test', () => { jest.setTimeout(10 * 60 * 2000); // 20 minutes const logger = createDebugLogger(`aztec:spartan-test:transfer`); - const TOKEN_NAME = 'USDC'; - const TOKEN_SYMBOL = 'USD'; - const TOKEN_DECIMALS = 18n; const MINT_AMOUNT = 20n; - const WALLET_COUNT = 1; // TODO fix this to allow for 16 wallets again const ROUNDS = 5n; - let pxe: PXE; - let wallets: AccountWalletWithSecretKey[]; - let recipientWallet: AccountWalletWithSecretKey; - let tokenAddress: AztecAddress; - let tokenAdminWallet: TokenContract; + let testWallets: TestWallets; beforeAll(async () => { + testWallets = await setupTestWalletsWithTokens(PXE_URL, MINT_AMOUNT, logger); expect(ROUNDS).toBeLessThanOrEqual(MINT_AMOUNT); - - pxe = await createCompatibleClient(PXE_URL, logger); - - { - const { accountKeys } = await addAccounts(1, logger, false)({ pxe }); - const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); - - const partialAddress = accountManagers[0].getCompleteAddress().partialAddress; - await pxe.registerAccount(accountKeys[0][0], partialAddress); - recipientWallet = await accountManagers[0].getWallet(); - logger.verbose(`Recipient Wallet address: ${recipientWallet.getAddress()} registered`); - } - - const { accountKeys } = await addAccounts(WALLET_COUNT, logger, false)({ pxe }); - const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); - - wallets = await Promise.all( - accountManagers.map(async (a, i) => { - const partialAddress = a.getCompleteAddress().partialAddress; - await pxe.registerAccount(accountKeys[i][0], partialAddress); - const wallet = await a.getWallet(); - logger.verbose(`Wallet ${i} address: ${wallet.getAddress()} registered`); - return wallet; - }), - ); - - logger.verbose(`Deploying TokenContract...`); - const tokenContract = await TokenContract.deploy( - wallets[0], - wallets[0].getAddress(), - TOKEN_NAME, - TOKEN_SYMBOL, - TOKEN_DECIMALS, - ) - .send() - .deployed({ timeout: 600 }); - - tokenAddress = tokenContract.address; - tokenAdminWallet = await TokenContract.at(tokenAddress, wallets[0]); - - logger.verbose(`Minting ${MINT_AMOUNT} public assets to the ${wallets.length} wallets...`); - - await Promise.all( - wallets.map(w => tokenAdminWallet.methods.mint_public(w.getAddress(), MINT_AMOUNT).send().wait({ timeout: 600 })), - ); - - logger.verbose(`Minting complete.`); }); it('can get info', async () => { - const name = readFieldCompressedString(await tokenAdminWallet.methods.private_get_name().simulate()); - expect(name).toBe(TOKEN_NAME); + const name = readFieldCompressedString(await testWallets.tokenAdminWallet.methods.private_get_name().simulate()); + expect(name).toBe(testWallets.tokenName); }); it('can transfer 1 token privately and publicly', async () => { - const recipient = recipientWallet.getAddress(); + const recipient = testWallets.recipientWallet.getAddress(); const transferAmount = 1n; - wallets.forEach(async w => { - expect(MINT_AMOUNT).toBe(await tokenAdminWallet.methods.balance_of_public(w.getAddress()).simulate()); + testWallets.wallets.forEach(async w => { + expect(MINT_AMOUNT).toBe(await testWallets.tokenAdminWallet.methods.balance_of_public(w.getAddress()).simulate()); }); - expect(0n).toBe(await tokenAdminWallet.methods.balance_of_public(recipient).simulate()); + expect(0n).toBe(await testWallets.tokenAdminWallet.methods.balance_of_public(recipient).simulate()); // For each round, make both private and public transfers for (let i = 1n; i <= ROUNDS; i++) { const interactions = await Promise.all([ - ...wallets.map(async w => + ...testWallets.wallets.map(async w => ( - await TokenContract.at(tokenAddress, w) + await TokenContract.at(testWallets.tokenAddress, w) ).methods.transfer_public(w.getAddress(), recipient, transferAmount, 0), ), ]); @@ -117,14 +56,14 @@ describe('token transfer test', () => { await Promise.all(txs.map(t => t.send().wait({ timeout: 600 }))); } - wallets.forEach(async w => { + testWallets.wallets.forEach(async w => { expect(MINT_AMOUNT - ROUNDS * transferAmount).toBe( - await tokenAdminWallet.methods.balance_of_public(w.getAddress()).simulate(), + await testWallets.tokenAdminWallet.methods.balance_of_public(w.getAddress()).simulate(), ); }); - expect(ROUNDS * transferAmount * BigInt(wallets.length)).toBe( - await tokenAdminWallet.methods.balance_of_public(recipient).simulate(), + expect(ROUNDS * transferAmount * BigInt(testWallets.wallets.length)).toBe( + await testWallets.tokenAdminWallet.methods.balance_of_public(recipient).simulate(), ); }); });