@pytest.mark.valid_from("Byzantium")
@pytest.mark.parametrize(
"input_data",
[
pytest.param(
PointG1(1, 3) + Spec.G2,
id="invalid_g1_point",
),
],
)
@pytest.mark.parametrize(
"extra_gas",
[
pytest.param(0, id="exact"),
pytest.param(100_000, id="extra_100k"),
],
)
def test_invalid_gas_consumption(
state_test: StateTestFiller,
pre: Alloc,
fork: Fork,
precompile_gas: int,
input_data: bytes,
extra_gas: int,
) -> None:
"""
Test that invalid input to ecpairing consumes all forwarded gas.
Use CodeGasMeasure to verify the STATICCALL with invalid input
consumes exactly the warm call cost plus all forwarded gas.
"""
gas_forward = precompile_gas + extra_gas
input_size = len(input_data)
storage = Storage()
staticcall_code = Op.STATICCALL(
gas=gas_forward,
address=Spec.ECPAIRING,
args_size=input_size,
)
push_cost = staticcall_code.gas_cost(fork) - Op.STATICCALL(
address_warm=False
).gas_cost(fork)
# Precompiles are warm from Berlin, flat call cost before.
staticcall_base = Op.STATICCALL(address_warm=True).gas_cost(fork)
account = pre.deploy_contract(
code=(
Om.MSTORE(input_data)
# Warm the precompile address
+ Op.POP(Op.STATICCALL(gas=0, address=Spec.ECPAIRING))
+ CodeGasMeasure(
code=staticcall_code,
overhead_cost=push_cost,
extra_stack_items=1,
sstore_key=storage.store_next(staticcall_base + gas_forward),
)
),
storage=storage.canary(),
)
tx = Transaction(
to=account,
sender=pre.fund_eoa(),
gas_limit=1_000_000,
protected=True,
)
post = {account: Account(storage=storage)}
state_test(pre=pre, post=post, tx=tx)