From fa15c395ec21a6abe27364a6e2a070d88abbe536 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 14 Nov 2024 16:28:27 +0200 Subject: [PATCH 1/4] Add test ERC20 contract --- etc/contracts-test-data/contracts/transfer/ERC20.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 etc/contracts-test-data/contracts/transfer/ERC20.sol diff --git a/etc/contracts-test-data/contracts/transfer/ERC20.sol b/etc/contracts-test-data/contracts/transfer/ERC20.sol new file mode 100644 index 000000000000..aad741e66a56 --- /dev/null +++ b/etc/contracts-test-data/contracts/transfer/ERC20.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract TestERC20 is ERC20("Test", "TEST") { + constructor(uint256 _toMint) { + _mint(msg.sender, _toMint); + } +} From 32a09d06e19f5e296fe70a6b60db88fd43c1fc77 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 14 Nov 2024 16:28:42 +0200 Subject: [PATCH 2/4] Bench ERC20 token transfers --- core/tests/vm-benchmark/benches/batch.rs | 12 +++- core/tests/vm-benchmark/src/lib.rs | 6 +- core/tests/vm-benchmark/src/transaction.rs | 64 +++++++++++++++++++++- core/tests/vm-benchmark/src/vm.rs | 16 +++++- 4 files changed, 90 insertions(+), 8 deletions(-) diff --git a/core/tests/vm-benchmark/benches/batch.rs b/core/tests/vm-benchmark/benches/batch.rs index 608f6be6d089..f4151c39a6f8 100644 --- a/core/tests/vm-benchmark/benches/batch.rs +++ b/core/tests/vm-benchmark/benches/batch.rs @@ -18,9 +18,9 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughpu use rand::{rngs::StdRng, Rng, SeedableRng}; use vm_benchmark::{ criterion::{is_test_mode, BenchmarkGroup, BenchmarkId, CriterionExt, MeteredTime}, - get_deploy_tx_with_gas_limit, get_heavy_load_test_tx, get_load_test_deploy_tx, - get_load_test_tx, get_realistic_load_test_tx, get_transfer_tx, BenchmarkingVm, - BenchmarkingVmFactory, Bytecode, Fast, Legacy, LoadTestParams, + get_deploy_tx_with_gas_limit, get_erc20_deploy_tx, get_erc20_transfer_tx, + get_heavy_load_test_tx, get_load_test_deploy_tx, get_load_test_tx, get_realistic_load_test_tx, + get_transfer_tx, BenchmarkingVm, BenchmarkingVmFactory, Bytecode, Fast, Legacy, LoadTestParams, }; use zksync_types::Transaction; @@ -146,6 +146,12 @@ fn bench_fill_bootloader( run_vm::(&mut group, "load_test_heavy", &txs); drop(txs); + // ERC-20 token transfers + let txs = (1..=max_txs).map(get_erc20_transfer_tx); + let txs: Vec<_> = iter::once(get_erc20_deploy_tx()).chain(txs).collect(); + run_vm::(&mut group, "erc20_transfer", &txs); + drop(txs); + // Base token transfers let txs: Vec<_> = (0..max_txs).map(get_transfer_tx).collect(); run_vm::(&mut group, "transfer", &txs); diff --git a/core/tests/vm-benchmark/src/lib.rs b/core/tests/vm-benchmark/src/lib.rs index 9c4f547c1de2..030c28ff1613 100644 --- a/core/tests/vm-benchmark/src/lib.rs +++ b/core/tests/vm-benchmark/src/lib.rs @@ -2,9 +2,9 @@ use zksync_types::Transaction; pub use crate::{ transaction::{ - get_deploy_tx, get_deploy_tx_with_gas_limit, get_heavy_load_test_tx, - get_load_test_deploy_tx, get_load_test_tx, get_realistic_load_test_tx, get_transfer_tx, - LoadTestParams, + get_deploy_tx, get_deploy_tx_with_gas_limit, get_erc20_deploy_tx, get_erc20_transfer_tx, + get_heavy_load_test_tx, get_load_test_deploy_tx, get_load_test_tx, + get_realistic_load_test_tx, get_transfer_tx, LoadTestParams, }, vm::{BenchmarkingVm, BenchmarkingVmFactory, CountInstructions, Fast, Legacy, VmLabel}, }; diff --git a/core/tests/vm-benchmark/src/transaction.rs b/core/tests/vm-benchmark/src/transaction.rs index e5be25545377..d7b467d57046 100644 --- a/core/tests/vm-benchmark/src/transaction.rs +++ b/core/tests/vm-benchmark/src/transaction.rs @@ -4,7 +4,7 @@ use zksync_contracts::{deployer_contract, TestContract}; use zksync_multivm::utils::get_max_gas_per_pubdata_byte; use zksync_types::{ bytecode::BytecodeHash, - ethabi::{encode, Token}, + ethabi::{self, encode, Token}, fee::Fee, l2::L2Tx, utils::deployed_address_create, @@ -14,12 +14,17 @@ use zksync_types::{ const LOAD_TEST_MAX_READS: usize = 3000; +const ERC20_CONTRACT_PATH: &str = + "etc/contracts-test-data/artifacts-zk/contracts/transfer/ERC20.sol/TestERC20.json"; + pub(crate) static PRIVATE_KEY: Lazy = Lazy::new(|| K256PrivateKey::from_bytes(H256([42; 32])).expect("invalid key bytes")); static LOAD_TEST_CONTRACT_ADDRESS: Lazy
= Lazy::new(|| deployed_address_create(PRIVATE_KEY.address(), 0.into())); static LOAD_TEST_CONTRACT: Lazy = Lazy::new(zksync_contracts::get_loadnext_contract); +static ERC20_TEST_CONTRACT: Lazy = + Lazy::new(|| zksync_contracts::load_contract(ERC20_CONTRACT_PATH)); static CREATE_FUNCTION_SIGNATURE: Lazy<[u8; 4]> = Lazy::new(|| { deployer_contract() @@ -92,6 +97,63 @@ pub fn get_transfer_tx(nonce: u32) -> Transaction { signed.into() } +pub fn get_erc20_transfer_tx(nonce: u32) -> Transaction { + let transfer_fn = ERC20_TEST_CONTRACT.function("transfer").unwrap(); + let calldata = transfer_fn + .encode_input(&[ + Token::Address(Address::repeat_byte(1)), + Token::Uint(1.into()), + ]) + .unwrap(); + + let mut signed = L2Tx::new_signed( + Some(*LOAD_TEST_CONTRACT_ADDRESS), + calldata, + Nonce(nonce), + tx_fee(1_000_000), + 0.into(), // value + L2ChainId::from(270), + &PRIVATE_KEY, + vec![], // factory deps + Default::default(), // paymaster params + ) + .expect("should create a signed execute transaction"); + + signed.set_input(H256::random().as_bytes().to_vec(), H256::random()); + signed.into() +} + +pub fn get_erc20_deploy_tx() -> Transaction { + let bytecode = zksync_contracts::read_bytecode(ERC20_CONTRACT_PATH); + let calldata = [Token::Uint(U256::one() << 128)]; // initial token amount minted to the deployer + let params = [ + Token::FixedBytes(vec![0_u8; 32]), + Token::FixedBytes(BytecodeHash::for_bytecode(&bytecode).value().0.to_vec()), + Token::Bytes(encode(&calldata)), + ]; + let create_calldata = CREATE_FUNCTION_SIGNATURE + .iter() + .cloned() + .chain(encode(¶ms)) + .collect(); + + let mut signed = L2Tx::new_signed( + Some(CONTRACT_DEPLOYER_ADDRESS), + create_calldata, + Nonce(0), + tx_fee(500_000_000), + U256::zero(), + L2ChainId::from(270), + &PRIVATE_KEY, + vec![bytecode], + Default::default(), + ) + .expect("should create a signed execute transaction"); + + signed.set_input(H256::random().as_bytes().to_vec(), H256::random()); + signed.into() +} + pub fn get_load_test_deploy_tx() -> Transaction { let calldata = [Token::Uint(LOAD_TEST_MAX_READS.into())]; let params = [ diff --git a/core/tests/vm-benchmark/src/vm.rs b/core/tests/vm-benchmark/src/vm.rs index a855dfafb04e..72921c7a3567 100644 --- a/core/tests/vm-benchmark/src/vm.rs +++ b/core/tests/vm-benchmark/src/vm.rs @@ -240,7 +240,9 @@ mod tests { use super::*; use crate::{ get_deploy_tx, get_heavy_load_test_tx, get_load_test_deploy_tx, get_load_test_tx, - get_realistic_load_test_tx, get_transfer_tx, LoadTestParams, BYTECODES, + get_realistic_load_test_tx, get_transfer_tx, + transaction::{get_erc20_deploy_tx, get_erc20_transfer_tx}, + LoadTestParams, BYTECODES, }; #[test] @@ -261,6 +263,18 @@ mod tests { assert_matches!(res.result, ExecutionResult::Success { .. }); } + #[test] + fn can_erc20_transfer() { + let mut vm = BenchmarkingVm::new(); + let res = vm.run_transaction(&get_erc20_deploy_tx()); + assert_matches!(res.result, ExecutionResult::Success { .. }); + + for nonce in 1..=5 { + let res = vm.run_transaction(&get_erc20_transfer_tx(nonce)); + assert_matches!(res.result, ExecutionResult::Success { .. }); + } + } + #[test] fn can_load_test() { let mut vm = BenchmarkingVm::new(); From b500eeb1c3de227169873769f29b07b88d994723 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 14 Nov 2024 17:46:05 +0200 Subject: [PATCH 3/4] Send tokens to unique addresses --- core/tests/vm-benchmark/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/vm-benchmark/src/transaction.rs b/core/tests/vm-benchmark/src/transaction.rs index d7b467d57046..332d4cf090b9 100644 --- a/core/tests/vm-benchmark/src/transaction.rs +++ b/core/tests/vm-benchmark/src/transaction.rs @@ -101,7 +101,7 @@ pub fn get_erc20_transfer_tx(nonce: u32) -> Transaction { let transfer_fn = ERC20_TEST_CONTRACT.function("transfer").unwrap(); let calldata = transfer_fn .encode_input(&[ - Token::Address(Address::repeat_byte(1)), + Token::Address(Address::from_low_u64_be(nonce.into())), // send tokens to unique addresses Token::Uint(1.into()), ]) .unwrap(); From 6d5587d8b6cbabaa840980c99d710d8b6629ad0e Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 18 Nov 2024 14:27:21 +0200 Subject: [PATCH 4/4] Checkout submodules in Protobuf workflow --- .github/workflows/protobuf.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/protobuf.yaml b/.github/workflows/protobuf.yaml index c9541167b464..f0565919ded1 100644 --- a/.github/workflows/protobuf.yaml +++ b/.github/workflows/protobuf.yaml @@ -41,6 +41,7 @@ jobs: ref: ${{ env.BASE }} path: before fetch-depth: 0 # fetches all branches and tags, which is needed to compute the LCA. + submodules: "recursive" - name: checkout LCA run: git checkout $(git merge-base $BASE $HEAD) --recurse-submodules