diff --git a/docs/writing_tests/checklist_templates/eip_testing_checklist_template.md b/docs/writing_tests/checklist_templates/eip_testing_checklist_template.md index 7592707417d..c5c47184076 100644 --- a/docs/writing_tests/checklist_templates/eip_testing_checklist_template.md +++ b/docs/writing_tests/checklist_templates/eip_testing_checklist_template.md @@ -299,9 +299,6 @@ Opcode is used to attempt to recreate a contract that is currently mid-creation ### Framework Changes -| ID | Description | Status | Tests | -| --- | ----------- | ------ | ----- | - - Add opcode to `src/ethereum_test_vm/opcode.py` - Add opcode to relevant methods in the fork where the EIP is introduced in `src/ethereum_test_forks/forks/forks.py` @@ -403,6 +400,8 @@ If the precompile requires a minimum value (fee) to execute, either constant or If the precompile does not require any minimum value (fee) to execute. +| ID | Description | Status | Tests | +| ------------------------------------------------ | ----------------------------- | ------ | ----- | | `precompile/test/value_transfer/no_fee` | Sending non-zero value does not cause an exception (unless otherwise specified by the EIP). | | | #### Out-of-bounds checks @@ -868,6 +867,8 @@ Verify the transaction is correctly rejected if it contains an invalid signature Verify values or variables that are persistent through the execution of the transaction (e.g. transient storage, warm/cold accounts). +| ID | Description | Status | Tests | +| --------------------------------------------------------------------- | ----------------------------------------------| ------ | ----- | | `transaction_type/test/tx_scoped_attributes/persistent/throughout` | Persist throughout the entire transaction. | | | | `transaction_type/test/tx_scoped_attributes/persistent/reset` | Reset on subsequent transactions in the same block. | | | diff --git a/tests/benchmark/test_worst_compute.py b/tests/benchmark/test_worst_compute.py index 74361785ba8..312c8879635 100644 --- a/tests/benchmark/test_worst_compute.py +++ b/tests/benchmark/test_worst_compute.py @@ -1688,6 +1688,7 @@ def test_worst_modexp( p256verify_spec.Spec.Y0, ], id="p256verify", + marks=[pytest.mark.eip_checklist("precompile/test/excessive_gas_usage", eip=[7951])], ), ], ) 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 4fa6173c888..41fda5771d0 100644 --- a/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py +++ b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -7,6 +7,7 @@ import pytest +from ethereum_test_checklists import EIPChecklist from ethereum_test_forks import ( Fork, get_transition_fork_predecessor, @@ -70,6 +71,8 @@ def precompile_addresses_in_predecessor_successor( "address,precompile_in_successor,precompile_in_predecessor", precompile_addresses_in_predecessor_successor, ) +@EIPChecklist.Precompile.Test.ForkTransition.Before.Cold(eip=[7951]) +@EIPChecklist.Precompile.Test.ForkTransition.After.Warm(eip=[7951]) def test_precompile_warming( blockchain_test: BlockchainTestFiller, fork: Fork, diff --git a/tests/osaka/eip7951_p256verify_precompiles/eip_checklist_external_coverage.txt b/tests/osaka/eip7951_p256verify_precompiles/eip_checklist_external_coverage.txt new file mode 100644 index 00000000000..310efa85640 --- /dev/null +++ b/tests/osaka/eip7951_p256verify_precompiles/eip_checklist_external_coverage.txt @@ -0,0 +1,2 @@ +general/code_coverage/eels = Covered in EELS +general/code_coverage/test_coverage = Run locally \ No newline at end of file diff --git a/tests/osaka/eip7951_p256verify_precompiles/eip_checklist_not_applicable.txt b/tests/osaka/eip7951_p256verify_precompiles/eip_checklist_not_applicable.txt new file mode 100644 index 00000000000..173bbff6cb8 --- /dev/null +++ b/tests/osaka/eip7951_p256verify_precompiles/eip_checklist_not_applicable.txt @@ -0,0 +1,16 @@ +general/code_coverage/second_client = Optional +system_contract = EIP does not include a new system contract +opcode = EIP does not introduce a new opcode +removed_precompile = EIP does not remove a precompile +precompile/test/gas_usage/dynamic = EIP uses a constant amount of gas +precompile/test/input_lengths/dynamic = EIP input is a constant length +precompile/test/value_transfer/fee = EIP does not require a minimum value to execute +transaction_type = EIP does not introduce a new transaction type +block_header_field = EIP does not add any new block header fields +gas_cost_changes = EIP does not introduce any gas cost changes +gas_refunds_changes = EIP does not introduce any gas refund changes +blob_count_changes = EIP does not introduce any blob count changes +execution_layer_request = EIP does not introduce an execution layer request +new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint +modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint +block_body_field = EIP does not add any new block body fields \ No newline at end of file diff --git a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 97bc1b53a41..8c4f1cd5efa 100644 --- a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -5,7 +5,9 @@ import pytest +from ethereum_test_checklists import EIPChecklist from ethereum_test_tools import ( + Address, Alloc, Environment, StateTestFiller, @@ -33,8 +35,9 @@ # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) -@pytest.mark.eip_checklist("precompile/test/call_contexts/normal") -@pytest.mark.eip_checklist("precompile/test/inputs/valid") +@EIPChecklist.Precompile.Test.CallContexts.Normal() +@EIPChecklist.Precompile.Test.Inputs.Valid() +@EIPChecklist.Precompile.Test.Inputs.MaxValues() def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): """Test P256Verify precompile.""" state_test(env=Environment(), pre=pre, post=post, tx=tx) @@ -189,14 +192,16 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact ) @pytest.mark.parametrize("expected_output", [Spec.INVALID_RETURN_VALUE], ids=[""]) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) -@pytest.mark.eip_checklist("precompile/test/inputs/all_zeros") -@pytest.mark.eip_checklist("precompile/test/inputs/invalid") -@pytest.mark.eip_checklist("precompile/test/inputs/invalid/crypto") -@pytest.mark.eip_checklist("precompile/test/inputs/invalid/corrupted") -@pytest.mark.eip_checklist("precompile/test/input_lengths/zero") -@pytest.mark.eip_checklist("precompile/test/input_lengths/static/correct") -@pytest.mark.eip_checklist("precompile/test/input_lengths/static/too_short") -@pytest.mark.eip_checklist("precompile/test/input_lengths/static/too_long") +@EIPChecklist.Precompile.Test.Inputs.AllZeros() +@EIPChecklist.Precompile.Test.Inputs.Invalid() +@EIPChecklist.Precompile.Test.Inputs.Invalid.Crypto() +@EIPChecklist.Precompile.Test.Inputs.Invalid.Corrupted() +@EIPChecklist.Precompile.Test.InputLengths.Zero() +@EIPChecklist.Precompile.Test.InputLengths.Static.Correct() +@EIPChecklist.Precompile.Test.InputLengths.Static.TooShort() +@EIPChecklist.Precompile.Test.InputLengths.Static.TooLong() +@EIPChecklist.Precompile.Test.OutOfBounds.Max() +@EIPChecklist.Precompile.Test.OutOfBounds.MaxPlusOne() def test_invalid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): """Negative tests for the P256VERIFY precompile.""" state_test(env=Environment(), pre=pre, post=post, tx=tx) @@ -236,8 +241,8 @@ def test_invalid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transa ], ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) -@pytest.mark.eip_checklist("precompile/test/gas_usage/constant/exact") -@pytest.mark.eip_checklist("precompile/test/gas_usage/constant/oog") +@EIPChecklist.Precompile.Test.GasUsage.Constant.Exact() +@EIPChecklist.Precompile.Test.GasUsage.Constant.Oog() def test_gas(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): """Test P256Verify precompile gas requirements.""" state_test(env=Environment(), pre=pre, post=post, tx=tx) @@ -262,9 +267,9 @@ def test_gas(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transactio ], ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) -@pytest.mark.eip_checklist("precompile/test/call_contexts/delegate") -@pytest.mark.eip_checklist("precompile/test/call_contexts/static") -@pytest.mark.eip_checklist("precompile/test/call_contexts/callcode") +@EIPChecklist.Precompile.Test.CallContexts.Delegate() +@EIPChecklist.Precompile.Test.CallContexts.Static() +@EIPChecklist.Precompile.Test.CallContexts.Callcode() def test_call_types( state_test: StateTestFiller, pre: Alloc, @@ -286,7 +291,7 @@ def test_call_types( ), ], ) -@pytest.mark.eip_checklist("precompile/test/call_contexts/tx_entry") +@EIPChecklist.Precompile.Test.CallContexts.TxEntry() def test_precompile_as_tx_entry_point( state_test: StateTestFiller, pre: Alloc, @@ -297,6 +302,58 @@ def test_precompile_as_tx_entry_point( state_test(env=Environment(), pre=pre, post=post, tx=tx) +@pytest.mark.parametrize( + "input_data,precompile_address,expected_output", + [ + pytest.param( + Spec.H0 + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + Spec.P256VERIFY, + Spec.SUCCESS_RETURN_VALUE, + id="valid_input_with_value_transfer", + ), + ], +) +@EIPChecklist.Precompile.Test.ValueTransfer.NoFee() +def test_precompile_will_return_success_with_tx_value( + state_test: StateTestFiller, + pre: Alloc, + input_data: bytes, + expected_output: bytes, + precompile_address: Address, +): + """Test P256Verify precompile will not fail if value is sent.""" + sender = pre.fund_eoa() + storage = Storage() + + call_256verify_bytecode = ( + Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) + + Op.CALL( + gas=Spec.P256VERIFY_GAS, + address=Spec.P256VERIFY, + value=Op.CALLVALUE(), + args_offset=0, + args_size=Op.CALLDATASIZE(), + ret_offset=0, + ret_size=32, + ) + + Op.SSTORE(storage.store_next(True), Op.DUP1()) + + Op.SSTORE(storage.store_next(expected_output), Op.MLOAD(0)) + + Op.SSTORE(storage.store_next(len(expected_output)), Op.RETURNDATASIZE()) + + Op.STOP + ) + + contract_address = pre.deploy_contract(call_256verify_bytecode) + tx = Transaction( + sender=sender, + gas_limit=1000000, + to=contract_address, + value=1000, + data=input_data, + ) + post = {contract_address: {"storage": storage}} + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + @pytest.mark.parametrize( "input_data,expected_output", [ @@ -334,8 +391,8 @@ def test_precompile_as_tx_entry_point( ], ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) -@pytest.mark.eip_checklist("precompile/test/inputs/valid") -@pytest.mark.eip_checklist("precompile/test/inputs/invalid/crypto") +@EIPChecklist.Precompile.Test.Inputs.Valid() +@EIPChecklist.Precompile.Test.Inputs.Invalid.Crypto() def test_modular_comparison(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): """ Test the modular comparison condition for secp256r1 precompile. @@ -363,10 +420,10 @@ def test_modular_comparison(state_test: StateTestFiller, pre: Alloc, post: dict, ], ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) +@EIPChecklist.Precompile.Test.CallContexts.Initcode.Tx() def test_contract_creation_transaction( state_test: StateTestFiller, pre: Alloc, - post: dict, tx: Transaction, input_data: bytes, expected_output: bytes, @@ -426,10 +483,10 @@ def test_contract_creation_transaction( ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) @pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2]) +@EIPChecklist.Precompile.Test.CallContexts.Initcode.CREATE() def test_contract_initcode( state_test: StateTestFiller, pre: Alloc, - post: dict, tx: Transaction, input_data: bytes, expected_output: bytes, diff --git a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py index 0278e80ef48..b331b55c369 100644 --- a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py +++ b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py @@ -6,6 +6,7 @@ import pytest +from ethereum_test_checklists import EIPChecklist from ethereum_test_tools import Alloc, Block, BlockchainTestFiller, Transaction from .spec import Spec, ref_spec_7951 @@ -17,19 +18,34 @@ @pytest.mark.parametrize( - "precompile_address,input_data", + "precompile_address,input_data,precompile_gas_modifier", [ pytest.param( Spec.P256VERIFY, Spec.H0 + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, - id="P256VERIFY", + 0, + id="P256VERIFY_valid_input_6900_gas", + ), + pytest.param( + Spec.P256VERIFY, + Spec.H0 + Spec.R0 + Spec.S0 + Spec.X0 + Spec.X0, + 0, + id="P256VERIFY_invalid_input", + ), + pytest.param( + Spec.P256VERIFY, + Spec.H0 + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + -6900, + id="P256VERIFY_valid_input_zero_gas", ), ], ) @pytest.mark.parametrize( - "expected_output,call_succeeds", [pytest.param(b"", True, id=pytest.HIDDEN_PARAM)] + "expected_output,call_succeeds", + [pytest.param(Spec.INVALID_RETURN_VALUE, True, id=pytest.HIDDEN_PARAM)], ) -@pytest.mark.eip_checklist("precompile/test/fork_transition/before/invalid_input") +@EIPChecklist.Precompile.Test.ForkTransition.Before.InvalidInput() +@EIPChecklist.Precompile.Test.ForkTransition.Before.ZeroGas() def test_precompile_before_fork( blockchain_test: BlockchainTestFiller, pre: Alloc, 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..c8d382cb9a7 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 @@ -11,6 +11,7 @@ import pytest from ethereum_test_base_types import HexNumber +from ethereum_test_checklists import EIPChecklist from ethereum_test_forks import Fork from ethereum_test_tools import ( AccessList, @@ -2588,7 +2589,7 @@ def test_set_code_to_log( @pytest.mark.with_all_call_opcodes @pytest.mark.with_all_precompiles -@pytest.mark.eip_checklist("precompile/test/call_contexts/set_code", eips=[7951, 7883]) +@EIPChecklist.Precompile.Test.CallContexts.SetCode(eip=[7951, 7883]) def test_set_code_to_precompile( state_test: StateTestFiller, pre: Alloc,