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

feat(tests): Move all env calls to one place in ts-tests #1968

Merged
merged 5 commits into from
May 17, 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
26 changes: 17 additions & 9 deletions core/tests/ts-integration/scripts/compile-yul.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ export function spawn(command: string) {
});
}

export async function compile(path: string, files: string[], outputDirName: string | null, type: string) {
export async function compile(
pathToHome: string,
path: string,
files: string[],
outputDirName: string | null,
type: string
) {
if (!files.length) {
console.log(`No test files provided in folder ${path}.`);
return;
}
let paths = preparePaths(path, files, outputDirName);
let paths = preparePaths(pathToHome, path, files, outputDirName);

let systemMode = type === 'yul' ? '--system-mode --optimization 3' : '';

Expand All @@ -50,23 +56,23 @@ export async function compile(path: string, files: string[], outputDirName: stri
);
}

export async function compileFolder(path: string, type: string) {
export async function compileFolder(pathToHome: string, path: string, type: string) {
let files: string[] = (await fs.promises.readdir(path)).filter((fn) => fn.endsWith(`.${type}`));
for (const file of files) {
await compile(path, [file], `${file}`, type);
await compile(pathToHome, path, [file], `${file}`, type);
}
}

function preparePaths(path: string, files: string[], outputDirName: string | null): CompilerPaths {
function preparePaths(pathToHome: string, path: string, files: string[], outputDirName: string | null): CompilerPaths {
const filePaths = files
.map((val, _) => {
return `sources/${val}`;
})
.join(' ');
const outputDir = outputDirName || files[0];
let absolutePathSources = `${process.env.ZKSYNC_HOME}/core/tests/ts-integration/${path}`;
let absolutePathSources = `${pathToHome}/core/tests/ts-integration/${path}`;

let absolutePathArtifacts = `${process.env.ZKSYNC_HOME}/core/tests/ts-integration/${path}/artifacts`;
let absolutePathArtifacts = `${pathToHome}/core/tests/ts-integration/${path}/artifacts`;

return new CompilerPaths(filePaths, outputDir, absolutePathSources, absolutePathArtifacts);
}
Expand All @@ -76,6 +82,7 @@ class CompilerPaths {
public outputDir: string;
public absolutePathSources: string;
public absolutePathArtifacts: string;

constructor(filePath: string, outputDir: string, absolutePathSources: string, absolutePathArtifacts: string) {
this.filePath = filePath;
this.outputDir = outputDir;
Expand All @@ -85,8 +92,9 @@ class CompilerPaths {
}

async function main() {
await compileFolder('contracts/yul', 'yul');
await compileFolder('contracts/zkasm', 'zkasm');
const pathToHome = path.join(__dirname, '../../../../');
await compileFolder(pathToHome, 'contracts/yul', 'yul');
await compileFolder(pathToHome, 'contracts/zkasm', 'zkasm');
}

main()
Expand Down
6 changes: 3 additions & 3 deletions core/tests/ts-integration/src/context-owner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export class TestContextOwner {
this.reporter.startAction(`Cancelling allowances transactions`);
// Since some tx may be pending on stage, we don't want to get stuck because of it.
// In order to not get stuck transactions, we manually cancel all the pending txs.
const chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!;
const chainId = this.env.l2ChainId;

const bridgehub = await this.mainSyncWallet.getBridgehubContract();
const erc20Bridge = await bridgehub.sharedBridge();
Expand Down Expand Up @@ -275,7 +275,7 @@ export class TestContextOwner {
) {
this.reporter.startAction(`Distributing base tokens on L1`);
if (baseTokenAddress != zksync.utils.ETH_ADDRESS_IN_CONTRACTS) {
const chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!;
const chainId = this.env.l2ChainId;
const l1startNonce = await this.mainEthersWallet.getTransactionCount();
this.reporter.debug(`Start nonce is ${l1startNonce}`);
const ethIsBaseToken =
Expand Down Expand Up @@ -365,7 +365,7 @@ export class TestContextOwner {
l2erc20DepositAmount: ethers.BigNumber,
baseTokenAddress: zksync.types.Address
) {
const chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!;
const chainId = this.env.l2ChainId;
this.reporter.startAction(`Distributing tokens on L1`);
const l1startNonce = await this.mainEthersWallet.getTransactionCount();
this.reporter.debug(`Start nonce is ${l1startNonce}`);
Expand Down
40 changes: 36 additions & 4 deletions core/tests/ts-integration/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as path from 'path';
import * as fs from 'fs';
import * as ethers from 'ethers';
import * as zksync from 'zksync-ethers';
import { TestEnvironment } from './types';
import { DataAvailabityMode, NodeMode, TestEnvironment } from './types';
import { Reporter } from './reporter';
import { L2_BASE_TOKEN_ADDRESS } from 'zksync-ethers/build/utils';

Expand Down Expand Up @@ -76,7 +76,8 @@ export async function loadTestEnvironment(): Promise<TestEnvironment> {
? process.env.CONTRACT_VERIFIER_URL!
: ensureVariable(process.env.CONTRACT_VERIFIER_URL, 'Contract verification API');

const tokens = getTokens(process.env.CHAIN_ETH_NETWORK || 'localhost');
const pathToHome = path.join(__dirname, '../../../../');
const tokens = getTokens(pathToHome, process.env.CHAIN_ETH_NETWORK || 'localhost');
// wBTC is chosen because it has decimals different from ETH (8 instead of 18).
// Using this token will help us to detect decimals-related errors.
// but if it's not available, we'll use the first token from the list.
Expand All @@ -103,8 +104,39 @@ export async function loadTestEnvironment(): Promise<TestEnvironment> {
).l2TokenAddress(weth.address);

const baseTokenAddressL2 = L2_BASE_TOKEN_ADDRESS;
const l2ChainId = parseInt(process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!);
const l1BatchCommitDataGeneratorMode = process.env
.CHAIN_STATE_KEEPER_L1_BATCH_COMMIT_DATA_GENERATOR_MODE! as DataAvailabityMode;
let minimalL2GasPrice;
if (process.env.CHAIN_STATE_KEEPER_MINIMAL_L2_GAS_PRICE !== undefined) {
minimalL2GasPrice = ethers.BigNumber.from(process.env.CHAIN_STATE_KEEPER_MINIMAL_L2_GAS_PRICE!);
} else {
minimalL2GasPrice = ethers.BigNumber.from(0);
}
let nodeMode;
if (process.env.EN_MAIN_NODE_URL !== undefined) {
nodeMode = NodeMode.External;
} else {
nodeMode = NodeMode.Main;
}

const validationComputationalGasLimit = parseInt(
process.env.CHAIN_STATE_KEEPER_VALIDATION_COMPUTATIONAL_GAS_LIMIT!
);
const priorityTxMaxGasLimit = parseInt(process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT!);
const maxLogsLimit = parseInt(
process.env.EN_REQ_ENTITIES_LIMIT ?? process.env.API_WEB3_JSON_RPC_REQ_ENTITIES_LIMIT!
);

return {
maxLogsLimit,
pathToHome,
priorityTxMaxGasLimit,
validationComputationalGasLimit,
nodeMode,
minimalL2GasPrice,
l1BatchCommitDataGeneratorMode,
l2ChainId,
network,
mainWalletPK,
l2NodeUrl,
Expand Down Expand Up @@ -152,8 +184,8 @@ type L1Token = {
address: string;
};

function getTokens(network: string): L1Token[] {
const configPath = `${process.env.ZKSYNC_HOME}/etc/tokens/${network}.json`;
function getTokens(pathToHome: string, network: string): L1Token[] {
const configPath = `${pathToHome}/etc/tokens/${network}.json`;
if (!fs.existsSync(configPath)) {
return [];
}
Expand Down
3 changes: 2 additions & 1 deletion core/tests/ts-integration/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function getTestContract(name: string): ZkSyncArtifact {
* @returns Conta
*/
export function getContractSource(relativePath: string): string {
const contractPath = `${process.env.ZKSYNC_HOME}/core/tests/ts-integration/contracts/${relativePath}`;
const contractPath = `${__dirname}/../contracts/${relativePath}`;
const source = fs.readFileSync(contractPath, 'utf8');
return source;
}
Expand Down Expand Up @@ -77,6 +77,7 @@ export async function waitForNewL1Batch(wallet: zksync.Wallet): Promise<zksync.t
}
return await wallet.provider.getTransactionReceipt(oldReceipt.transactionHash);
}

/**
* Waits until the requested block is finalized.
*
Expand Down
42 changes: 42 additions & 0 deletions core/tests/ts-integration/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { ethers } from 'ethers';

export enum NodeMode {
Main,
External
}

export enum DataAvailabityMode {
Rollup = 'Rollup',
Validium = 'Validium'
}

/**
* Description of an ERC20 token.
*/
Expand All @@ -15,6 +25,38 @@ export interface Token {
* Description of the environment the integration tests are being run in.
*/
export interface TestEnvironment {
/*
* Max Logs limit
*/
maxLogsLimit: number;
/*
* Gas limit for priority txs
*/
priorityTxMaxGasLimit: number;
/*
* Gas limit for computations
*/
validationComputationalGasLimit: number;
/*
* Minimal gas price of l2
*/
minimalL2GasPrice: ethers.BigNumber;
/*
* Data availability mode
*/
l1BatchCommitDataGeneratorMode: DataAvailabityMode;
/*
* Path to code home directory
*/
pathToHome: string;
/**
* Chain Id of the L2 Network
*/
l2ChainId: number;
/*
* Mode of the l2 node
*/
nodeMode: NodeMode;
/**
* Plaintext name of the L1 network name (i.e. `localhost` or `goerli`).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fetch from 'node-fetch';
import fs from 'fs';
import { deployContract, getContractSource, getTestContract } from '../../src/helpers';
import { sleep } from 'zksync-ethers/build/utils';
import { NodeMode } from '../../src/types';

// Regular expression to match ISO dates.
const DATE_REGEX = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{6})?/;
Expand Down Expand Up @@ -44,7 +45,7 @@ describe('Tests for the contract verification API', () => {
testMaster = TestMaster.getInstance(__filename);
alice = testMaster.mainAccount();

if (process.env.ZKSYNC_ENV!.startsWith('ext-node')) {
if (testMaster.environment().nodeMode == NodeMode.External) {
console.warn("You are trying to run contract verification tests on external node. It's not supported.");
}
});
Expand Down Expand Up @@ -72,7 +73,7 @@ describe('Tests for the contract verification API', () => {
let artifact = contracts.counter;
// TODO: use plugin compilation when it's ready instead of pre-compiled bytecode.
artifact.bytecode = fs.readFileSync(
`${process.env.ZKSYNC_HOME}/core/tests/ts-integration/contracts/counter/zkVM_bytecode.txt`,
`${testMaster.environment().pathToHome}/core/tests/ts-integration/contracts/counter/zkVM_bytecode.txt`,
'utf8'
);

Expand Down Expand Up @@ -136,10 +137,14 @@ describe('Tests for the contract verification API', () => {
});

test('should test yul contract verification', async () => {
const contractPath = `${process.env.ZKSYNC_HOME}/core/tests/ts-integration/contracts/yul/Empty.yul`;
const contractPath = `${
testMaster.environment().pathToHome
}/core/tests/ts-integration/contracts/yul/Empty.yul`;
const sourceCode = fs.readFileSync(contractPath, 'utf8');

const bytecodePath = `${process.env.ZKSYNC_HOME}/core/tests/ts-integration/contracts/yul/artifacts/Empty.yul/Empty.yul.zbin`;
const bytecodePath = `${
testMaster.environment().pathToHome
}/core/tests/ts-integration/contracts/yul/artifacts/Empty.yul/Empty.yul.zbin`;
const bytecode = fs.readFileSync(bytecodePath);

const contractFactory = new zksync.ContractFactory([], bytecode, alice);
Expand Down
4 changes: 3 additions & 1 deletion core/tests/ts-integration/tests/api/debug.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ describe('Debug methods', () => {
});

test('Should not fail for infinity recursion', async () => {
const bytecodePath = `${process.env.ZKSYNC_HOME}/core/tests/ts-integration/contracts/zkasm/artifacts/deep_stak.zkasm/deep_stak.zkasm.zbin`;
const bytecodePath = `${
testMaster.environment().pathToHome
}/core/tests/ts-integration/contracts/zkasm/artifacts/deep_stak.zkasm/deep_stak.zkasm.zbin`;
const bytecode = fs.readFileSync(bytecodePath);

const contractFactory = new zksync.ContractFactory([], bytecode, testMaster.mainAccount());
Expand Down
28 changes: 14 additions & 14 deletions core/tests/ts-integration/tests/api/web3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import * as zksync from 'zksync-ethers';
import { types } from 'zksync-ethers';
import { BigNumberish, ethers, Event } from 'ethers';
import { serialize } from '@ethersproject/transactions';
import { deployContract, getTestContract, waitForNewL1Batch, anyTransaction } from '../../src/helpers';
import { anyTransaction, deployContract, getTestContract, waitForNewL1Batch } from '../../src/helpers';
import { shouldOnlyTakeFee } from '../../src/modifiers/balance-checker';
import fetch, { RequestInit } from 'node-fetch';
import { EIP712_TX_TYPE, PRIORITY_OPERATION_L2_TX_TYPE } from 'zksync-ethers/build/utils';
import { NodeMode } from '../../src/types';

// Regular expression to match variable-length hex number.
const HEX_VALUE_REGEX = /^0x[\da-fA-F]*$/;
Expand All @@ -30,7 +31,7 @@ describe('web3 API compatibility tests', () => {
testMaster = TestMaster.getInstance(__filename);
alice = testMaster.mainAccount();
l2Token = testMaster.environment().erc20Token.l2Address;
chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!;
chainId = testMaster.environment().l2ChainId;
});

test('Should test block/transaction web3 methods', async () => {
Expand Down Expand Up @@ -110,7 +111,7 @@ describe('web3 API compatibility tests', () => {
// zks_getAllAccountBalances
// NOTE: `getAllBalances` will not work on external node,
// since TokenListFetcher is not running
if (!process.env.EN_MAIN_NODE_URL) {
if (testMaster.environment().nodeMode === NodeMode.Main) {
const balances = await alice.getAllBalances();
const tokenBalance = await alice.getBalance(l2Token);
expect(balances[l2Token.toLowerCase()].eq(tokenBalance));
Expand Down Expand Up @@ -197,7 +198,7 @@ describe('web3 API compatibility tests', () => {
const tx1 = await alice.provider.getTransaction(tx.transactionHash);
expect(tx1.l1BatchNumber).toEqual(expect.anything()); // Can be anything except `null` or `undefined`.
expect(tx1.l1BatchTxIndex).toEqual(expect.anything()); // Can be anything except `null` or `undefined`.
expect(tx1.chainId).toEqual(+process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!);
expect(tx1.chainId).toEqual(testMaster.environment().l2ChainId);
expect(tx1.type).toEqual(EIP1559_TX_TYPE);

expect(receipt.l1BatchNumber).toEqual(expect.anything()); // Can be anything except `null` or `undefined`.
Expand All @@ -211,7 +212,7 @@ describe('web3 API compatibility tests', () => {
blockWithTransactions.transactions.forEach((txInBlock, _) => {
expect(txInBlock.l1BatchNumber).toEqual(expect.anything()); // Can be anything except `null` or `undefined`.
expect(txInBlock.l1BatchTxIndex).toEqual(expect.anything()); // Can be anything except `null` or `undefined`.
expect(txInBlock.chainId).toEqual(+process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!);
expect(txInBlock.chainId).toEqual(testMaster.environment().l2ChainId);
expect([0, EIP712_TX_TYPE, PRIORITY_OPERATION_L2_TX_TYPE, EIP1559_TX_TYPE]).toContain(txInBlock.type);
});
});
Expand Down Expand Up @@ -242,7 +243,7 @@ describe('web3 API compatibility tests', () => {
});

test('Should test getFilterChanges for pending transactions', async () => {
if (process.env.EN_MAIN_NODE_URL) {
if (testMaster.environment().nodeMode === NodeMode.External) {
// Pending transactions logic doesn't work on EN since we don't have a proper mempool -
// transactions only appear in the DB after they are included in the block.
return;
Expand Down Expand Up @@ -606,7 +607,7 @@ describe('web3 API compatibility tests', () => {

test('Should check metamask interoperability', async () => {
// Prepare "metamask" wallet.
const from = new MockMetamask(alice);
const from = new MockMetamask(alice, testMaster.environment().l2ChainId);
const to = alice.address;
const web3Provider = new zksync.Web3Provider(from);
const signer = zksync.Signer.from(web3Provider.getSigner(), alice.provider);
Expand Down Expand Up @@ -649,9 +650,7 @@ describe('web3 API compatibility tests', () => {

test('Should check API returns error when there are too many logs in eth_getLogs', async () => {
const contract = await deployContract(alice, contracts.events, []);
const maxLogsLimit = parseInt(
process.env.EN_REQ_ENTITIES_LIMIT ?? process.env.API_WEB3_JSON_RPC_REQ_ENTITIES_LIMIT!
);
const maxLogsLimit = testMaster.environment().maxLogsLimit;

// Send 3 transactions that emit `maxLogsLimit / 2` events.
const tx1 = await contract.emitManyEvents(maxLogsLimit / 2);
Expand Down Expand Up @@ -854,7 +853,7 @@ describe('web3 API compatibility tests', () => {
});

test('Should check transaction signature', async () => {
const CHAIN_ID = +process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!;
const CHAIN_ID = testMaster.environment().l2ChainId;
const value = 1;
const gasLimit = 350000;
const gasPrice = await alice.provider.getGasPrice();
Expand Down Expand Up @@ -951,10 +950,11 @@ describe('web3 API compatibility tests', () => {

export class MockMetamask {
readonly isMetaMask: boolean = true;
readonly networkVersion = parseInt(process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!, 10);
readonly chainId: string = ethers.utils.hexlify(parseInt(process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!, 10));
readonly chainId: string;

constructor(readonly wallet: zksync.Wallet) {}
constructor(readonly wallet: zksync.Wallet, readonly networkVersion: number) {
this.chainId = ethers.utils.hexlify(networkVersion);
}

// EIP-1193
async request(req: { method: string; params?: any[] }) {
Expand Down
Loading
Loading