@pytest.mark.parametrize(
"call_gas",
[
(Spec.POINT_EVALUATION_PRECOMPILE_GAS),
(Spec.POINT_EVALUATION_PRECOMPILE_GAS + 1),
(Spec.POINT_EVALUATION_PRECOMPILE_GAS - 1),
],
ids=["exact_gas", "extra_gas", "insufficient_gas"],
)
@pytest.mark.parametrize(
"z,y,kzg_commitment,kzg_proof,versioned_hash,proof_correct",
[
[Z, 0, INF_POINT, INF_POINT, None, True],
[Z, 1, INF_POINT, INF_POINT, None, False],
],
ids=["correct_proof", "incorrect_proof"],
)
@pytest.mark.valid_from("Cancun")
def test_tx_entry_point(
fork: Fork,
state_test: StateTestFiller,
precompile_input: bytes,
call_gas: int,
pre: Alloc,
proof_correct: bool,
) -> None:
"""
Test calling the Point Evaluation Precompile directly as transaction entry
point, and measure the gas consumption.
- Using `gas_limit` with exact necessary gas, insufficient gas and extra
gas.
- Using correct and incorrect proofs
"""
sender = pre.fund_eoa()
# Starting from EIP-7623, we need to use an access list to raise the
# intrinsic gas cost to be above the floor data cost.
access_list = [
AccessList(address=Address(i), storage_keys=[]) for i in range(1, 10)
]
# Gas is appended the intrinsic gas cost of the transaction
tx_intrinsic_gas_cost_calculator = (
fork.transaction_intrinsic_cost_calculator()
)
intrinsic_gas_cost = tx_intrinsic_gas_cost_calculator(
calldata=precompile_input, access_list=access_list
)
# Consumed gas will only be the precompile gas if the proof is correct and
# the call gas is sufficient.
# Otherwise, the call gas will be consumed in full.
precompile_gas = fork.gas_costs().PRECOMPILE_POINT_EVALUATION
consumed_gas = (
precompile_gas
if call_gas >= precompile_gas and proof_correct
else call_gas
) + tx_intrinsic_gas_cost_calculator(
calldata=precompile_input,
access_list=access_list,
return_cost_deducted_prior_execution=True,
)
tx = Transaction(
sender=sender,
data=precompile_input,
access_list=access_list,
to=Address(Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS),
gas_limit=call_gas + intrinsic_gas_cost,
expected_receipt=TransactionReceipt(cumulative_gas_used=consumed_gas),
)
post = {
sender: Account(
nonce=1,
)
}
state_test(
env=Environment(),
pre=pre,
post=post,
tx=tx,
)