Skip to content
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
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Users can select any of the artifacts depending on their testing needs for their
- ✨ EIP-7823, EIP-7883: Add test cases for ModExp precompile gas-cost updates and input limits on Osaka ([#1579](https://github.com/ethereum/execution-spec-tests/pull/1579), [#1729](https://github.com/ethereum/execution-spec-tests/pull/1729)).
- ✨ [EIP-7825](https://eips.ethereum.org/EIPS/eip-7825): Add test cases for the transaction gas limit of 30M gas ([#1711](https://github.com/ethereum/execution-spec-tests/pull/1711)).
- ✨ [EIP-7951](https://eips.ethereum.org/EIPS/eip-7951): add test cases for `P256VERIFY` precompile to support secp256r1 curve [#1670](https://github.com/ethereum/execution-spec-tests/pull/1670).
- ✨ Introduce blockchain tests for ZKEVM to cover the scenario of pure ether transfers [#1742](https://github.com/ethereum/execution-spec-tests/pull/1742).

## [v4.5.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.5.0) - 2025-05-14

Expand Down
158 changes: 158 additions & 0 deletions tests/zkevm/test_worst_blocks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
"""
abstract: Tests zkEVMs worst-case block scenarios.
Tests zkEVMs worst-case block scenarios.

Tests running worst-case block scenarios for zkEVMs.
"""

import pytest

from ethereum_test_forks import Fork
from ethereum_test_tools import (
Account,
Address,
Alloc,
Block,
BlockchainTestFiller,
Environment,
Transaction,
)


@pytest.fixture
def iteration_count(eth_transfer_cost: int):
"""Calculate the number of iterations based on the gas limit and intrinsic cost."""
return Environment().gas_limit // eth_transfer_cost


@pytest.fixture
def transfer_amount():
"""Ether to transfer in each transaction."""
return 1


@pytest.fixture
def eth_transfer_cost(fork: Fork):
"""Transaction gas limit."""
intrinsic_cost = fork.transaction_intrinsic_cost_calculator()
return intrinsic_cost()


def get_distinct_sender_list(pre: Alloc):
"""Get a list of distinct sender accounts."""
while True:
yield pre.fund_eoa()


def get_distinct_receiver_list(pre: Alloc):
"""Get a list of distinct receiver accounts."""
while True:
yield pre.fund_eoa(0)


def get_single_sender_list(pre: Alloc):
"""Get a list of single sender accounts."""
sender = pre.fund_eoa()
while True:
yield sender


def get_single_receiver_list(pre: Alloc):
"""Get a list of single receiver accounts."""
receiver = pre.fund_eoa(0)
while True:
yield receiver


@pytest.fixture
def ether_transfer_case(
case_id: str,
pre: Alloc,
):
"""Generate the test parameters based on the case ID."""
if case_id == "a_to_a":
"""Sending to self."""
senders = get_single_sender_list(pre)
receivers = senders

elif case_id == "a_to_b":
"""One sender → one receiver."""
senders = get_single_sender_list(pre)
receivers = get_single_receiver_list(pre)

elif case_id == "diff_acc_to_b":
"""Multiple senders → one receiver."""
senders = get_distinct_sender_list(pre)
receivers = get_single_receiver_list(pre)

elif case_id == "a_to_diff_acc":
"""One sender → multiple receivers."""
senders = get_single_sender_list(pre)
receivers = get_distinct_receiver_list(pre)

elif case_id == "diff_acc_to_diff_acc":
"""Multiple senders → multiple receivers."""
senders = get_distinct_sender_list(pre)
receivers = get_distinct_receiver_list(pre)

else:
raise ValueError(f"Unknown case: {case_id}")

return senders, receivers


@pytest.mark.valid_from("Cancun")
@pytest.mark.parametrize(
"case_id",
["a_to_a", "a_to_b", "diff_acc_to_b", "a_to_diff_acc", "diff_acc_to_diff_acc"],
)
def test_block_full_of_ether_transfers(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
case_id: str,
ether_transfer_case,
iteration_count: int,
transfer_amount: int,
eth_transfer_cost: int,
):
"""
Single test for ether transfer scenarios.

Scenarios:
- a_to_a: one sender → one sender
- a_to_b: one sender → one receiver
- diff_acc_to_b: multiple senders → one receiver
- a_to_diff_acc: one sender → multiple receivers
- diff_acc_to_diff_acc: multiple senders → multiple receivers
"""
senders, receivers = ether_transfer_case

# Create a single block with all transactions
txs = []
balances: dict[Address, int] = {}
for _ in range(iteration_count):
receiver = next(receivers)
balances[receiver] = balances.get(receiver, 0) + transfer_amount
txs.append(
Transaction(
to=receiver,
value=transfer_amount,
gas_limit=eth_transfer_cost,
sender=next(senders),
)
)

# Only include post state for non a_to_a cases
post_state = (
{}
if case_id == "a_to_a"
else {receiver: Account(balance=balance) for receiver, balance in balances.items()}
)

blockchain_test(
genesis_environment=Environment(),
pre=pre,
post=post_state,
blocks=[Block(txs=txs)],
exclude_full_post_state_in_output=True,
)
Loading