Skip to content

Commit

Permalink
test: Benchmark ERC20 token transfers (#3281)
Browse files Browse the repository at this point in the history
## What ❔

Benchmarks ERC20 token transfers.

## Why ❔

It would be useful to compare their performance to base token transfers.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zkstack dev fmt` and `zkstack dev
lint`.
  • Loading branch information
slowli authored Dec 4, 2024
1 parent a7dc0ed commit dc2c476
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 7 deletions.
11 changes: 11 additions & 0 deletions core/lib/test_contracts/contracts/transfer/ERC20.sol
Original file line number Diff line number Diff line change
@@ -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);
}
}
7 changes: 7 additions & 0 deletions core/lib/test_contracts/src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ impl TestContract {
&CONTRACT
}

/// Returns a test ERC20 token implementation.
pub fn test_erc20() -> &'static Self {
static CONTRACT: Lazy<TestContract> =
Lazy::new(|| TestContract::new(raw::transfer::TestERC20));
&CONTRACT
}

/// Returns a mock version of `ContractDeployer`.
pub fn mock_deployer() -> &'static Self {
static CONTRACT: Lazy<TestContract> =
Expand Down
12 changes: 9 additions & 3 deletions core/tests/vm-benchmark/benches/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -146,6 +146,12 @@ fn bench_fill_bootloader<VM: BenchmarkingVmFactory, const FULL: bool>(
run_vm::<VM, FULL>(&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::<VM, FULL>(&mut group, "erc20_transfer", &txs);
drop(txs);

// Base token transfers
let txs: Vec<_> = (0..max_txs).map(get_transfer_tx).collect();
run_vm::<VM, FULL>(&mut group, "transfer", &txs);
Expand Down
6 changes: 3 additions & 3 deletions core/tests/vm-benchmark/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
};
Expand Down
32 changes: 32 additions & 0 deletions core/tests/vm-benchmark/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ pub fn get_transfer_tx(nonce: u32) -> Transaction {
signed.into()
}

pub fn get_erc20_transfer_tx(nonce: u32) -> Transaction {
let transfer_fn = TestContract::test_erc20().function("transfer");
let calldata = transfer_fn
.encode_input(&[
Token::Address(Address::from_low_u64_be(nonce.into())), // send tokens to unique addresses
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 calldata = [Token::Uint(U256::one() << 128)]; // initial token amount minted to the deployer
let execute = TestContract::test_erc20().deploy_payload(&calldata);
Account::new(PRIVATE_KEY.clone()).get_l2_tx_for_execute(execute, Some(tx_fee(500_000_000)))
}

pub fn get_load_test_deploy_tx() -> Transaction {
let calldata = [Token::Uint(LOAD_TEST_MAX_READS.into())];
let execute = TestContract::load_test().deploy_payload(&calldata);
Expand Down
16 changes: 15 additions & 1 deletion core/tests/vm-benchmark/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -259,6 +261,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();
Expand Down

0 comments on commit dc2c476

Please sign in to comment.