Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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. | | |

Expand Down
1 change: 1 addition & 0 deletions tests/benchmark/test_worst_compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])],
),
],
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import pytest

from ethereum_test_checklists import EIPChecklist
from ethereum_test_forks import (
Fork,
get_transition_fork_predecessor,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
general/code_coverage/eels = Covered in EELS
general/code_coverage/test_coverage = Run locally
Original file line number Diff line number Diff line change
@@ -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
97 changes: 77 additions & 20 deletions tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

import pytest

from ethereum_test_checklists import EIPChecklist
from ethereum_test_tools import (
Address,
Alloc,
Environment,
StateTestFiller,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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",
[
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion tests/prague/eip7702_set_code_tx/test_set_code_txs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Loading