diff --git a/src/pytest_plugins/shared/execute_fill.py b/src/pytest_plugins/shared/execute_fill.py index 565771d29a4..cffb0f34659 100644 --- a/src/pytest_plugins/shared/execute_fill.py +++ b/src/pytest_plugins/shared/execute_fill.py @@ -158,6 +158,10 @@ def pytest_configure(config: pytest.Config): "markers", "valid_for_bpo_forks: Marks a test as valid for BPO forks", ) + config.addinivalue_line( + "markers", + "mainnet: Specialty tests crafted for running on mainnet and sanity checking.", + ) @pytest.fixture(scope="function") diff --git a/tests/prague/eip2537_bls_12_381_precompiles/conftest.py b/tests/prague/eip2537_bls_12_381_precompiles/conftest.py index a4780065df7..d8b2efe771a 100644 --- a/tests/prague/eip2537_bls_12_381_precompiles/conftest.py +++ b/tests/prague/eip2537_bls_12_381_precompiles/conftest.py @@ -162,7 +162,7 @@ def call_contract_address(pre: Alloc, call_contract_code: Bytecode) -> Address: @pytest.fixture def sender(pre: Alloc) -> EOA: """Sender of the transaction.""" - return pre.fund_eoa(1_000_000_000_000_000_000) + return pre.fund_eoa() @pytest.fixture diff --git a/tests/prague/eip2537_bls_12_381_precompiles/test_eip_mainnet.py b/tests/prague/eip2537_bls_12_381_precompiles/test_eip_mainnet.py new file mode 100644 index 00000000000..1f20576b76b --- /dev/null +++ b/tests/prague/eip2537_bls_12_381_precompiles/test_eip_mainnet.py @@ -0,0 +1,90 @@ +""" +abstract: Crafted tests for mainnet of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) + Crafted tests for mainnet of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" # noqa: E501 + +import pytest + +from ethereum_test_tools import Alloc, StateTestFiller, Transaction + +from .spec import FP, FP2, Scalar, Spec, ref_spec_2537 + +REFERENCE_SPEC_GIT_PATH = ref_spec_2537.git_path +REFERENCE_SPEC_VERSION = ref_spec_2537.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +@pytest.mark.parametrize( + "precompile_address,input_data,expected_output,vector_gas_value", + [ + pytest.param( + Spec.G1ADD, + Spec.G1 + Spec.INF_G1, + Spec.G1, + None, + id="G1ADD", + ), + pytest.param( + Spec.G1MSM, + Spec.G1 + Scalar(1) + Spec.INF_G1 + Scalar(1), + Spec.G1, + None, + id="G1MSM", + ), + pytest.param( + Spec.G2ADD, + Spec.G2 + Spec.INF_G2, + Spec.G2, + None, + id="G2ADD", + ), + pytest.param( + Spec.G2MSM, + Spec.G2 + Scalar(1) + Spec.INF_G2 + Scalar(1), + Spec.G2, + None, + id="G2MSM", + ), + pytest.param( + Spec.PAIRING, + Spec.G1 + Spec.INF_G2, + Spec.PAIRING_TRUE, + None, + id="PAIRING", + ), + pytest.param( + Spec.MAP_FP_TO_G1, + FP( + 799950832265136997107648781861994410980648980263584507133499364313075404851459407870655748616451882783569609925573 # noqa: E501 + ), + Spec.INF_G1, + None, + id="fp_map_to_inf", + ), + pytest.param( + Spec.MAP_FP2_TO_G2, + FP2( + ( + 3510328712861478240121438855244276237335901234329585006107499559909114695366216070652508985150831181717984778988906, # noqa: E501 + 2924545590598115509050131525615277284817672420174395176262156166974132393611647670391999011900253695923948997972401, # noqa: E501 + ) + ), + Spec.INF_G2, + None, + id="fp_map_to_inf", + ), + ], +) +def test_eip_2537( + state_test: StateTestFiller, + pre: Alloc, + post: dict, + tx: Transaction, +): + """Test the all precompiles of EIP-2537.""" + state_test( + pre=pre, + tx=tx, + post=post, + ) diff --git a/tests/prague/eip2935_historical_block_hashes_from_state/test_eip_mainnet.py b/tests/prague/eip2935_historical_block_hashes_from_state/test_eip_mainnet.py new file mode 100644 index 00000000000..60b2cd3bfae --- /dev/null +++ b/tests/prague/eip2935_historical_block_hashes_from_state/test_eip_mainnet.py @@ -0,0 +1,51 @@ +""" +abstract: Crafted tests for mainnet of [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935) + Crafted tests for mainnet of [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935). +""" # noqa: E501 + +import pytest + +from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction +from ethereum_test_tools import Opcodes as Op + +from .spec import Spec, ref_spec_2935 + +REFERENCE_SPEC_GIT_PATH = ref_spec_2935.git_path +REFERENCE_SPEC_VERSION = ref_spec_2935.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +def test_eip_2935( + blockchain_test: BlockchainTestFiller, + pre: Alloc, +): + """Test a simple block hash request from EIP-2935 system contract.""" + check_block_number = Op.SUB(Op.NUMBER, 1) # Parent block number + check_contract_code = ( + Op.MSTORE(0, check_block_number) + + Op.POP( + Op.CALL( + address=Spec.HISTORY_STORAGE_ADDRESS, + args_offset=0, + args_size=32, + ret_offset=32, + ret_size=32, + ) + ) + + Op.SSTORE(0, Op.EQ(Op.MLOAD(32), Op.BLOCKHASH(check_block_number))) + ) + check_contract_address = pre.deploy_contract(check_contract_code) + tx = Transaction( + to=check_contract_address, + gas_limit=50_000, + sender=pre.fund_eoa(), + ) + block = Block(txs=[tx]) + blockchain_test( + pre=pre, + blocks=[block], + post={ + check_contract_address: Account(storage={0: 1}), + }, + ) diff --git a/tests/prague/eip6110_deposits/test_eip_mainnet.py b/tests/prague/eip6110_deposits/test_eip_mainnet.py new file mode 100644 index 00000000000..852ba1d1751 --- /dev/null +++ b/tests/prague/eip6110_deposits/test_eip_mainnet.py @@ -0,0 +1,57 @@ +""" +abstract: Crafted tests for mainnet of [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110) + Crafted tests for mainnet of [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110). +""" # noqa: E501 + +from typing import List + +import pytest + +from ethereum_test_tools import ( + Alloc, + Block, + BlockchainTestFiller, +) + +from .helpers import DepositRequest, DepositTransaction +from .spec import ref_spec_6110 + +REFERENCE_SPEC_GIT_PATH = ref_spec_6110.git_path +REFERENCE_SPEC_VERSION = ref_spec_6110.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +@pytest.mark.parametrize( + "requests", + [ + pytest.param( + [ + DepositTransaction( + # TODO: Use a real public key to allow recovery of the funds. + requests=[ + DepositRequest( + pubkey=0x01, + withdrawal_credentials=0x02, + amount=1_000_000_000, + signature=0x03, + index=0x0, + ) + ], + ), + ], + id="single_deposit_from_eoa_minimum", + ), + ], +) +def test_eip_6110( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + blocks: List[Block], +): + """Test making a deposit to the beacon chain deposit contract.""" + blockchain_test( + pre=pre, + post={}, + blocks=blocks, + ) diff --git a/tests/prague/eip7002_el_triggerable_withdrawals/test_eip_mainnet.py b/tests/prague/eip7002_el_triggerable_withdrawals/test_eip_mainnet.py new file mode 100644 index 00000000000..b42d71ee74f --- /dev/null +++ b/tests/prague/eip7002_el_triggerable_withdrawals/test_eip_mainnet.py @@ -0,0 +1,56 @@ +""" +abstract: Crafted tests for mainnet of [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002) + Crafted tests for mainnet of [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). +""" # noqa: E501 + +from typing import List + +import pytest + +from ethereum_test_tools import ( + Alloc, + Block, + BlockchainTestFiller, +) + +from .helpers import WithdrawalRequest, WithdrawalRequestTransaction +from .spec import Spec, ref_spec_7002 + +REFERENCE_SPEC_GIT_PATH = ref_spec_7002.git_path +REFERENCE_SPEC_VERSION = ref_spec_7002.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +@pytest.mark.parametrize( + "blocks_withdrawal_requests", + [ + pytest.param( + [ + [ + WithdrawalRequestTransaction( + requests=[ + WithdrawalRequest( + validator_pubkey=0x01, + amount=0, + fee=Spec.get_fee(0), + ) + ], + ), + ], + ], + id="single_withdrawal_request", + ), + ], +) +def test_eip_7002( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + blocks: List[Block], +): + """Test making a withdrawal request.""" + blockchain_test( + pre=pre, + post={}, + blocks=blocks, + ) diff --git a/tests/prague/eip7251_consolidations/test_eip_mainnet.py b/tests/prague/eip7251_consolidations/test_eip_mainnet.py new file mode 100644 index 00000000000..1449dae6b15 --- /dev/null +++ b/tests/prague/eip7251_consolidations/test_eip_mainnet.py @@ -0,0 +1,56 @@ +""" +abstract: Crafted tests for mainnet of [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251) + Crafted tests for mainnet of [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). +""" # noqa: E501 + +from typing import List + +import pytest + +from ethereum_test_tools import ( + Alloc, + Block, + BlockchainTestFiller, +) + +from .helpers import ConsolidationRequest, ConsolidationRequestTransaction +from .spec import Spec, ref_spec_7251 + +REFERENCE_SPEC_GIT_PATH = ref_spec_7251.git_path +REFERENCE_SPEC_VERSION = ref_spec_7251.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +@pytest.mark.parametrize( + "blocks_consolidation_requests", + [ + pytest.param( + [ + [ + ConsolidationRequestTransaction( + requests=[ + ConsolidationRequest( + source_pubkey=0x01, + target_pubkey=0x02, + fee=Spec.get_fee(0), + ) + ], + ), + ], + ], + id="single_consolidation_request", + ), + ], +) +def test_eip_7251( + blockchain_test: BlockchainTestFiller, + blocks: List[Block], + pre: Alloc, +): + """Test making a consolidation request.""" + blockchain_test( + pre=pre, + post={}, + blocks=blocks, + ) diff --git a/tests/prague/eip7623_increase_calldata_cost/test_eip_mainnet.py b/tests/prague/eip7623_increase_calldata_cost/test_eip_mainnet.py new file mode 100644 index 00000000000..eccb88fac07 --- /dev/null +++ b/tests/prague/eip7623_increase_calldata_cost/test_eip_mainnet.py @@ -0,0 +1,106 @@ +""" +abstract: Crafted tests for mainnet of [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623) + Crafted tests for mainnet of [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). +""" # noqa: E501 + +import pytest + +from ethereum_test_tools import ( + AccessList, + Address, + Alloc, + Hash, + StateTestFiller, + Transaction, + add_kzg_version, +) + +from ...cancun.eip4844_blobs.spec import Spec as EIP_4844_Spec +from .helpers import DataTestType +from .spec import ref_spec_7623 + +REFERENCE_SPEC_GIT_PATH = ref_spec_7623.git_path +REFERENCE_SPEC_VERSION = ref_spec_7623.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +@pytest.mark.parametrize( + "ty,protected,access_list,blob_versioned_hashes,authorization_list", + [ + pytest.param(0, True, None, None, None, id="type_0_protected"), + pytest.param(0, False, None, None, None, id="type_0_unprotected"), + pytest.param( + 1, + True, + [AccessList(address=Address(1), storage_keys=[Hash(0)])], + None, + None, + id="type_1", + ), + pytest.param( + 2, + True, + [AccessList(address=Address(1), storage_keys=[Hash(0)])], + None, + None, + id="type_2", + ), + pytest.param( + 3, + True, + [AccessList(address=Address(1), storage_keys=[Hash(0)])], + add_kzg_version( + [Hash(x) for x in range(1)], + EIP_4844_Spec.BLOB_COMMITMENT_VERSION_KZG, + ), + None, + id="type_3", + marks=pytest.mark.execute( + pytest.mark.skip(reason="Blob txs not supported by execute") + ), + ), + pytest.param( + 4, + True, + [AccessList(address=Address(1), storage_keys=[Hash(0)])], + None, + [Address(1)], + id="type_4", + ), + ], + indirect=["authorization_list"], +) +@pytest.mark.parametrize( + "tx_gas_delta", + [ + pytest.param(0, id=""), + ], +) +@pytest.mark.parametrize( + "to", + [ + pytest.param("eoa", id=""), + ], + indirect=True, +) +@pytest.mark.parametrize( + "data_test_type", + [ + pytest.param( + DataTestType.FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS, + id="", + ), + ], +) +def test_eip_7623( + state_test: StateTestFiller, + pre: Alloc, + tx: Transaction, +) -> None: + """Test transaction validity for transactions without access lists and contract creation.""" + state_test( + pre=pre, + post={}, + tx=tx, + ) diff --git a/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py b/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py new file mode 100644 index 00000000000..1d415b3b5c5 --- /dev/null +++ b/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py @@ -0,0 +1,88 @@ +""" +abstract: Crafted tests for mainnet of [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) + Crafted tests for mainnet of [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). +""" # noqa: E501 + +import pytest + +from ethereum_test_forks import Fork +from ethereum_test_tools import ( + Account, + Alloc, + AuthorizationTuple, + StateTestFiller, + Storage, + Transaction, +) +from ethereum_test_tools import Opcodes as Op + +from .spec import Spec, ref_spec_7702 + +REFERENCE_SPEC_GIT_PATH = ref_spec_7702.git_path +REFERENCE_SPEC_VERSION = ref_spec_7702.version + +pytestmark = [pytest.mark.valid_at("Prague"), pytest.mark.mainnet] + + +def test_eip_7702( + state_test: StateTestFiller, + pre: Alloc, + fork: Fork, +): + """Test the executing a simple SSTORE in a set-code transaction.""" + storage = Storage() + sender = pre.fund_eoa() + auth_signer = sender + + tx_value = 1 + + set_code = ( + Op.SSTORE(storage.store_next(sender), Op.ORIGIN) + + Op.SSTORE(storage.store_next(sender), Op.CALLER) + + Op.SSTORE(storage.store_next(tx_value), Op.CALLVALUE) + + Op.STOP + ) + set_code_to_address = pre.deploy_contract( + set_code, + ) + authorization_list = [ + AuthorizationTuple( + address=set_code_to_address, + nonce=1, + signer=auth_signer, + ), + ] + gas_costs = fork.gas_costs() + intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_cost_calc( + access_list=[], + authorization_list_or_count=authorization_list, + ) + execution_cost = ( + (gas_costs.G_COLD_SLOAD + gas_costs.G_STORAGE_SET) * 3 + + (gas_costs.G_VERY_LOW * 3) + + (gas_costs.G_BASE * 3) + ) + + tx = Transaction( + gas_limit=intrinsic_gas_cost + execution_cost, + to=auth_signer, + value=tx_value, + authorization_list=authorization_list, + sender=sender, + ) + + state_test( + pre=pre, + tx=tx, + post={ + set_code_to_address: Account( + storage=dict.fromkeys(storage, 0), + ), + auth_signer: Account( + nonce=2, + code=Spec.delegation_designation(set_code_to_address), + storage=storage, + ), + }, + ) diff --git a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py index 254cb5f7dfd..ce9c8a35cad 100644 --- a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -263,9 +263,18 @@ def test_set_code_to_non_empty_storage_non_zero_nonce( ) +@pytest.mark.parametrize( + "access_list_in_tx", + [ + pytest.param(None, id=""), + pytest.param("sender", id="sender_in_access_list"), + pytest.param("auth_signer", id="auth_signer_in_access_list"), + ], +) def test_set_code_to_sstore_then_sload( blockchain_test: BlockchainTestFiller, pre: Alloc, + access_list_in_tx: str | None, ): """Test the executing a simple SSTORE then SLOAD in two separate set-code transactions.""" auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -295,6 +304,16 @@ def test_set_code_to_sstore_then_sload( sender=sender, ) + access_list = ( + [ + AccessList( + address=sender if access_list_in_tx == "sender" else auth_signer, + storage_keys=[Hash(storage_key_1)], + ) + ] + if access_list_in_tx + else [] + ) tx_2 = Transaction( gas_limit=100_000, to=auth_signer, @@ -306,6 +325,7 @@ def test_set_code_to_sstore_then_sload( signer=auth_signer, ), ], + access_list=access_list, sender=sender, )