@pytest.mark.xdist_group(name="bigmem")
@pytest.mark.parametrize(
"contract_code,expected_storage",
[
# Use PUSH0 to set a key for SSTORE.
pytest.param(
Op.SSTORE(Op.PUSH0, 1),
Account(storage={0x00: 0x01}),
id="key_sstore",
),
# Fill stack with PUSH0, then OR all values and save using SSTORE.
pytest.param(
(Op.PUSH0 * 1024) + (Op.OR * 1023) + Op.SSTORE(Op.SWAP1, 1),
Account(storage={0x00: 0x01}),
id="fill_stack",
),
# Stack overflow by using PUSH0 1025 times.
pytest.param(
Op.SSTORE(Op.PUSH0, 1) + (Op.PUSH0 * 1025),
Account(storage={0x00: 0x00}),
id="stack_overflow",
),
# Update an already existing storage value.
pytest.param(
Op.SSTORE(Op.PUSH0, 2) + Op.SSTORE(1, Op.PUSH0),
Account(storage={0x00: 0x02, 0x01: 0x00}),
id="storage_overwrite",
),
# Jump to a JUMPDEST next to a PUSH0, must succeed.
pytest.param(
Op.PUSH1(4)
+ Op.JUMP
+ Op.PUSH0
+ Op.JUMPDEST
+ Op.SSTORE(Op.PUSH0, 1)
+ Op.STOP,
Account(storage={0x00: 0x01}),
id="before_jumpdest",
),
# Test PUSH0 gas cost.
pytest.param(
CodeGasMeasure(
code=Op.PUSH0,
extra_stack_items=1,
),
Account(storage={0x00: 0x02}),
id="gas_cost",
),
],
)
def test_push0_contracts(
state_test: StateTestFiller,
env: Environment,
pre: Alloc,
post: Alloc,
sender: EOA,
contract_code: Bytecode,
expected_storage: Account,
) -> None:
"""Tests PUSH0 within various deployed contracts."""
push0_contract = pre.deploy_contract(contract_code)
tx = Transaction(to=push0_contract, gas_limit=100_000, sender=sender)
post[push0_contract] = expected_storage
state_test(env=env, pre=pre, post=post, tx=tx)