From f0c9213faa7dd1ca6aea033a6788dd8db8c87ba5 Mon Sep 17 00:00:00 2001 From: danceratopz Date: Fri, 25 Apr 2025 13:52:49 +0200 Subject: [PATCH 1/7] feat(tests): verify precompile eip-2929 address warming --- .../frontier/precompiles/test_precompiles.py | 112 +++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/tests/frontier/precompiles/test_precompiles.py b/tests/frontier/precompiles/test_precompiles.py index 9a016b87729..dfbcccc82c0 100644 --- a/tests/frontier/precompiles/test_precompiles.py +++ b/tests/frontier/precompiles/test_precompiles.py @@ -4,10 +4,16 @@ import pytest -from ethereum_test_forks import Fork +from ethereum_test_forks import ( + Fork, + get_transition_fork_predecessor, + get_transition_fork_successor, +) from ethereum_test_tools import ( Account, Alloc, + Block, + BlockchainTestFiller, Environment, StateTestFiller, Transaction, @@ -109,3 +115,107 @@ def test_precompiles( post = {account: Account(storage={0: "0x00" if precompile_exists else "0x01"})} state_test(env=env, pre=pre, post=post, tx=tx) + + +def precompile_addresses_in_successor(fork: Fork) -> Iterator[Tuple[str, bool]]: + """ + Yield the addresses of precompiled contracts and whether they existed in the parent fork. + + Args: + fork (Fork): The transition fork instance containing precompiled contract information. + + Yields: + Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a + boolean indicating whether the address has existed in the predecessor. + + """ + predecessor_precompiles = [ + hex(int.from_bytes(address, byteorder="big")) + for address in get_transition_fork_predecessor(fork).precompiles() + ] + successor_precompiles = [ + hex(int.from_bytes(address, byteorder="big")) + for address in get_transition_fork_successor(fork).precompiles() + ] + for address in successor_precompiles: + if address in predecessor_precompiles: + yield address, True + else: + yield address, False + + +@pytest.mark.valid_at_transition_to("Paris", subsequent_forks=True) +@pytest.mark.parametrize_by_fork( + "address,exists_in_predecessor", precompile_addresses_in_successor +) +def test_precompile_warming( + blockchain_test: BlockchainTestFiller, address: str, exists_in_predecessor: bool, pre: Alloc +): + """ + Call BALANCE of a precompile addresses before and after a fork. + + According to EIP-2929, when a transaction begins, accessed_addresses is initialized to include: + - tx.sender, tx.to + - and the set of all precompiles + + This test verifies that: + 1. Precompiles that exist in the predecessor fork are always "warm" (lower gas cost) + 2. New precompiles added in a fork are "cold" before the fork and become "warm" after + + """ + sender = pre.fund_eoa() + call_cost_slot = 0 + + code = ( + Op.GAS + + Op.BALANCE(address) + + Op.POP + + Op.SSTORE(call_cost_slot, Op.SUB(Op.SWAP1, Op.GAS)) + + Op.STOP + ) + before = pre.deploy_contract(code, storage={0: 0xDEADBEEF}) + after = pre.deploy_contract(code, storage={0: 0xDEADBEEF}) + + # Block before fork + blocks = [ + Block( + timestamp=10000, + txs=[ + Transaction( + sender=sender, + to=before, + gas_limit=1_000_000, + ) + ], + ) + ] + + # Block after fork + blocks += [ + Block( + timestamp=20000, + txs=[ + Transaction( + sender=sender, + to=after, + gas_limit=1_000_000, + ) + ], + ) + ] + + if not exists_in_predecessor: + expected_gas_before = 2607 + else: + expected_gas_before = 107 + + post = { + before: Account(storage={call_cost_slot: expected_gas_before}), + after: Account(storage={call_cost_slot: 107}), + } + + blockchain_test( + pre=pre, + post=post, + blocks=blocks, + ) From 6d099bb4bd40cffb45c3649458fc49b77316c303 Mon Sep 17 00:00:00 2001 From: danceratopz Date: Fri, 25 Apr 2025 13:53:25 +0200 Subject: [PATCH 2/7] fix(consume): update old misnamed transition fork ruleset This seemed to be previously unused. --- src/pytest_plugins/consume/hive_simulators/ruleset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest_plugins/consume/hive_simulators/ruleset.py b/src/pytest_plugins/consume/hive_simulators/ruleset.py index d5920946643..0d60a44e136 100644 --- a/src/pytest_plugins/consume/hive_simulators/ruleset.py +++ b/src/pytest_plugins/consume/hive_simulators/ruleset.py @@ -302,7 +302,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_TERMINAL_TOTAL_DIFFICULTY": 0, "HIVE_SHANGHAI_TIMESTAMP": 0, }, - "MergeToShanghaiAtTime15k": { + "ParisToShanghaiAtTime15k": { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, From 1a4f6e922de6be67b267d71ed4f8f5b357ab8e88 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Tue, 29 Apr 2025 05:41:44 -0600 Subject: [PATCH 3/7] fix: review comments (#1504) --- .../frontier/precompiles/test_precompiles.py | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/tests/frontier/precompiles/test_precompiles.py b/tests/frontier/precompiles/test_precompiles.py index dfbcccc82c0..f4032bfac8c 100644 --- a/tests/frontier/precompiles/test_precompiles.py +++ b/tests/frontier/precompiles/test_precompiles.py @@ -11,6 +11,7 @@ ) from ethereum_test_tools import ( Account, + Address, Alloc, Block, BlockchainTestFiller, @@ -117,7 +118,7 @@ def test_precompiles( state_test(env=env, pre=pre, post=post, tx=tx) -def precompile_addresses_in_successor(fork: Fork) -> Iterator[Tuple[str, bool]]: +def precompile_addresses_in_predecessor_successor(fork: Fork) -> Iterator[Tuple[Address, bool]]: """ Yield the addresses of precompiled contracts and whether they existed in the parent fork. @@ -129,27 +130,31 @@ def precompile_addresses_in_successor(fork: Fork) -> Iterator[Tuple[str, bool]]: boolean indicating whether the address has existed in the predecessor. """ - predecessor_precompiles = [ - hex(int.from_bytes(address, byteorder="big")) - for address in get_transition_fork_predecessor(fork).precompiles() - ] - successor_precompiles = [ - hex(int.from_bytes(address, byteorder="big")) - for address in get_transition_fork_successor(fork).precompiles() - ] - for address in successor_precompiles: - if address in predecessor_precompiles: - yield address, True - else: - yield address, False + predecessor_precompiles = set(get_transition_fork_predecessor(fork).precompiles()) + successor_precompiles = set(get_transition_fork_successor(fork).precompiles()) + all_precompiles = successor_precompiles | predecessor_precompiles + highest_precompile = int.from_bytes(max(all_precompiles)) + extra_range = 5 + extra_precompiles = { + Address(i) for i in range(highest_precompile + 1, highest_precompile + extra_range) + } + all_precompiles = all_precompiles | extra_precompiles + for address in sorted(all_precompiles): + yield address, address in successor_precompiles, address in predecessor_precompiles @pytest.mark.valid_at_transition_to("Paris", subsequent_forks=True) @pytest.mark.parametrize_by_fork( - "address,exists_in_predecessor", precompile_addresses_in_successor + "address,precompile_in_successor,precompile_in_predecessor", + precompile_addresses_in_predecessor_successor, ) def test_precompile_warming( - blockchain_test: BlockchainTestFiller, address: str, exists_in_predecessor: bool, pre: Alloc + blockchain_test: BlockchainTestFiller, + fork: Fork, + address: Address, + precompile_in_successor: bool, + precompile_in_predecessor: bool, + pre: Alloc, ): """ Call BALANCE of a precompile addresses before and after a fork. @@ -179,7 +184,7 @@ def test_precompile_warming( # Block before fork blocks = [ Block( - timestamp=10000, + timestamp=10_000, txs=[ Transaction( sender=sender, @@ -193,7 +198,7 @@ def test_precompile_warming( # Block after fork blocks += [ Block( - timestamp=20000, + timestamp=20_000, txs=[ Transaction( sender=sender, @@ -204,14 +209,25 @@ def test_precompile_warming( ) ] - if not exists_in_predecessor: - expected_gas_before = 2607 - else: - expected_gas_before = 107 + predecessor = get_transition_fork_predecessor(fork) + successor = get_transition_fork_successor(fork) + + def get_expected_gas(precompile_present: bool, fork: Fork) -> int: + gas_costs = fork.gas_costs() + warm_access_cost = gas_costs.G_WARM_ACCOUNT_ACCESS + cold_access_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + extra_cost = gas_costs.G_BASE * 2 + gas_costs.G_VERY_LOW + if precompile_present: + return warm_access_cost + extra_cost + else: + return cold_access_cost + extra_cost + + expected_gas_before = get_expected_gas(precompile_in_predecessor, predecessor) + expected_gas_after = get_expected_gas(precompile_in_successor, successor) post = { before: Account(storage={call_cost_slot: expected_gas_before}), - after: Account(storage={call_cost_slot: 107}), + after: Account(storage={call_cost_slot: expected_gas_after}), } blockchain_test( From 2fe06b1c1dd23b1137576aea861e1b9748d70b92 Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 29 Apr 2025 12:44:06 +0100 Subject: [PATCH 4/7] Update tests/frontier/precompiles/test_precompiles.py Co-authored-by: Mario Vega --- tests/frontier/precompiles/test_precompiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/frontier/precompiles/test_precompiles.py b/tests/frontier/precompiles/test_precompiles.py index f4032bfac8c..1f44064a232 100644 --- a/tests/frontier/precompiles/test_precompiles.py +++ b/tests/frontier/precompiles/test_precompiles.py @@ -178,8 +178,8 @@ def test_precompile_warming( + Op.SSTORE(call_cost_slot, Op.SUB(Op.SWAP1, Op.GAS)) + Op.STOP ) - before = pre.deploy_contract(code, storage={0: 0xDEADBEEF}) - after = pre.deploy_contract(code, storage={0: 0xDEADBEEF}) + before = pre.deploy_contract(code, storage={call_cost_slot: 0xDEADBEEF}) + after = pre.deploy_contract(code, storage={call_cost_slot: 0xDEADBEEF}) # Block before fork blocks = [ From a76d5069cb9f5c56fa2c35345ed17d8ec38f0184 Mon Sep 17 00:00:00 2001 From: spencer-tb Date: Tue, 29 Apr 2025 12:51:10 +0100 Subject: [PATCH 5/7] chore(docs): add changelog. --- docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d3ed838b165..6399eacb5aa 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -33,6 +33,7 @@ Users can expect that all tests currently living in [ethereum/tests](https://git - ✨ [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702): Test that DELEGATECALL to a 7702 target works as intended ([#1485](https://github.com/ethereum/execution-spec-tests/pull/1485)). - ✨ [EIP-2573](https://eips.ethereum.org/EIPS/eip-2537): Includes a BLS12 point generator, alongside additional coverage many of the precompiles ([#1350](https://github.com/ethereum/execution-spec-tests/pull/1350)). - ✨ Add all [`GeneralStateTests` from `ethereum/tests`](https://github.com/ethereum/tests/tree/7dc757ec132e372b6178a016b91f4c639f366c02/src/GeneralStateTestsFiller) to `execution-spec-tests` located now at [tests/static/state_tests](https://github.com/ethereum/execution-spec-tests/tree/main/tests/static/state_tests) ([#1442](https://github.com/ethereum/execution-spec-tests/pull/1442)). +- ✨ [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929): Test that precompile addresses are cold/warm depending on the fork they are activated ([#1495](https://github.com/ethereum/execution-spec-tests/pull/1495)). ## [v4.3.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.3.0) - 2025-04-18 From c439d2624734e9c4216a99d9c268027924307718 Mon Sep 17 00:00:00 2001 From: spencer-tb Date: Tue, 29 Apr 2025 13:13:56 +0100 Subject: [PATCH 6/7] chore: move to berlin, fix typecheck. --- .../eip2929_gas_cost_increases/__init__.py | 4 + .../test_precompile_warming.py | 147 ++++++++++++++++++ .../frontier/precompiles/test_precompiles.py | 124 --------------- 3 files changed, 151 insertions(+), 124 deletions(-) create mode 100644 tests/berlin/eip2929_gas_cost_increases/__init__.py create mode 100644 tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py diff --git a/tests/berlin/eip2929_gas_cost_increases/__init__.py b/tests/berlin/eip2929_gas_cost_increases/__init__.py new file mode 100644 index 00000000000..9646b2063ca --- /dev/null +++ b/tests/berlin/eip2929_gas_cost_increases/__init__.py @@ -0,0 +1,4 @@ +""" +abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929) + Test cases for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929). +""" # noqa: E501 diff --git a/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py new file mode 100644 index 00000000000..58886c6d017 --- /dev/null +++ b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -0,0 +1,147 @@ +""" +abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929) + Test cases for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929). +""" # noqa: E501 + +from typing import Iterator, Tuple + +import pytest + +from ethereum_test_forks import ( + Fork, + get_transition_fork_predecessor, + get_transition_fork_successor, +) +from ethereum_test_tools import ( + Account, + Address, + Alloc, + Block, + BlockchainTestFiller, + Transaction, +) +from ethereum_test_tools.vm.opcode import Opcodes as Op + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-2929.md" +REFERENCE_SPEC_VERSION = "0e11417265a623adb680c527b15d0cb6701b870b" + + +def precompile_addresses_in_predecessor_successor( + fork: Fork, +) -> Iterator[Tuple[Address, bool, bool]]: + """ + Yield the addresses of precompiled contracts and whether they existed in the parent fork. + + Args: + fork (Fork): The transition fork instance containing precompiled contract information. + + Yields: + Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a + boolean indicating whether the address has existed in the predecessor. + + """ + predecessor_precompiles = set(get_transition_fork_predecessor(fork).precompiles()) + successor_precompiles = set(get_transition_fork_successor(fork).precompiles()) + all_precompiles = successor_precompiles | predecessor_precompiles + highest_precompile = int.from_bytes(max(all_precompiles)) + extra_range = 5 + extra_precompiles = { + Address(i) for i in range(highest_precompile + 1, highest_precompile + extra_range) + } + all_precompiles = all_precompiles | extra_precompiles + for address in sorted(all_precompiles): + yield address, address in successor_precompiles, address in predecessor_precompiles + + +@pytest.mark.valid_at_transition_to("Paris", subsequent_forks=True) +@pytest.mark.parametrize_by_fork( + "address,precompile_in_successor,precompile_in_predecessor", + precompile_addresses_in_predecessor_successor, +) +def test_precompile_warming( + blockchain_test: BlockchainTestFiller, + fork: Fork, + address: Address, + precompile_in_successor: bool, + precompile_in_predecessor: bool, + pre: Alloc, +): + """ + Call BALANCE of a precompile addresses before and after a fork. + + According to EIP-2929, when a transaction begins, accessed_addresses is initialized to include: + - tx.sender, tx.to + - and the set of all precompiles + + This test verifies that: + 1. Precompiles that exist in the predecessor fork are always "warm" (lower gas cost) + 2. New precompiles added in a fork are "cold" before the fork and become "warm" after + + """ + sender = pre.fund_eoa() + call_cost_slot = 0 + + code = ( + Op.GAS + + Op.BALANCE(address) + + Op.POP + + Op.SSTORE(call_cost_slot, Op.SUB(Op.SWAP1, Op.GAS)) + + Op.STOP + ) + before = pre.deploy_contract(code, storage={call_cost_slot: 0xDEADBEEF}) + after = pre.deploy_contract(code, storage={call_cost_slot: 0xDEADBEEF}) + + # Block before fork + blocks = [ + Block( + timestamp=10_000, + txs=[ + Transaction( + sender=sender, + to=before, + gas_limit=1_000_000, + ) + ], + ) + ] + + # Block after fork + blocks += [ + Block( + timestamp=20_000, + txs=[ + Transaction( + sender=sender, + to=after, + gas_limit=1_000_000, + ) + ], + ) + ] + + predecessor = get_transition_fork_predecessor(fork) + successor = get_transition_fork_successor(fork) + + def get_expected_gas(precompile_present: bool, fork: Fork) -> int: + gas_costs = fork.gas_costs() + warm_access_cost = gas_costs.G_WARM_ACCOUNT_ACCESS + cold_access_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + extra_cost = gas_costs.G_BASE * 2 + gas_costs.G_VERY_LOW + if precompile_present: + return warm_access_cost + extra_cost + else: + return cold_access_cost + extra_cost + + expected_gas_before = get_expected_gas(precompile_in_predecessor, predecessor) + expected_gas_after = get_expected_gas(precompile_in_successor, successor) + + post = { + before: Account(storage={call_cost_slot: expected_gas_before}), + after: Account(storage={call_cost_slot: expected_gas_after}), + } + + blockchain_test( + pre=pre, + post=post, + blocks=blocks, + ) diff --git a/tests/frontier/precompiles/test_precompiles.py b/tests/frontier/precompiles/test_precompiles.py index 1f44064a232..c3d8ad44e4f 100644 --- a/tests/frontier/precompiles/test_precompiles.py +++ b/tests/frontier/precompiles/test_precompiles.py @@ -6,15 +6,10 @@ from ethereum_test_forks import ( Fork, - get_transition_fork_predecessor, - get_transition_fork_successor, ) from ethereum_test_tools import ( Account, - Address, Alloc, - Block, - BlockchainTestFiller, Environment, StateTestFiller, Transaction, @@ -116,122 +111,3 @@ def test_precompiles( post = {account: Account(storage={0: "0x00" if precompile_exists else "0x01"})} state_test(env=env, pre=pre, post=post, tx=tx) - - -def precompile_addresses_in_predecessor_successor(fork: Fork) -> Iterator[Tuple[Address, bool]]: - """ - Yield the addresses of precompiled contracts and whether they existed in the parent fork. - - Args: - fork (Fork): The transition fork instance containing precompiled contract information. - - Yields: - Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a - boolean indicating whether the address has existed in the predecessor. - - """ - predecessor_precompiles = set(get_transition_fork_predecessor(fork).precompiles()) - successor_precompiles = set(get_transition_fork_successor(fork).precompiles()) - all_precompiles = successor_precompiles | predecessor_precompiles - highest_precompile = int.from_bytes(max(all_precompiles)) - extra_range = 5 - extra_precompiles = { - Address(i) for i in range(highest_precompile + 1, highest_precompile + extra_range) - } - all_precompiles = all_precompiles | extra_precompiles - for address in sorted(all_precompiles): - yield address, address in successor_precompiles, address in predecessor_precompiles - - -@pytest.mark.valid_at_transition_to("Paris", subsequent_forks=True) -@pytest.mark.parametrize_by_fork( - "address,precompile_in_successor,precompile_in_predecessor", - precompile_addresses_in_predecessor_successor, -) -def test_precompile_warming( - blockchain_test: BlockchainTestFiller, - fork: Fork, - address: Address, - precompile_in_successor: bool, - precompile_in_predecessor: bool, - pre: Alloc, -): - """ - Call BALANCE of a precompile addresses before and after a fork. - - According to EIP-2929, when a transaction begins, accessed_addresses is initialized to include: - - tx.sender, tx.to - - and the set of all precompiles - - This test verifies that: - 1. Precompiles that exist in the predecessor fork are always "warm" (lower gas cost) - 2. New precompiles added in a fork are "cold" before the fork and become "warm" after - - """ - sender = pre.fund_eoa() - call_cost_slot = 0 - - code = ( - Op.GAS - + Op.BALANCE(address) - + Op.POP - + Op.SSTORE(call_cost_slot, Op.SUB(Op.SWAP1, Op.GAS)) - + Op.STOP - ) - before = pre.deploy_contract(code, storage={call_cost_slot: 0xDEADBEEF}) - after = pre.deploy_contract(code, storage={call_cost_slot: 0xDEADBEEF}) - - # Block before fork - blocks = [ - Block( - timestamp=10_000, - txs=[ - Transaction( - sender=sender, - to=before, - gas_limit=1_000_000, - ) - ], - ) - ] - - # Block after fork - blocks += [ - Block( - timestamp=20_000, - txs=[ - Transaction( - sender=sender, - to=after, - gas_limit=1_000_000, - ) - ], - ) - ] - - predecessor = get_transition_fork_predecessor(fork) - successor = get_transition_fork_successor(fork) - - def get_expected_gas(precompile_present: bool, fork: Fork) -> int: - gas_costs = fork.gas_costs() - warm_access_cost = gas_costs.G_WARM_ACCOUNT_ACCESS - cold_access_cost = gas_costs.G_COLD_ACCOUNT_ACCESS - extra_cost = gas_costs.G_BASE * 2 + gas_costs.G_VERY_LOW - if precompile_present: - return warm_access_cost + extra_cost - else: - return cold_access_cost + extra_cost - - expected_gas_before = get_expected_gas(precompile_in_predecessor, predecessor) - expected_gas_after = get_expected_gas(precompile_in_successor, successor) - - post = { - before: Account(storage={call_cost_slot: expected_gas_before}), - after: Account(storage={call_cost_slot: expected_gas_after}), - } - - blockchain_test( - pre=pre, - post=post, - blocks=blocks, - ) From 02dcc4636a2d2ad45b2749d9de99cd26189ee746 Mon Sep 17 00:00:00 2001 From: spencer-tb Date: Tue, 29 Apr 2025 13:46:59 +0100 Subject: [PATCH 7/7] chore(tests): increase precompile extra range. --- .../eip2929_gas_cost_increases/test_precompile_warming.py | 2 +- tests/frontier/precompiles/test_precompiles.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py index 58886c6d017..49c83853b26 100644 --- a/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py +++ b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -44,7 +44,7 @@ def precompile_addresses_in_predecessor_successor( successor_precompiles = set(get_transition_fork_successor(fork).precompiles()) all_precompiles = successor_precompiles | predecessor_precompiles highest_precompile = int.from_bytes(max(all_precompiles)) - extra_range = 5 + extra_range = 32 extra_precompiles = { Address(i) for i in range(highest_precompile + 1, highest_precompile + extra_range) } diff --git a/tests/frontier/precompiles/test_precompiles.py b/tests/frontier/precompiles/test_precompiles.py index c3d8ad44e4f..9a016b87729 100644 --- a/tests/frontier/precompiles/test_precompiles.py +++ b/tests/frontier/precompiles/test_precompiles.py @@ -4,9 +4,7 @@ import pytest -from ethereum_test_forks import ( - Fork, -) +from ethereum_test_forks import Fork from ethereum_test_tools import ( Account, Alloc,