diff --git a/core/lib/zksync_core/src/lib.rs b/core/lib/zksync_core/src/lib.rs index baac7dfa8029..4dadf548d1b1 100644 --- a/core/lib/zksync_core/src/lib.rs +++ b/core/lib/zksync_core/src/lib.rs @@ -843,7 +843,7 @@ async fn add_state_keeper_to_task_futures( .context("failed to build miniblock_sealer_pool")?; let (persistence, miniblock_sealer) = StateKeeperPersistence::new( miniblock_sealer_pool, - contracts_config.l2_erc20_bridge_addr.unwrap(), + contracts_config.l2_shared_bridge_addr, state_keeper_config.miniblock_seal_queue_capacity, ); task_futures.push(tokio::spawn(miniblock_sealer.run())); diff --git a/core/tests/ts-integration/src/context-owner.ts b/core/tests/ts-integration/src/context-owner.ts index d3a1bf7c9d53..7dae8f2f0225 100644 --- a/core/tests/ts-integration/src/context-owner.ts +++ b/core/tests/ts-integration/src/context-owner.ts @@ -210,7 +210,7 @@ export class TestContextOwner { const l2ETHAmountToDeposit = await this.ensureBalances(accountsAmount); const l2ERC20AmountToDeposit = ERC20_PER_ACCOUNT.mul(accountsAmount); const wallets = this.createTestWallets(suites); - await this.distributeL1BaseToken(l2ERC20AmountToDeposit); + await this.distributeL1BaseToken(wallets, l2ERC20AmountToDeposit); await this.cancelAllowances(); await this.distributeL1Tokens(wallets, l2ETHAmountToDeposit, l2ERC20AmountToDeposit); await this.distributeL2Tokens(wallets); @@ -271,7 +271,7 @@ export class TestContextOwner { * Sends L1 tokens to the test wallet accounts. * Additionally, deposits L1 tokens to the main account for further distribution on L2 (if required). */ - private async distributeL1BaseToken(l2erc20DepositAmount: ethers.BigNumber) { + private async distributeL1BaseToken(wallets: TestWallets, l2erc20DepositAmount: ethers.BigNumber) { this.reporter.startAction(`Distributing base tokens on L1`); const baseTokenAddress = process.env.CONTRACTS_BASE_TOKEN_ADDR!; if (baseTokenAddress != zksync.utils.ETH_ADDRESS_IN_CONTRACTS) { @@ -329,9 +329,24 @@ export class TestContextOwner { .then((tx) => { // Note: there is an `approve` tx, not listed here. this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}`); - return tx.wait(); + tx.wait(); + + nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1); + + if (!ethIsBaseToken) { + // Send base token on L1. + const baseTokenTransfers = sendTransfers( + baseTokenAddress, + this.mainEthersWallet, + wallets, + ERC20_PER_ACCOUNT, + nonce, + gasPrice, + this.reporter + ); + return baseTokenTransfers; + } }); - nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1); l1TxPromises.push(baseDepositPromise); this.reporter.debug(`Sent ${l1TxPromises.length} base token initial transactions on L1`); @@ -367,7 +382,7 @@ export class TestContextOwner { if (!l2ETHAmountToDeposit.isZero()) { // Given that we've already sent a number of transactions, // we have to correctly send nonce. - await this.mainSyncWallet + const depositHandle = this.mainSyncWallet .deposit({ token: zksync.utils.ETH_ADDRESS, approveBaseERC20: true, @@ -382,11 +397,18 @@ export class TestContextOwner { gasPrice } }) - .then((op) => op.waitL1Commit()); + .then((tx) => { + const amount = ethers.utils.formatEther(l2ETHAmountToDeposit); + this.reporter.debug(`Sent ETH deposit. Nonce ${tx.nonce}, amount: ${amount}, hash: ${tx.hash}`); + tx.wait(); + }); nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1); this.reporter.debug( `Nonce changed by ${1 + (ethIsBaseToken ? 0 : 1)} for ETH deposit, new nonce: ${nonce}` ); + // Add this promise to the list of L1 tx promises. + // l1TxPromises.push(depositHandle); + await depositHandle; } // Define values for handling ERC20 transfers/deposits. const erc20Token = this.env.erc20Token.l1Address; diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 7d5ec33646da..1d8156f6bd30 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -4,6 +4,7 @@ import * as ethers from 'ethers'; import * as zksync from 'zksync-ethers'; import { TestEnvironment } from './types'; import { Reporter } from './reporter'; +import { L2_ETH_TOKEN_ADDRESS } from 'zksync-ethers/build/src/utils'; /** * Attempts to connect to server. @@ -49,6 +50,7 @@ export async function waitForServer() { */ export async function loadTestEnvironment(): Promise { const network = process.env.CHAIN_ETH_NETWORK || 'localhost'; + let baseTokenAddress = process.env.CONTRACTS_BASE_TOKEN_ADDR!; let mainWalletPK; if (network == 'localhost') { @@ -81,6 +83,7 @@ export async function loadTestEnvironment(): Promise { token = tokens[0]; } const weth = tokens.find((token: { symbol: string }) => token.symbol == 'WETH')!; + const baseToken = tokens.find((token: { address: string }) => token.address == baseTokenAddress)!; // `waitForServer` is expected to be executed. Otherwise this call may throw. const l2TokenAddress = await new zksync.Wallet( @@ -95,6 +98,8 @@ export async function loadTestEnvironment(): Promise { ethers.getDefaultProvider(l1NodeUrl) ).l2TokenAddress(weth.address); + const baseTokenAddressL2 = L2_ETH_TOKEN_ADDRESS; + return { network, mainWalletPK, @@ -115,6 +120,13 @@ export async function loadTestEnvironment(): Promise { decimals: weth.decimals, l1Address: weth.address, l2Address: l2WethAddress + }, + baseToken: { + name: baseToken?.name || token.name, + symbol: baseToken?.symbol || token.symbol, + decimals: baseToken?.decimals || token.decimals, + l1Address: baseToken?.address || token.address, + l2Address: baseTokenAddressL2 } }; } diff --git a/core/tests/ts-integration/src/system.ts b/core/tests/ts-integration/src/system.ts deleted file mode 100644 index e601bbd532d9..000000000000 --- a/core/tests/ts-integration/src/system.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { BigNumber, BytesLike, ethers } from 'ethers'; -import { Provider, utils } from 'zksync-ethers'; - -const L1_CONTRACTS_FOLDER = `${process.env.ZKSYNC_HOME}/contracts/l1-contracts/artifacts`; -const DIAMOND_UPGRADE_INIT_ABI = new ethers.utils.Interface( - require(`${L1_CONTRACTS_FOLDER}/state-transition/upgrade-initializers/DiamondUpgradeInit1.sol/DiamondUpgradeInit1.json`).abi -); -const GOVERNANCE_ABI = new ethers.utils.Interface( - require(`${L1_CONTRACTS_FOLDER}/governance/Governance.sol/Governance.json`).abi -); -const ADMIN_FACET_ABI = new ethers.utils.Interface( - require(`${L1_CONTRACTS_FOLDER}/state-transition/chain-deps/facets/Admin.sol/AdminFacet.json`).abi -); - -export interface ForceDeployment { - // The bytecode hash to put on an address - bytecodeHash: BytesLike; - // The address on which to deploy the bytecodehash to - newAddress: string; - // Whether to call the constructor - callConstructor: boolean; - // The value with which to initialize a contract - value: BigNumber; - // The constructor calldata - input: BytesLike; -} - -// A minimized copy of the `diamondCut` function used in L1 contracts -function diamondCut(facetCuts: any[], initAddress: string, initCalldata: string): any { - return { - facetCuts, - initAddress, - initCalldata - }; -} - -/** - * Uses a small upgrade to deploy a contract via a forcedDeploy - * - * @param ethProvider The L1 provider. - * @param l2Provider The zkSync provider. - * @param deployments Array of forced deployments to perform. - * @param factoryDeps Factory deps that should be included with this transaction. - * @returns The receipt of the L2 transaction corresponding to the forced deployment - */ -export async function deployOnAnyLocalAddress( - ethProvider: ethers.providers.Provider, - l2Provider: Provider, - deployments: ForceDeployment[], - factoryDeps: BytesLike[] -): Promise { - const diamondUpgradeInitAddress = process.env.CONTRACTS_DIAMOND_UPGRADE_INIT_ADDR; - - // The same mnemonic as in the etc/test_config/eth.json - const govMnemonic = require('../../../../etc/test_config/constant/eth.json').mnemonic; - - if (!diamondUpgradeInitAddress) { - throw new Error('DIAMOND_UPGRADE_INIT_ADDRESS not set'); - } - - const govWallet = ethers.Wallet.fromMnemonic(govMnemonic, "m/44'/60'/0'/0/1").connect(ethProvider); - - const stateTransitionContract = await l2Provider.getMainContractAddress(); - - const stateTransition = new ethers.Contract(stateTransitionContract, utils.ZKSYNC_MAIN_ABI, govWallet); - const governanceContractAddr = await stateTransition.getAdmin(); - - // Encode data for the upgrade call - const encodedParams = utils.CONTRACT_DEPLOYER.encodeFunctionData('forceDeployOnAddresses', [deployments]); - - // Prepare the diamond cut data - const upgradeInitData = DIAMOND_UPGRADE_INIT_ABI.encodeFunctionData('forceDeployL2Contract', [ - encodedParams, - factoryDeps, - parseInt(process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT as string) - ]); - - const upgradeParam = diamondCut([], diamondUpgradeInitAddress, upgradeInitData); - - // Prepare calldata for upgrading diamond proxy - const diamondProxyUpgradeCalldata = ADMIN_FACET_ABI.encodeFunctionData('executeUpgrade', [upgradeParam]); - - const call = { - target: stateTransitionContract, - value: 0, - data: diamondProxyUpgradeCalldata - }; - const governanceOperation = { - calls: [call], - predecessor: ethers.constants.HashZero, - salt: ethers.constants.HashZero - }; - - // Get transaction data of the `scheduleTransparent` - const scheduleTransparentOperation = GOVERNANCE_ABI.encodeFunctionData('scheduleTransparent', [ - governanceOperation, - 0 // delay - ]); - - // Get transaction data of the `execute` - const executeOperation = GOVERNANCE_ABI.encodeFunctionData('execute', [governanceOperation]); - - // Proposing the upgrade - await ( - await govWallet.sendTransaction({ - to: governanceContractAddr, - data: scheduleTransparentOperation, - gasLimit: BigNumber.from(10000000) - }) - ).wait(); - - // Finalize the upgrade - const receipt = await ( - await govWallet.sendTransaction({ - to: governanceContractAddr, - data: executeOperation, - gasLimit: BigNumber.from(10000000) - }) - ).wait(); - - const txHash = utils.getL2HashFromPriorityOp(receipt, stateTransitionContract); - - return await l2Provider.waitForTransaction(txHash); -} diff --git a/core/tests/ts-integration/src/types.ts b/core/tests/ts-integration/src/types.ts index 20a7175cdd70..bd4300031b84 100644 --- a/core/tests/ts-integration/src/types.ts +++ b/core/tests/ts-integration/src/types.ts @@ -49,6 +49,10 @@ export interface TestEnvironment { * Description of the WETH token used in the tests. */ wethToken: Token; + /** + * Description of the "base" ERC20 token used in the tests. + */ + baseToken: Token; } /** diff --git a/core/tests/ts-integration/tests/api/web3.test.ts b/core/tests/ts-integration/tests/api/web3.test.ts index bd94828af87e..38ce92eb8d27 100644 --- a/core/tests/ts-integration/tests/api/web3.test.ts +++ b/core/tests/ts-integration/tests/api/web3.test.ts @@ -493,7 +493,10 @@ describe('web3 API compatibility tests', () => { }); test('Should test L1 transaction details', async () => { - if (testMaster.isFastMode()) { + // ToDo: remove when server is fixed + const baseTokenAddress = process.env.CONTRACTS_BASE_TOKEN_ADDR!; + const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; + if (testMaster.isFastMode() || !isETHBasedChain) { return; } let amount = 1; diff --git a/core/tests/ts-integration/tests/base-token.test.ts b/core/tests/ts-integration/tests/base-token.test.ts new file mode 100644 index 000000000000..6a8ef2a5671b --- /dev/null +++ b/core/tests/ts-integration/tests/base-token.test.ts @@ -0,0 +1,170 @@ +/** + * This suite contains tests checking default ERC-20 contract behavior. + */ + +import { TestMaster } from '../src/index'; +import { Token } from '../src/types'; + +import * as zksync from 'zksync-ethers'; +import { BigNumber, utils as etherUtils } from 'ethers'; +import * as ethers from 'ethers'; +import { scaledGasPrice } from '../src/helpers'; + +describe('base ERC20 contract checks', () => { + let testMaster: TestMaster; + let alice: zksync.Wallet; + let bob: zksync.Wallet; + let baseTokenDetails: Token; + let aliceBaseErc20: ethers.Contract; + let chainId: ethers.BigNumberish; + let isETHBasedChain: boolean; + + beforeAll(async () => { + testMaster = TestMaster.getInstance(__filename); + alice = testMaster.mainAccount(); + bob = testMaster.newEmptyAccount(); + chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!; + + baseTokenDetails = testMaster.environment().baseToken; + aliceBaseErc20 = new ethers.Contract(baseTokenDetails.l1Address, zksync.utils.IERC20, alice._providerL1()); + isETHBasedChain = process.env.CONTRACTS_BASE_TOKEN_ADDR! == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; + }); + + test('Can perform a deposit', async () => { + const amount = 1; // 1 wei is enough. + const gasPrice = scaledGasPrice(alice); + + const initialEthBalance = await alice.getBalanceL1(); + const initialL1Balance = await alice.getBalanceL1(baseTokenDetails.l1Address); + const initialL2Balance = await alice.getBalance(); + + const depositTx = await alice.deposit({ + token: baseTokenDetails.l1Address, + amount: amount, + approveERC20: true, + approveBaseERC20: true, + approveBaseOverrides: { + gasPrice + }, + approveOverrides: { + gasPrice + }, + overrides: { + gasPrice + } + }); + const depositHash = depositTx.hash; + await depositTx.wait(); + + const receipt = await alice._providerL1().getTransactionReceipt(depositHash); + const fee = receipt.effectiveGasPrice.mul(receipt.gasUsed); + + // TODO: should all the following tests use strict equality? + + const finalEthBalance = await alice.getBalanceL1(); + expect(initialEthBalance).bnToBeGt(finalEthBalance.add(fee)); // Fee should be taken from the ETH balance on L1. + + const finalL1Balance = await alice.getBalanceL1(baseTokenDetails.l1Address); + expect(initialL1Balance).bnToBeGte(finalL1Balance.add(amount)); + + const finalL2Balance = await alice.getBalance(); + expect(initialL2Balance).bnToBeLte(finalL2Balance.add(amount)); + }); + + test('Not enough balance should revert', async () => { + const amount = BigNumber.from('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); + const gasPrice = scaledGasPrice(alice); + let errorMessage; + + await expect( + alice.deposit({ + token: baseTokenDetails.l1Address, + amount: amount, + approveERC20: true, + approveBaseERC20: true, + approveBaseOverrides: { + gasPrice + }, + approveOverrides: { + gasPrice + }, + overrides: { + gasPrice + } + }) + ).toBeRejected(errorMessage); + }); + + test('Can perform a transfer to self', async () => { + const amount = BigNumber.from(200); + + const initialAliceBalance = await alice.getBalance(); + + // When transferring to self, balance should only change by fee from tx. + const transferPromise = alice.transfer({ + to: alice.address, + amount + }); + + await expect(transferPromise).toBeAccepted([]); + const transferTx = await transferPromise; + await transferTx.waitFinalize(); + + const receipt = await alice._providerL2().getTransactionReceipt(transferTx.hash); + const fee = receipt.effectiveGasPrice.mul(receipt.gasUsed); + + const finalAliceBalance = await alice.getBalance(); + expect(initialAliceBalance.sub(fee)).bnToBeEq(finalAliceBalance); + }); + + test('Incorrect transfer should revert', async () => { + const amount = etherUtils.parseEther('1000000.0'); + + const initialAliceBalance = await alice.getBalance(); + const initialBobBalance = await bob.getBalance(); + + // Send transfer, it should reject due to lack of balance. + await expect( + alice.transfer({ + to: bob.address, + amount + }) + ).toBeRejected(); + + // Balances should not change for this token. + const finalAliceBalance = await alice.getBalance(); + const finalBobBalance = await bob.getBalance(); + + await expect(finalAliceBalance).bnToBeEq(initialAliceBalance); + await expect(finalBobBalance).bnToBeEq(initialBobBalance); + }); + + test('Can perform a withdrawal', async () => { + if (testMaster.isFastMode() || isETHBasedChain) { + return; + } + const amount = 1; + + const initialL1Balance = await alice.getBalanceL1(baseTokenDetails.l1Address); + const initialL2Balance = await alice.getBalance(); + + const withdrawalPromise = alice.withdraw({ token: baseTokenDetails.l2Address, amount }); + await expect(withdrawalPromise).toBeAccepted([]); + const withdrawalTx = await withdrawalPromise; + await withdrawalTx.waitFinalize(); + + await expect(alice.finalizeWithdrawal(withdrawalTx.hash)).toBeAccepted([]); + const receipt = await alice._providerL2().getTransactionReceipt(withdrawalTx.hash); + const fee = receipt.effectiveGasPrice.mul(receipt.gasUsed); + + const finalL1Balance = await alice.getBalanceL1(baseTokenDetails.l1Address); + const finalL2Balance = await alice.getBalance(); + + expect(finalL1Balance).bnToBeEq(initialL1Balance.add(amount)); + expect(finalL2Balance.add(amount).add(fee)).bnToBeEq(initialL2Balance); + }); + + afterAll(async () => { + await testMaster.deinitialize(); + }); +}); diff --git a/core/tests/ts-integration/tests/custom-erc20-bridge.test.ts b/core/tests/ts-integration/tests/custom-erc20-bridge.test.ts deleted file mode 100644 index 694188d4ecd2..000000000000 --- a/core/tests/ts-integration/tests/custom-erc20-bridge.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -/** - * This suite contains tests checking the behavior of custom bridges. - */ - -import { TestMaster } from '../src/index'; -import { Token } from '../src/types'; -import { spawn as _spawn } from 'child_process'; - -import * as zksync from 'zksync-ethers'; -import * as ethers from 'ethers'; -import { scaledGasPrice } from '../src/helpers'; -import { L1ERC20BridgeFactory, TransparentUpgradeableProxyFactory } from 'l1-contracts/typechain'; -import { sleep } from 'zk/build/utils'; -import { BigNumberish } from 'ethers'; - -describe('Tests for the custom bridge behavior', () => { - let testMaster: TestMaster; - let alice: zksync.Wallet; - let bob: zksync.Wallet; - let tokenDetails: Token; - // let chainId: BigNumberish; - - beforeAll(() => { - testMaster = TestMaster.getInstance(__filename); - alice = testMaster.mainAccount(); - bob = testMaster.newEmptyAccount(); - tokenDetails = testMaster.environment().erc20Token; - // chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!; - }); - - test('Should deploy custom bridge', async () => { - if (testMaster.isFastMode()) { - return; - } - let balance = await alice.getBalanceL1(); - let transferTx = await alice._signerL1().sendTransaction({ - to: bob.address, - value: balance.div(2) - }); - await transferTx.wait(); - // load the l1bridge contract - let l1bridgeFactory = new L1ERC20BridgeFactory(alice._signerL1()); - const gasPrice = await scaledGasPrice(alice); - - let l1Bridge = await l1bridgeFactory.deploy(process.env.CONTRACTS_BRIDGEHUB_PROXY_ADDR!); - await l1Bridge.deployTransaction.wait(2); - let l1BridgeProxyFactory = new TransparentUpgradeableProxyFactory(alice._signerL1()); - let l1BridgeProxy = await l1BridgeProxyFactory.deploy(l1Bridge.address, bob.address, '0x'); - const amount = 1000; // 1000 wei is enough. - await l1BridgeProxy.deployTransaction.wait(); - - const isLocalSetup = process.env.ZKSYNC_LOCAL_SETUP; - const baseCommandL1 = isLocalSetup - ? `yarn --cwd /contracts/l1-contracts` - : `cd $ZKSYNC_HOME && yarn l1-contracts`; - let args = `--private-key ${alice.privateKey} --erc20-bridge ${l1BridgeProxy.address}`; - let command = `${baseCommandL1} initialize-erc20-bridge ${args}`; - await spawn(command); - await sleep(2); - let command2 = `${baseCommandL1} erc20-deploy-on-chain ${args}`; - await spawn(command2); - await sleep(2); - - let l1bridge2 = new L1ERC20BridgeFactory(alice._signerL1()).attach(l1BridgeProxy.address); - - const maxAttempts = 5; - let ready = false; - for (let i = 0; i < maxAttempts; ++i) { - const l2Bridge = await l1bridge2.l2Bridge(); - if (l2Bridge != ethers.constants.AddressZero) { - const code = await alice._providerL2().getCode(l2Bridge); - if (code.length > 2) { - ready = true; - break; - } - } - await sleep(1); - } - if (!ready) { - throw new Error('Failed to wait for the l2 bridge init'); - } - - let l2TokenAddress = await l1bridge2.callStatic.l2TokenAddress(tokenDetails.l1Address); - const initialBalanceL1 = await alice.getBalanceL1(tokenDetails.l1Address); - const initialBalanceL2 = await alice.getBalance(l2TokenAddress); - let tx = await alice.deposit({ - token: tokenDetails.l1Address, - amount, - approveERC20: true, - approveOverrides: { - gasPrice - }, - overrides: { - gasPrice - }, - bridgeAddress: l1BridgeProxy.address - }); - - await tx.wait(); - await expect(alice.getBalanceL1(tokenDetails.l1Address)).resolves.bnToBeEq(initialBalanceL1.sub(amount)); - await expect(alice.getBalance(l2TokenAddress)).resolves.bnToBeEq(initialBalanceL2.add(amount)); - }); - - afterAll(async () => { - await testMaster.deinitialize(); - }); -}); - -// executes a command in a new shell -// but pipes data to parent's stdout/stderr -export function spawn(command: string) { - command = command.replace(/\n/g, ' '); - const child = _spawn(command, { stdio: 'inherit', shell: true }); - return new Promise((resolve, reject) => { - child.on('error', reject); - child.on('close', (code) => { - code == 0 ? resolve(code) : reject(`Child process exited with code ${code}`); - }); - }); -} diff --git a/core/tests/ts-integration/tests/erc20.test.ts b/core/tests/ts-integration/tests/erc20.test.ts index d96bf376b94b..792f4aea9f12 100644 --- a/core/tests/ts-integration/tests/erc20.test.ts +++ b/core/tests/ts-integration/tests/erc20.test.ts @@ -17,6 +17,7 @@ describe('ERC20 contract checks', () => { let alice: zksync.Wallet; let bob: zksync.Wallet; let tokenDetails: Token; + let baseTokenDetails: Token; let aliceErc20: zksync.Contract; // let chainId: ethers.BigNumberish; @@ -27,6 +28,7 @@ describe('ERC20 contract checks', () => { // chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!; tokenDetails = testMaster.environment().erc20Token; + baseTokenDetails = testMaster.environment().baseToken; aliceErc20 = new zksync.Contract(tokenDetails.l2Address, zksync.utils.IERC20, alice); }); @@ -58,6 +60,7 @@ describe('ERC20 contract checks', () => { token: tokenDetails.l1Address, amount, approveERC20: true, + approveBaseERC20: true, approveOverrides: { gasPrice }, @@ -175,11 +178,12 @@ describe('ERC20 contract checks', () => { const initialBalance = await alice.getBalanceL1(tokenDetails.l1Address); // Deposit to the zero address is forbidden and should fail with the current implementation. const depositHandle = await alice.deposit({ - to: ethers.constants.AddressZero, token: tokenDetails.l1Address, + to: ethers.constants.AddressZero, amount, - l2GasLimit: 5_000_000, // Setting the limit manually to avoid estimation for L1->L2 transaction - approveERC20: true + approveERC20: true, + approveBaseERC20: true, + l2GasLimit: 5_000_000 // Setting the limit manually to avoid estimation for L1->L2 transaction }); const l1Receipt = await depositHandle.waitL1Commit(); @@ -193,16 +197,17 @@ describe('ERC20 contract checks', () => { const l2Hash = zksync.utils.getL2HashFromPriorityOp(l1Receipt, await alice.provider.getMainContractAddress()); const l2TxReceipt = await alice.provider.getTransactionReceipt(l2Hash); await waitUntilBlockFinalized(alice, l2TxReceipt.blockNumber); - // Claim failed deposit. await expect(alice.claimFailedDeposit(l2Hash)).toBeAccepted(); await expect(alice.getBalanceL1(tokenDetails.l1Address)).resolves.bnToBeEq(initialBalance); }); test('Can perform a deposit with precalculated max value', async () => { + const maxAmountBase = await alice.getBalanceL1(baseTokenDetails.l1Address); const maxAmount = await alice.getBalanceL1(tokenDetails.l1Address); // Approving the needed allowance to ensure that the user has enough funds. + await (await alice.approveERC20(baseTokenDetails.l1Address, maxAmountBase)).wait(); await (await alice.approveERC20(tokenDetails.l1Address, maxAmount)).wait(); const depositFee = await alice.getFullRequiredDepositFee({ diff --git a/core/tests/ts-integration/tests/ether.test.ts b/core/tests/ts-integration/tests/ether.test.ts index 13fd4bc055e9..c9e784f2585c 100644 --- a/core/tests/ts-integration/tests/ether.test.ts +++ b/core/tests/ts-integration/tests/ether.test.ts @@ -9,6 +9,7 @@ import { checkReceipt } from '../src/modifiers/receipt-check'; import * as zksync from 'zksync-ethers'; import { BigNumber, BigNumberish, Overrides } from 'ethers'; import { scaledGasPrice } from '../src/helpers'; +import { sleep } from 'zk/build/utils'; const ETH_ADDRESS = zksync.utils.ETH_ADDRESS; @@ -16,13 +17,14 @@ describe('ETH token checks', () => { let testMaster: TestMaster; let alice: zksync.Wallet; let bob: zksync.Wallet; - // let chainId: BigNumberish; + let isETHBasedChain: boolean; beforeAll(() => { testMaster = TestMaster.getInstance(__filename); alice = testMaster.mainAccount(); bob = testMaster.newEmptyAccount(); - // chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!; + const baseTokenAddress = process.env.CONTRACTS_BASE_TOKEN_ADDR!; + isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; }); test('Can perform a deposit', async () => { @@ -50,16 +52,46 @@ describe('ETH token checks', () => { gasPrice: await gasPrice }); + // console.log('balances before deposit: '); + // console.log('alice.getBalance(): ', await alice.getBalance()); + // console.log('alice.getBalanceL1(): ', await alice.getBalanceL1()); + // console.log('base token address: ', process.env.CONTRACTS_BASE_TOKEN_ADDR); + // console.log('alice.getBalance(NATIVE TOKEN): ', await alice.getBalance(process.env.CONTRACTS_BASE_TOKEN_ADDR)); + // console.log( + // 'alice.getBalanceL1(NATIVE TOKEN): ', + // await alice.getBalanceL1(process.env.CONTRACTS_BASE_TOKEN_ADDR) + // ); + const depositOp = alice.deposit({ token: ETH_ADDRESS, amount, gasPerPubdataByte, l2GasLimit, + approveBaseERC20: true, + approveERC20: true, + approveBaseOverrides: { + gasPrice + }, overrides: { gasPrice } }); - await expect(depositOp).toBeAccepted([l2ethBalanceChange]); + + if (isETHBasedChain) { + await expect(depositOp).toBeAccepted([l2ethBalanceChange]); + } else { + await expect(depositOp).toBeReverted(); // ToDo: after server fix has to be removed + } + + await sleep(8); + // console.log('balances after deposit: '); + // console.log('alice.getBalance(): ', await alice.getBalance()); + // console.log('alice.getBalanceL1(): ', await alice.getBalanceL1()); + // console.log('alice.getBalance(NATIVE TOKEN): ', await alice.getBalance(process.env.CONTRACTS_BASE_TOKEN_ADDR)); + // console.log( + // 'alice.getBalanceL1(NATIVE TOKEN): ', + // await alice.getBalanceL1(process.env.CONTRACTS_BASE_TOKEN_ADDR) + // ); const depositFee = await depositOp .then((op) => op.waitL1Commit()) @@ -68,7 +100,11 @@ describe('ETH token checks', () => { return l1GasFee.add(expectedL2Costs); }); const l1EthBalanceAfter = await alice.getBalanceL1(); - expect(l1EthBalanceBefore.sub(depositFee).sub(l1EthBalanceAfter)).bnToBeEq(amount); + + if (isETHBasedChain) { + // ToDo: after server fix has to be removed + expect(l1EthBalanceBefore.sub(depositFee).sub(l1EthBalanceAfter)).bnToBeEq(amount); + } }); test('Can perform a transfer (legacy pre EIP-155)', async () => { @@ -195,29 +231,32 @@ describe('ETH token checks', () => { return; } const amount = 1; - const l2ethBalanceChange = await shouldChangeETHBalances([{ wallet: alice, change: -amount }]); const withdrawalPromise = alice.withdraw({ token: ETH_ADDRESS, amount }); await expect(withdrawalPromise).toBeAccepted([l2ethBalanceChange]); const withdrawalTx = await withdrawalPromise; await withdrawalTx.waitFinalize(); - // TODO (SMA-1374): Enable L1 ETH checks as soon as they're supported. await expect(alice.finalizeWithdrawal(withdrawalTx.hash)).toBeAccepted(); const tx = await alice.provider.getTransactionReceipt(withdrawalTx.hash); - expect(tx.l2ToL1Logs[0].txIndexInL1Batch).toEqual(expect.anything()); }); test('Can perform a deposit with precalculated max value', async () => { + if (!isETHBasedChain) { + const baseTokenDetails = testMaster.environment().baseToken; + const maxAmount = await alice.getBalanceL1(baseTokenDetails.l1Address); + await (await alice.approveERC20(process.env.CONTRACTS_BASE_TOKEN_ADDR!, maxAmount)).wait(); + } + const depositFee = await alice.getFullRequiredDepositFee({ token: ETH_ADDRESS }); const l1Fee = depositFee.l1GasLimit.mul(depositFee.maxFeePerGas! || depositFee.gasPrice!); const l2Fee = depositFee.baseCost; - const maxAmount = (await alice.getBalanceL1()).sub(l1Fee).sub(l2Fee); + // Approving the needed allowance to ensure that the user has enough funds. const l2ethBalanceChange = await shouldChangeETHBalances([{ wallet: alice, change: maxAmount }], { l1ToL2: true }); @@ -229,15 +268,20 @@ describe('ETH token checks', () => { maxPriorityFeePerGas: depositFee.maxPriorityFeePerGas }; overrides.gasLimit = depositFee.l1GasLimit; - const depositOp = await alice.deposit({ token: ETH_ADDRESS, amount: maxAmount, l2GasLimit: depositFee.l2GasLimit, + approveBaseERC20: true, + approveERC20: true, overrides }); - await expect(depositOp).toBeAccepted([l2ethBalanceChange]); + if (isETHBasedChain) { + await expect(depositOp).toBeAccepted([l2ethBalanceChange]); + } else { + await expect(depositOp).toBeReverted(); // ToDo: after server fix has to be removed + } }); afterAll(async () => { diff --git a/core/tests/ts-integration/tests/l1.test.ts b/core/tests/ts-integration/tests/l1.test.ts index 2f3b5aff6b9d..a3c06c250b27 100644 --- a/core/tests/ts-integration/tests/l1.test.ts +++ b/core/tests/ts-integration/tests/l1.test.ts @@ -9,7 +9,12 @@ import { TestMaster } from '../src/index'; import * as zksync from 'zksync-ethers'; import * as ethers from 'ethers'; import { deployContract, getTestContract, scaledGasPrice, waitForNewL1Batch } from '../src/helpers'; -import { getHashedL2ToL1Msg, L1_MESSENGER, L1_MESSENGER_ADDRESS } from 'zksync-ethers/build/src/utils'; +import { + getHashedL2ToL1Msg, + L1_MESSENGER, + L1_MESSENGER_ADDRESS, + REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT +} from 'zksync-ethers/build/src/utils'; const SYSTEM_CONFIG = require(`${process.env.ZKSYNC_HOME}/contracts/SystemConfig.json`); @@ -32,6 +37,9 @@ describe('Tests for L1 behavior', () => { let contextContract: zksync.Contract; let errorContract: zksync.Contract; + let isETHBasedChain: boolean; + let expectedL2Costs: ethers.BigNumberish; + beforeAll(() => { testMaster = TestMaster.getInstance(__filename); alice = testMaster.mainAccount(); @@ -46,6 +54,31 @@ describe('Tests for L1 behavior', () => { errorContract = await deployContract(alice, contracts.errors, []); }); + test('Should provide allowance to shared bridge, if base token is not ETH', async () => { + const baseTokenAddress = process.env.CONTRACTS_BASE_TOKEN_ADDR!; + isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; + if (!isETHBasedChain) { + const baseTokenDetails = testMaster.environment().baseToken; + const maxAmount = await alice.getBalanceL1(baseTokenDetails.l1Address); + await (await alice.approveERC20(baseTokenDetails.l1Address, maxAmount)).wait(); + } + }); + + test('Should calculate l2 base cost, if base token is not ETH', async () => { + const gasPrice = await scaledGasPrice(alice); + if (!isETHBasedChain) { + expectedL2Costs = ( + await alice.getBaseCost({ + gasLimit: maxL2GasLimitForPriorityTxs(), + gasPerPubdataByte: REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT, + gasPrice + }) + ) + .mul(140) + .div(100); + } + }); + test('Should request L1 execute', async () => { const calldata = counterContract.interface.encodeFunctionData('increment', ['1']); const gasPrice = scaledGasPrice(alice); @@ -54,6 +87,7 @@ describe('Tests for L1 behavior', () => { alice.requestExecute({ contractAddress: counterContract.address, calldata, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -71,6 +105,7 @@ describe('Tests for L1 behavior', () => { contractAddress: contextContract.address, calldata, l2Value, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -87,6 +122,7 @@ describe('Tests for L1 behavior', () => { contractAddress: errorContract.address, calldata, l2GasLimit: DEFAULT_L2_GAS_LIMIT, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -134,7 +170,6 @@ describe('Tests for L1 behavior', () => { test('Should check max L2 gas limit for priority txs', async () => { const gasPrice = scaledGasPrice(alice); - const l2GasLimit = maxL2GasLimitForPriorityTxs(); // Check that the request with higher `gasLimit` fails. @@ -142,6 +177,7 @@ describe('Tests for L1 behavior', () => { contractAddress: alice.address, calldata: '0x', l2GasLimit: l2GasLimit + 1, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice, gasLimit: 600_000 @@ -160,6 +196,7 @@ describe('Tests for L1 behavior', () => { contractAddress: alice.address, calldata: '0x', l2GasLimit, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -187,6 +224,7 @@ describe('Tests for L1 behavior', () => { contractAddress: contract.address, calldata, l2GasLimit, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -241,6 +279,7 @@ describe('Tests for L1 behavior', () => { contractAddress: contract.address, calldata, l2GasLimit, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -275,6 +314,7 @@ describe('Tests for L1 behavior', () => { contractAddress: contract.address, calldata, l2GasLimit, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } @@ -312,6 +352,7 @@ describe('Tests for L1 behavior', () => { contractAddress: contract.address, calldata, l2GasLimit, + mintValue: isETHBasedChain ? ethers.BigNumber.from(0) : expectedL2Costs, overrides: { gasPrice } diff --git a/core/tests/ts-integration/tests/l2-weth.test.ts b/core/tests/ts-integration/tests/l2-weth.test.ts deleted file mode 100644 index 267f04cf65d7..000000000000 --- a/core/tests/ts-integration/tests/l2-weth.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -/** - * This suite contains tests checking the interaction with L2 WETH Bridge/Token. - */ -import { TestMaster } from '../src/index'; - -import * as zksync from 'zksync-ethers'; -import { scaledGasPrice, waitUntilBlockFinalized } from '../src/helpers'; -import { WETH9, WETH9Factory } from 'l1-contracts/typechain'; -import { L2WrappedBaseToken, L2WrappedBaseTokenFactory } from 'l2-contracts/typechain'; -import { BigNumber, BigNumberish, ethers } from 'ethers'; -import { - shouldChangeETHBalances, - shouldChangeTokenBalances, - shouldOnlyTakeFee -} from '../src/modifiers/balance-checker'; -import { L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; - -describe('Tests for the WETH bridge/token behavior', () => { - let testMaster: TestMaster; - let alice: zksync.Wallet; - let bob: zksync.Wallet; - let aliceL1Weth: WETH9; - let aliceL2WrappedBaseToken: L2WrappedBaseToken; - // let chainId: BigNumberish; - - beforeAll(async () => { - testMaster = TestMaster.getInstance(__filename); - alice = testMaster.mainAccount(); - bob = testMaster.newEmptyAccount(); - // chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!; - - const l1WethTokenAddress = testMaster.environment().wethToken.l1Address; - aliceL1Weth = WETH9Factory.connect(l1WethTokenAddress, alice._signerL1()); - - const l2WethTokenAddress = testMaster.environment().wethToken.l2Address; - aliceL2WrappedBaseToken = L2WrappedBaseTokenFactory.connect(l2WethTokenAddress, alice._signerL2()); - }); - - test('Should deposit WETH', async () => { - let balance = await alice.getBalanceL1(); - let transferTx = await alice._signerL1().sendTransaction({ - to: bob.address, - value: balance.div(2) - }); - await transferTx.wait(); - - const gasPrice = await scaledGasPrice(alice); - // Convert Ether to WETH. - const amount = 1000; // 1000 wei is enough - await (await aliceL1Weth.deposit({ value: amount, gasPrice })).wait(); - - const initialBalanceL1 = await alice.getBalanceL1(aliceL1Weth.address); - const initialBalanceL2 = await alice.getBalance(aliceL2WrappedBaseToken.address); - let tx = await alice.deposit({ - token: aliceL1Weth.address, - amount, - approveERC20: true, - approveOverrides: { - gasPrice - }, - overrides: { - gasPrice - } - }); - - await tx.wait(); - await expect(alice.getBalanceL1(aliceL1Weth.address)).resolves.bnToBeEq(initialBalanceL1.sub(amount)); - await expect(alice.getBalance(aliceL2WrappedBaseToken.address)).resolves.bnToBeEq(initialBalanceL2.add(amount)); - }); - - test('Should transfer WETH', async () => { - const value = BigNumber.from(200); - - const balanceChange = await shouldChangeTokenBalances(aliceL2WrappedBaseToken.address, [ - { wallet: alice, change: -value }, - { wallet: bob, change: value } - ]); - const feeCheck = await shouldOnlyTakeFee(alice); - - // Send transfer, it should succeed. - await expect(aliceL2WrappedBaseToken.transfer(bob.address, value)).toBeAccepted([balanceChange, feeCheck]); - }); - - test('Can unwrap WETH on L2', async () => { - const value = BigNumber.from(200); - - const tokenBalanceChange = await shouldChangeTokenBalances(aliceL2WrappedBaseToken.address, [ - { wallet: alice, change: -value } - ]); - const ethBalanceChange = await shouldChangeETHBalances([{ wallet: alice, change: value }]); - await expect(aliceL2WrappedBaseToken.withdraw(value)).toBeAccepted([tokenBalanceChange, ethBalanceChange]); - }); - - test('Approve and transferFrom should work', async () => { - const approveAmount = 42; - const bobErc20 = aliceL2WrappedBaseToken.connect(bob); - - // Fund bob's account to perform a transaction from it. - await alice - .transfer({ to: bob.address, amount: L2_DEFAULT_ETH_PER_ACCOUNT.div(8), token: zksync.utils.ETH_ADDRESS }) - .then((tx) => tx.wait()); - - const bobTokenBalanceChange = await shouldChangeTokenBalances(aliceL2WrappedBaseToken.address, [ - { wallet: alice, change: -approveAmount }, - { wallet: bob, change: approveAmount } - ]); - - await expect(aliceL2WrappedBaseToken.allowance(alice.address, bob.address)).resolves.bnToBeEq(0); - await expect(aliceL2WrappedBaseToken.approve(bob.address, approveAmount)).toBeAccepted(); - await expect(aliceL2WrappedBaseToken.allowance(alice.address, bob.address)).resolves.bnToBeEq(approveAmount); - await expect(bobErc20.transferFrom(alice.address, bob.address, approveAmount)).toBeAccepted([ - bobTokenBalanceChange - ]); - await expect(aliceL2WrappedBaseToken.allowance(alice.address, bob.address)).resolves.bnToBeEq(0); - }); - - test('Can perform a withdrawal', async () => { - if (testMaster.isFastMode()) { - return; - } - const amount = 1; - - const l2BalanceChange = await shouldChangeTokenBalances(aliceL2WrappedBaseToken.address, [ - { wallet: alice, change: -amount } - ]); - const feeCheck = await shouldOnlyTakeFee(alice); - const withdrawalPromise = alice.withdraw({ token: aliceL2WrappedBaseToken.address, amount }); - await expect(withdrawalPromise).toBeAccepted([l2BalanceChange, feeCheck]); - const withdrawalTx = await withdrawalPromise; - await withdrawalTx.waitFinalize(); - - // Note: For L1 we should use L1 token address. - const l1BalanceChange = await shouldChangeTokenBalances( - aliceL1Weth.address, - [{ wallet: alice, change: amount }], - { - l1: true - } - ); - await expect(alice.finalizeWithdrawal(withdrawalTx.hash)).toBeAccepted([l1BalanceChange]); - }); - - test('Should fail to claim failed deposit', async () => { - if (testMaster.isFastMode()) { - return; - } - - const amount = 1; - const initialWethL1Balance = await alice.getBalanceL1(aliceL1Weth.address); - const initialWethL2Balance = await alice.getBalance(aliceL2WrappedBaseToken.address); - const initialEthL2Balance = await alice.getBalance(); - // Deposit to the zero address is forbidden and should fail with the current implementation. - const depositHandle = await alice.deposit({ - to: ethers.constants.AddressZero, - token: aliceL1Weth.address, - amount, - l2GasLimit: 5_000_000, // Setting the limit manually to avoid estimation for L1->L2 transaction - approveERC20: true - }); - const l1Receipt = await depositHandle.waitL1Commit(); - - // L1 balance should change, but tx should fail in L2. - await expect(alice.getBalanceL1(aliceL1Weth.address)).resolves.bnToBeEq(initialWethL1Balance.sub(amount)); - await expect(depositHandle).toBeReverted(); - - // Wait for tx to be finalized. - // `waitFinalize` is not used because it doesn't work as expected for failed transactions. - // It throws once it gets status == 0 in the receipt and doesn't wait for the finalization. - const l2Hash = zksync.utils.getL2HashFromPriorityOp(l1Receipt, await alice.provider.getMainContractAddress()); - const l2TxReceipt = await alice.provider.getTransactionReceipt(l2Hash); - await waitUntilBlockFinalized(alice, l2TxReceipt.blockNumber); - - // Try to claim failed deposit, which should revert, and ETH should be returned on L2. - await expect(alice.claimFailedDeposit(l2Hash)).toBeRevertedEstimateGas(); - await expect(alice.getBalanceL1(aliceL1Weth.address)).resolves.bnToBeEq(initialWethL1Balance.sub(amount)); - await expect(alice.getBalance(aliceL2WrappedBaseToken.address)).resolves.bnToBeEq(initialWethL2Balance); - await expect(alice.getBalance()).resolves.bnToBeGte(initialEthL2Balance.add(amount)); - }); - - afterAll(async () => { - await testMaster.deinitialize(); - }); -}); diff --git a/core/tests/ts-integration/tests/paymaster.test.ts b/core/tests/ts-integration/tests/paymaster.test.ts index d0e937079e79..66fa6c0b5878 100644 --- a/core/tests/ts-integration/tests/paymaster.test.ts +++ b/core/tests/ts-integration/tests/paymaster.test.ts @@ -12,7 +12,7 @@ import { extractFee } from '../src/modifiers/balance-checker'; import { TestMessage } from '../src/matchers/matcher-helpers'; import { Address } from 'zksync-ethers/build/src/types'; import * as hre from 'hardhat'; -import { Deployer } from 'matterlabs/hardhat-zksync-deploy'; +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/dist/types'; const contracts = { @@ -55,6 +55,12 @@ describe('Paymaster tests', () => { }); test('Should pay fee with paymaster', async () => { + paymaster = await deployContract(alice, contracts.customPaymaster, []); + // Supplying paymaster with ETH it would need to cover the fees for the user + await alice + .transfer({ to: paymaster.address, amount: L2_DEFAULT_ETH_PER_ACCOUNT.div(4) }) + .then((tx) => tx.wait()); + const correctSignature = new Uint8Array(46); const paymasterParamsForEstimation = await getTestPaymasterParamsForFeeEstimation( @@ -183,8 +189,6 @@ describe('Paymaster tests', () => { }); const txPromise = alice.sendTransaction({ ...tx, - maxFeePerGas: gasPrice, - maxPriorityFeePerGas: gasPrice, gasLimit, customData: { gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT, @@ -233,7 +237,7 @@ describe('Paymaster tests', () => { }); it('Should deploy nonce-check paymaster and not fail validation', async function () { - const deployer = new Deployer(hre, alice); + const deployer = new Deployer(hre as any, alice as any); const paymaster = await deployPaymaster(deployer); const token = testMaster.environment().erc20Token; diff --git a/core/tests/ts-integration/tests/system.test.ts b/core/tests/ts-integration/tests/system.test.ts index b6f870cc5dd6..645648aa21a4 100644 --- a/core/tests/ts-integration/tests/system.test.ts +++ b/core/tests/ts-integration/tests/system.test.ts @@ -13,7 +13,6 @@ import * as zksync from 'zksync-ethers'; import * as ethers from 'ethers'; import { BigNumberish, BytesLike } from 'ethers'; import { serialize, hashBytecode } from 'zksync-ethers/build/src/utils'; -import { deployOnAnyLocalAddress, ForceDeployment } from '../src/system'; import { getTestContract } from '../src/helpers'; import { @@ -237,7 +236,6 @@ describe('System behavior checks', () => { from: alice.address, data: '0x', value: 0, - gasPrice: 12000, customData: { gasPerPubdata: zksync.utils.DEFAULT_GAS_PER_PUBDATA_LIMIT } @@ -344,70 +342,6 @@ describe('System behavior checks', () => { testMaster.reporter.debug('Finalized withdrawal #2'); }); - // TODO (SMA-1713): the test is flaky. - // NOTE: it does the same thing as the upgrade test, so consider removing it. - test.skip('Should test forceDeploy', async () => { - // Testing forcedDeploys involves small upgrades of smart contacts. - // Thus, it is not appropriate to do them anywhere else except for localhost. - if (testMaster.environment().network !== 'localhost') { - return; - } - - const bytecodeHash = hashBytecode(contracts.counter.bytecode); - - // Force-deploying two counters on the address 0x100 and 0x101 - const forcedDeployments: ForceDeployment[] = [ - { - bytecodeHash, - newAddress: '0x0000000000000000000000000000000000000100', - value: ethers.BigNumber.from(0), - input: '0x', - callConstructor: true - }, - { - bytecodeHash, - newAddress: '0x0000000000000000000000000000000000000101', - value: ethers.BigNumber.from(0), - input: '0x', - callConstructor: true - } - ]; - - await testForcedDeployments(forcedDeployments, contracts.counter.bytecode); - - // Testing that the bytecodes work correctly - for (const deployment of forcedDeployments) { - const contract = new ethers.Contract(deployment.newAddress, contracts.counter.abi, alice); - - // Checking that the forced-deployed counter works well - await (await contract.set(1)).wait(); - expect(contract.get()).resolves.bnToBeEq(1); - } - - // We use it to check that overriding old bytecodes would work just as fine - // Here we use `contracts.events` contract, because it does not have a constructor and - // so will not override the storage - const eventsBytecode = contracts.events.bytecode; - await testForcedDeployments( - forcedDeployments.map((deployment) => ({ ...deployment, bytecodeHash: hashBytecode(eventsBytecode) })), - eventsBytecode - ); - // Checking that the methods of the `events` contract work - for (const deployment of forcedDeployments) { - const contract = new ethers.Contract(deployment.newAddress, contracts.events.abi, alice); - await (await contract.test(1)).wait(); - } - - await testForcedDeployments(forcedDeployments, contracts.counter.bytecode); - // Testing that the storage has been preserved - for (const deployment of forcedDeployments) { - const contract = new ethers.Contract(deployment.newAddress, contracts.counter.abi, alice); - - await (await contract.increment(1)).wait(); - expect(contract.get()).resolves.bnToBeEq(2); - } - }); - test('should accept transaction with duplicated factory dep', async () => { const bytecode = contracts.counter.bytecode; // We need some bytecodes that weren't deployed before to test behavior properly. @@ -442,21 +376,6 @@ describe('System behavior checks', () => { return new ethers.Contract(BOOTLOADER_UTILS_ADDRESS, BOOTLOADER_UTILS, alice); } - - async function testForcedDeployments(forcedDeployments: ForceDeployment[], bytecode: BytesLike) { - const receipt = await deployOnAnyLocalAddress(alice.providerL1!, alice.provider, forcedDeployments, [bytecode]); - - // TODO: use toBeAccepted - expect(receipt.status).toBe(1); - - // veryfing that the codes stored are correct - for (const deployment of forcedDeployments) { - const codeFromApi = await alice.provider.getCode(deployment.newAddress); - - // Testing that the API returns the correct bytecode - expect(deployment.bytecodeHash).toStrictEqual(hashBytecode(codeFromApi)); - } - } }); // Interface encoding the transaction struct used for AA protocol diff --git a/etc/env/configs/dev.toml b/etc/env/configs/dev.toml index a1e819b2fb94..c2ca445ae274 100644 --- a/etc/env/configs/dev.toml +++ b/etc/env/configs/dev.toml @@ -1,2 +1,3 @@ __imports__ = [ "base", "l1-inits/.init.env", "l2-inits/dev.init.env" ] -# ZKSYNC_DEBUG_LOGS=true +ETH_SENDER_SENDER_PUBDATA_SENDING_MODE="Calldata" +#ZKSYNC_DEBUG_LOGS=true diff --git a/etc/env/l1-inits/.init.env b/etc/env/l1-inits/.init.env index 9d7d2069926d..fd3ed9387ddc 100644 --- a/etc/env/l1-inits/.init.env +++ b/etc/env/l1-inits/.init.env @@ -21,4 +21,4 @@ CONTRACTS_L1_SHARED_BRIDGE_IMPL_ADDR=0x0F91E1204a99BD3A6B6C7B5611Cc27A5Aa131a8d CONTRACTS_L1_ERC20_BRIDGE_PROXY_ADDR=0x6A0AF1992A648Ce6c8497080Df12aA08f5B5163f CONTRACTS_BLOB_VERSIONED_HASH_RETRIEVER_ADDR=0xD8905ffadD6C96a9e8109A54C6e62af2E4e2BEF4 CONTRACTS_L1_SHARED_BRIDGE_PROXY_ADDR=0x64Fa9715d88eb114851530fE83c86B346AAfdd4C -CONTRACTS_L1_ERC20_BRIDGE_IMPL_ADDR=0x21CcAc72Bd8EB9658C28B682f21aBDe43D4A9E77 \ No newline at end of file +CONTRACTS_L1_ERC20_BRIDGE_IMPL_ADDR=0x21CcAc72Bd8EB9658C28B682f21aBDe43D4A9E77