@pytest.mark.parametrize(
"storage_action",
[
pytest.param(StorageAction.READ, id="SLOAD"),
pytest.param(StorageAction.WRITE_SAME_VALUE, id="SSTORE same value"),
pytest.param(StorageAction.WRITE_NEW_VALUE, id="SSTORE new value"),
],
)
def test_storage_access_warm(
benchmark_test: BenchmarkTestFiller,
pre: Alloc,
storage_action: StorageAction,
gas_benchmark_value: int,
tx_gas_limit: int,
) -> None:
"""Benchmark warm storage slot accesses."""
blocks = []
match storage_action:
case StorageAction.WRITE_SAME_VALUE:
execution_code_body = Op.SSTORE(0, Op.DUP1)
case StorageAction.WRITE_NEW_VALUE:
execution_code_body = Op.SSTORE(0, Op.GAS)
case StorageAction.READ:
execution_code_body = Op.POP(Op.SLOAD(0))
case _:
raise ValueError("Unspecified storage action")
execution_code = Op.SLOAD(0) + While(body=execution_code_body)
execution_code_address = pre.deploy_contract(code=execution_code)
creation_code = (
Op.SSTORE(0, 42)
+ Op.EXTCODECOPY(
address=execution_code_address,
dest_offset=0,
offset=0,
size=Op.EXTCODESIZE(execution_code_address),
)
+ Op.RETURN(0, Op.MSIZE)
)
with TestPhaseManager.setup():
sender_addr = pre.fund_eoa()
setup_tx = Transaction(
to=None,
gas_limit=tx_gas_limit,
data=creation_code,
sender=sender_addr,
)
blocks.append(Block(txs=[setup_tx]))
contract_address = compute_create_address(address=sender_addr, nonce=0)
with TestPhaseManager.execution():
num_exec_txs = math.ceil(gas_benchmark_value / tx_gas_limit)
txs = []
for i in range(num_exec_txs):
gas_limit = min(
tx_gas_limit, gas_benchmark_value - i * tx_gas_limit
)
txs.append(
Transaction(
to=contract_address,
gas_limit=gas_limit,
sender=pre.fund_eoa(),
)
)
blocks.append(Block(txs=txs))
benchmark_test(blocks=blocks)