From 6d064342ed493952d490ca8b6e4bc3d3fe1af36a Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Wed, 5 Aug 2026 14:59:45 +0800 Subject: [PATCH 1/3] feat: add deployment script --- docs/filling_tests/fill_stateful.md | 2 + .../plugins/fill_stateful/fill_stateful.py | 20 +++ tests/benchmark/helper/account_creator.py | 4 +- .../stateful/bloatnet/test_setup_contracts.py | 165 ++++++++++++++++++ 4 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 tests/benchmark/stateful/bloatnet/test_setup_contracts.py diff --git a/docs/filling_tests/fill_stateful.md b/docs/filling_tests/fill_stateful.md index ebbb52bba9..dde7ac8548 100644 --- a/docs/filling_tests/fill_stateful.md +++ b/docs/filling_tests/fill_stateful.md @@ -123,6 +123,7 @@ Optional: - `--output PATH` — default `./fixtures`. - `--clean` — wipe the output dir before filling. - `--extract-opcode-count` — after building each block, trace it via `debug_traceBlockByHash` (a JS opcode-counting tracer) and record per-opcode execution counts (execution-phase blocks only) in the fixture's `_info.metadata.opcode_counts` — an array with one entry per `engineNewPayloads` block (`opcode_counts[i]` is the count for `engineNewPayloads[i]`, or `null` if its trace was unavailable), so multi-block benchmarks keep per-payload granularity. When a benchmark test declares a target opcode count (`fixed_opcode_count`/`expected_opcode_count`), the live-client count is verified against it and the fill fails on >5% divergence. Requires the `debug` namespace with JS tracer support. Adds a full re-execution trace per block, so it is slow and opt-in. +- `--no-reset-between-tests` — skip the between-test rewind to `start_block`, so each test builds on the state the previous one left behind and the client head accumulates upward. Used to pre-populate a datadir (e.g. deploy setup contracts) whose persisted state a later run builds on. The written fixtures are unchanged — each still records its own `start_block` — so a fixture produced this way is only valid to replay against a client already at that `start_block`; do not mix accumulate-state fills and normal single-anchor fills in one output dir. ## Output layout @@ -198,6 +199,7 @@ Both backends satisfy `FillerBackend` (`client_clis/filler_backend.py`). `Client |---|---|---| | `--snapshot-block` | `fill-stateful` | Anchor by 32-byte hash (reorg-safe) or block number; defaults to `latest`. | | `--rpc-seed-key` | `fill-stateful` | Pin the seed EOA; otherwise generated + funded via CL withdrawal. | +| `--no-reset-between-tests` | `fill-stateful` | Skip the between-test rewind so tests accumulate state on the live client (pre-populate a datadir a later run builds on). | | `--default-gas-price`, `--default-max-fee-per-gas`, `--default-max-priority-fee-per-gas`, `--default-max-fee-per-blob-gas` | `shared/live_client_flags` | Pin per-session fees; defaults bump a one-shot live query by `1.5x`. | | `--max-gas-per-test`, `--max-tx-per-batch`, `--transaction-gas-limit`, ... | `shared/live_client_flags` | Generic live-client knobs reused across commands. | diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/fill_stateful/fill_stateful.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/fill_stateful/fill_stateful.py index e98f15a657..11661319aa 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/fill_stateful/fill_stateful.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/fill_stateful/fill_stateful.py @@ -158,6 +158,17 @@ def pytest_addoption(parser: pytest.Parser) -> None: "This flag checks every account at start_block.)" ), ) + group.addoption( + "--no-reset-between-tests", + action="store_true", + dest="no_reset_between_tests", + default=False, + help=( + "Accumulate state across tests (don't rewind between them). Useful" + "for pre-populating datadir. Fixtures remain valid only from their" + "recorded start_block. Don't mix with single-anchor fills." + ), + ) def _resolve_session_fork( @@ -507,6 +518,12 @@ def extract_opcode_count(request: pytest.FixtureRequest) -> bool: return request.config.getoption("extract_opcode_count") +@pytest.fixture(scope="session") +def no_reset_between_tests(request: pytest.FixtureRequest) -> bool: + """Whether --no-reset-between-tests state accumulation is enabled.""" + return request.config.getoption("no_reset_between_tests") + + @pytest.fixture(scope="session") def client_backend( eth_rpc: ChainBuilderEthRPC, @@ -770,6 +787,7 @@ def _reset_chain_between_tests( client_backend: ClientBackend, debug_rpc: DebugRPC, eth_rpc: "ChainBuilderEthRPC", + no_reset_between_tests: bool, ) -> Generator[None, None, None]: """ Rewind to start_block after each test so the chain is identical for @@ -781,6 +799,8 @@ def _reset_chain_between_tests( drifted (e.g. a live reorg). """ yield + if no_reset_between_tests: + return if client_backend.start_block is None: return start_hex = client_backend.start_block["number"] diff --git a/tests/benchmark/helper/account_creator.py b/tests/benchmark/helper/account_creator.py index 464d04939f..9e12581fe4 100644 --- a/tests/benchmark/helper/account_creator.py +++ b/tests/benchmark/helper/account_creator.py @@ -160,7 +160,7 @@ class JochemnetPredeployContractInitcode(ContractInitcode): code_size: int - def __new__(cls, *, code_size: int = DEFAULT_CODE_SIZE) -> Self: + def __new__(cls, *, code_size: int = Osaka.max_code_size()) -> Self: """Assemble the initcode.""" # Each MCOPY doubles the JUMPDEST-filled span (the first copy is # MCOPY(32, 0, 32), since 1 << 5 = 32) until it covers code_size. @@ -329,7 +329,7 @@ def contract_initcode(self) -> ContractInitcode: ) case AccountMode.EXISTING_CONTRACT_JUMPDEST: return JochemnetPredeployContractInitcode( - code_size=self.code_size + code_size=Osaka.max_code_size() ) case _: raise ValueError(f"{self.mode.name} is not a contract") diff --git a/tests/benchmark/stateful/bloatnet/test_setup_contracts.py b/tests/benchmark/stateful/bloatnet/test_setup_contracts.py new file mode 100644 index 0000000000..26bc15d891 --- /dev/null +++ b/tests/benchmark/stateful/bloatnet/test_setup_contracts.py @@ -0,0 +1,165 @@ +"""Deploy the CREATE2 contracts for benchmarks.""" + +import os + +from execution_testing import ( + DETERMINISTIC_FACTORY_ADDRESS, + EOA, + Account, + Alloc, + AuthorizationTuple, + BenchmarkTestFiller, + Fork, + Hash, + Op, + Transaction, + compute_create2_address, +) + +from tests.benchmark.helper.account_creator import ( + AccountCreator, + AccountMode, +) +from tests.benchmark.helper.account_sender_receiver import ( + DELEGATE_BASE_KEY, +) +from tests.benchmark.helper.transactions import ( + pack_transactions_into_blocks, +) +from tests.prague.eip7702_set_code_tx.spec import Spec as Spec7702 + +# Number of CREATE2 receiver contracts deployed per mode. Overridable via +# BLOATNET_RECEIVER_CONTRACT_COUNT so a smoke/plumbing run (e.g. benchmarkoor +# pre_runs) can deploy a small set for fast iteration; defaults to the full +# 100k benchmark set. +RECEIVER_CONTRACT_COUNT = int( + os.environ.get("BLOATNET_RECEIVER_CONTRACT_COUNT", "100000") +) + +CONTRACT_MODES = [ + AccountMode.EXISTING_CONTRACT_MINIMAL, + AccountMode.EXISTING_CONTRACT_SAME_MAX, + AccountMode.EXISTING_CONTRACT_DIFF_MAX, +] + +# Factory-frame and initcode execution costs (CALLDATACOPY, the MCOPY +# doubling loop, memory expansion) plus CREATE2's 63/64 retention. +EXECUTION_GAS_BUFFER = 50_000 + + +def deployment_gas_limit( + fork: Fork, initcode: bytes, runtime_size: int +) -> int: + """ + Return the gas limit for one CREATE2 deployment, derived from the + intrinsic, CREATE2, and code-deposit costs with a margin for the + factory and initcode execution. + """ + intrinsic = fork.transaction_intrinsic_cost_calculator()( + calldata=b"\xff" * 32 + initcode + ) + create_cost = Op.CREATE2( + value=0, + offset=0, + size=len(initcode), + salt=0, + init_code_size=len(initcode), + ).gas_cost(fork) + deposit_cost = Op.RETURN( + 0, + runtime_size, + code_deposit_size=runtime_size, + ).gas_cost(fork) + base = intrinsic + create_cost + deposit_cost + return base + base // 16 + EXECUTION_GAS_BUFFER + + +def test_deploy_existing_contracts( + benchmark_test: BenchmarkTestFiller, + pre: Alloc, + fork: Fork, + gas_benchmark_value: int, + tx_gas_limit: int, +) -> None: + """ + Deploy the contracts behind the `AccountMode.EXISTING_CONTRACT_*` + receivers via the deterministic CREATE2 factory. + + Delegate deterministic EOAs to EXISTING_CONTRACT_DIFF_MAX receivers. + """ + txs = [] + post: dict = {} + for account_mode in CONTRACT_MODES: + creator = AccountCreator(account_mode) + initcode = creator.initcode + gas_limit = deployment_gas_limit(fork, initcode, creator.runtime_size) + sender = pre.fund_eoa() + for salt in range(RECEIVER_CONTRACT_COUNT): + txs.append( + Transaction( + to=DETERMINISTIC_FACTORY_ADDRESS, + data=Hash(salt) + initcode, + gas_limit=gas_limit, + sender=sender, + ) + ) + # Nonce 1 at the CREATE2-derived address proves deployment. + for salt in (0, RECEIVER_CONTRACT_COUNT - 1): + contract = compute_create2_address( + address=DETERMINISTIC_FACTORY_ADDRESS, + salt=salt, + initcode=initcode, + ) + post[contract] = Account(nonce=1) + + # Delegate authority i to the i-th DIFF receiver (EIP-7702). + delegation_sender = pre.fund_eoa() + intrinsic = fork.transaction_intrinsic_cost_calculator() + # DIFF receivers share one initcode; build it once for CREATE2 derivation. + diff_initcode = AccountCreator( + AccountMode.EXISTING_CONTRACT_DIFF_MAX + ).initcode + + base_gas = intrinsic(authorization_list_or_count=0) + per_auth_gas = intrinsic(authorization_list_or_count=1) - base_gas + gas_buffer = 100_000 + auths_per_tx = max( + 1, (tx_gas_limit - gas_buffer - base_gas) // per_auth_gas + ) + + for start in range(0, RECEIVER_CONTRACT_COUNT, auths_per_tx): + count = min(auths_per_tx, RECEIVER_CONTRACT_COUNT - start) + authorization_list = [] + for i in range(start, start + count): + authority = EOA(key=DELEGATE_BASE_KEY + i) + target = compute_create2_address( + address=DETERMINISTIC_FACTORY_ADDRESS, + salt=i, + initcode=diff_initcode, + ) + authorization_list.append( + AuthorizationTuple(address=target, nonce=0, signer=authority) + ) + if i == 0 or i == RECEIVER_CONTRACT_COUNT - 1: + post[authority] = Account( + nonce=1, + code=Spec7702.delegation_designation(target), + ) + + txs.append( + Transaction( + to=delegation_sender, + gas_limit=( + intrinsic(authorization_list_or_count=count) + gas_buffer + ), + sender=delegation_sender, + authorization_list=authorization_list, + ) + ) + + benchmark_test( + post=post, + blocks=pack_transactions_into_blocks(txs, gas_benchmark_value), + skip_gas_used_validation=True, + expected_receipt_status=1, + ) From be69f3c5a6c5d81aeff8ed519c935dd6ebb853dd Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Wed, 5 Aug 2026 16:30:09 +0800 Subject: [PATCH 2/3] refactor: deployment script --- tests/benchmark/helper/transactions.py | 46 ++++++++ .../stateful/bloatnet/test_setup_contracts.py | 110 ++++++++++++------ 2 files changed, 119 insertions(+), 37 deletions(-) diff --git a/tests/benchmark/helper/transactions.py b/tests/benchmark/helper/transactions.py index 70a623fdaa..ee5a7f5721 100644 --- a/tests/benchmark/helper/transactions.py +++ b/tests/benchmark/helper/transactions.py @@ -10,6 +10,7 @@ Fork, Hash, Transaction, + TransactionWithCost, ) from .enums import CacheStrategy @@ -138,3 +139,48 @@ def pack_transactions_into_blocks( blocks.append(Block(txs=current_txs)) return blocks + + +def pack_transactions_with_cost_into_blocks( + transactions: list[TransactionWithCost], + gas_limit: int, +) -> list[Block]: + """ + Pack transactions into blocks, tracking both gas dimensions. + + A transaction is includable only while its gas limit still fits the + room left in the regular and in the state dimension alike, so the + room a block has left is measured against the larger of the two + running totals. Raise when a single transaction cannot fit an empty + block, which no packing can rescue. + """ + if not transactions: + return [] + + blocks: list[Block] = [] + current_txs: list[TransactionWithCost] = [] + current_regular = 0 + current_state = 0 + + for tx in transactions: + tx_gas_limit = int(tx.gas_limit) + if tx_gas_limit > gas_limit: + raise ValueError( + f"transaction gas limit {tx_gas_limit} exceeds the " + f"{gas_limit} block gas limit" + ) + room = gas_limit - max(current_regular, current_state) + if tx_gas_limit > room and current_txs: + blocks.append(Block(txs=current_txs)) + current_txs = [] + current_regular = 0 + current_state = 0 + + current_txs.append(tx) + current_regular += tx.regular_cost + current_state += tx.state_cost + + if current_txs: + blocks.append(Block(txs=current_txs)) + + return blocks diff --git a/tests/benchmark/stateful/bloatnet/test_setup_contracts.py b/tests/benchmark/stateful/bloatnet/test_setup_contracts.py index 26bc15d891..269749e98b 100644 --- a/tests/benchmark/stateful/bloatnet/test_setup_contracts.py +++ b/tests/benchmark/stateful/bloatnet/test_setup_contracts.py @@ -12,7 +12,7 @@ Fork, Hash, Op, - Transaction, + TransactionWithCost, compute_create2_address, ) @@ -24,7 +24,7 @@ DELEGATE_BASE_KEY, ) from tests.benchmark.helper.transactions import ( - pack_transactions_into_blocks, + pack_transactions_with_cost_into_blocks, ) from tests.prague.eip7702_set_code_tx.spec import Spec as Spec7702 @@ -47,13 +47,17 @@ EXECUTION_GAS_BUFFER = 50_000 -def deployment_gas_limit( +def deployment_gas( fork: Fork, initcode: bytes, runtime_size: int -) -> int: +) -> tuple[int, int]: """ - Return the gas limit for one CREATE2 deployment, derived from the - intrinsic, CREATE2, and code-deposit costs with a margin for the - factory and initcode execution. + Return the (regular, state) gas for one CREATE2 deployment, derived + from the intrinsic, CREATE2, and code-deposit costs with a margin + for the factory and initcode execution. + + The opcode costs are two-dimensional totals, so the state gas the + account creation and the code deposit charge is split back out; the + margin lands on the regular side, which is what it pays for. """ intrinsic = fork.transaction_intrinsic_cost_calculator()( calldata=b"\xff" * 32 + initcode @@ -71,7 +75,9 @@ def deployment_gas_limit( code_deposit_size=runtime_size, ).gas_cost(fork) base = intrinsic + create_cost + deposit_cost - return base + base // 16 + EXECUTION_GAS_BUFFER + state = fork.create_state_gas(code_size=runtime_size) + regular = base - state + base // 16 + EXECUTION_GAS_BUFFER + return regular, state def test_deploy_existing_contracts( @@ -92,15 +98,19 @@ def test_deploy_existing_contracts( for account_mode in CONTRACT_MODES: creator = AccountCreator(account_mode) initcode = creator.initcode - gas_limit = deployment_gas_limit(fork, initcode, creator.runtime_size) + regular_gas, state_gas = deployment_gas( + fork, initcode, creator.runtime_size + ) sender = pre.fund_eoa() for salt in range(RECEIVER_CONTRACT_COUNT): txs.append( - Transaction( + TransactionWithCost( to=DETERMINISTIC_FACTORY_ADDRESS, data=Hash(salt) + initcode, - gas_limit=gas_limit, + gas_limit=regular_gas + state_gas, sender=sender, + regular_cost=regular_gas, + state_cost=state_gas, ) ) # Nonce 1 at the CREATE2-derived address proves deployment. @@ -115,51 +125,77 @@ def test_deploy_existing_contracts( # Delegate authority i to the i-th DIFF receiver (EIP-7702). delegation_sender = pre.fund_eoa() intrinsic = fork.transaction_intrinsic_cost_calculator() + top_frame = fork.transaction_top_frame_gas_calculator() # DIFF receivers share one initcode; build it once for CREATE2 derivation. diff_initcode = AccountCreator( AccountMode.EXISTING_CONTRACT_DIFF_MAX ).initcode - base_gas = intrinsic(authorization_list_or_count=0) - per_auth_gas = intrinsic(authorization_list_or_count=1) - base_gas + authorizations = [] + for i in range(RECEIVER_CONTRACT_COUNT): + authority = EOA(key=DELEGATE_BASE_KEY + i) + target = compute_create2_address( + address=DETERMINISTIC_FACTORY_ADDRESS, + salt=i, + initcode=diff_initcode, + ) + authorizations.append( + AuthorizationTuple( + address=target, + nonce=0, + signer=authority, + # The authorities are deterministic and never funded, so + # applying the delegation is what brings them into being. + creates_account=True, + ) + ) + if i == 0 or i == RECEIVER_CONTRACT_COUNT - 1: + post[authority] = Account( + nonce=1, + code=Spec7702.delegation_designation(target), + ) + + def authorization_gas( + authorization_list: list[AuthorizationTuple], + ) -> tuple[int, int]: + """Return the (regular, state) gas an authorization list costs.""" + regular = intrinsic( + authorization_list_or_count=len(authorization_list) + ) + top_frame(authorizations=authorization_list) + state = fork.transaction_top_frame_state_gas( + authorizations=authorization_list + ) + return regular, state + gas_buffer = 100_000 + base_regular, base_state = authorization_gas([]) + one_regular, one_state = authorization_gas(authorizations[:1]) + per_auth_gas = (one_regular + one_state) - (base_regular + base_state) auths_per_tx = max( - 1, (tx_gas_limit - gas_buffer - base_gas) // per_auth_gas + 1, + (tx_gas_limit - gas_buffer - base_regular - base_state) + // per_auth_gas, ) for start in range(0, RECEIVER_CONTRACT_COUNT, auths_per_tx): - count = min(auths_per_tx, RECEIVER_CONTRACT_COUNT - start) - authorization_list = [] - for i in range(start, start + count): - authority = EOA(key=DELEGATE_BASE_KEY + i) - target = compute_create2_address( - address=DETERMINISTIC_FACTORY_ADDRESS, - salt=i, - initcode=diff_initcode, - ) - authorization_list.append( - AuthorizationTuple(address=target, nonce=0, signer=authority) - ) - if i == 0 or i == RECEIVER_CONTRACT_COUNT - 1: - post[authority] = Account( - nonce=1, - code=Spec7702.delegation_designation(target), - ) - + authorization_list = authorizations[start : start + auths_per_tx] + regular_gas, state_gas = authorization_gas(authorization_list) txs.append( - Transaction( + TransactionWithCost( to=delegation_sender, - gas_limit=( - intrinsic(authorization_list_or_count=count) + gas_buffer - ), + gas_limit=regular_gas + state_gas + gas_buffer, sender=delegation_sender, authorization_list=authorization_list, + regular_cost=regular_gas + gas_buffer, + state_cost=state_gas, ) ) benchmark_test( post=post, - blocks=pack_transactions_into_blocks(txs, gas_benchmark_value), + blocks=pack_transactions_with_cost_into_blocks( + txs, gas_benchmark_value + ), skip_gas_used_validation=True, expected_receipt_status=1, ) From 328611c11727504ceb9c6db90208e12dec9e4369 Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Wed, 5 Aug 2026 17:16:14 +0800 Subject: [PATCH 3/3] refactor: apply suggestion --- .../testing/src/execution_testing/__init__.py | 2 ++ tests/benchmark/helper/account_creator.py | 4 +-- .../stateful/bloatnet/test_setup_contracts.py | 27 ++++++++++++++++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/testing/src/execution_testing/__init__.py b/packages/testing/src/execution_testing/__init__.py index 0b47af7a9b..9bd3ff0392 100644 --- a/packages/testing/src/execution_testing/__init__.py +++ b/packages/testing/src/execution_testing/__init__.py @@ -50,6 +50,7 @@ ) from .test_types import ( DETERMINISTIC_FACTORY_ADDRESS, + DETERMINISTIC_FACTORY_BYTECODE, EOA, Alloc, AuthorizationTuple, @@ -132,6 +133,7 @@ __all__ = ( "DETERMINISTIC_FACTORY_ADDRESS", + "DETERMINISTIC_FACTORY_BYTECODE", "AccessList", "Account", "Address", diff --git a/tests/benchmark/helper/account_creator.py b/tests/benchmark/helper/account_creator.py index 9e12581fe4..464d04939f 100644 --- a/tests/benchmark/helper/account_creator.py +++ b/tests/benchmark/helper/account_creator.py @@ -160,7 +160,7 @@ class JochemnetPredeployContractInitcode(ContractInitcode): code_size: int - def __new__(cls, *, code_size: int = Osaka.max_code_size()) -> Self: + def __new__(cls, *, code_size: int = DEFAULT_CODE_SIZE) -> Self: """Assemble the initcode.""" # Each MCOPY doubles the JUMPDEST-filled span (the first copy is # MCOPY(32, 0, 32), since 1 << 5 = 32) until it covers code_size. @@ -329,7 +329,7 @@ def contract_initcode(self) -> ContractInitcode: ) case AccountMode.EXISTING_CONTRACT_JUMPDEST: return JochemnetPredeployContractInitcode( - code_size=Osaka.max_code_size() + code_size=self.code_size ) case _: raise ValueError(f"{self.mode.name} is not a contract") diff --git a/tests/benchmark/stateful/bloatnet/test_setup_contracts.py b/tests/benchmark/stateful/bloatnet/test_setup_contracts.py index 269749e98b..f66e377970 100644 --- a/tests/benchmark/stateful/bloatnet/test_setup_contracts.py +++ b/tests/benchmark/stateful/bloatnet/test_setup_contracts.py @@ -2,8 +2,10 @@ import os +import pytest from execution_testing import ( DETERMINISTIC_FACTORY_ADDRESS, + DETERMINISTIC_FACTORY_BYTECODE, EOA, Account, Alloc, @@ -59,27 +61,46 @@ def deployment_gas( account creation and the code deposit charge is split back out; the margin lands on the regular side, which is what it pays for. """ + initcode_size = len(initcode) intrinsic = fork.transaction_intrinsic_cost_calculator()( calldata=b"\xff" * 32 + initcode ) create_cost = Op.CREATE2( value=0, offset=0, - size=len(initcode), + size=initcode_size, salt=0, - init_code_size=len(initcode), + # Gas accounting + init_code_size=initcode_size, ).gas_cost(fork) + # The factory frame wrapped around that CREATE2: its own bytecode, + # less the CREATE2 already counted above, plus the copy of the + # initcode out of the calldata that the bytecode alone cannot size. + factory_cost = ( + DETERMINISTIC_FACTORY_BYTECODE.gas_cost(fork) + - Op.CREATE2(value=0, offset=0, size=0, salt=0).gas_cost(fork) + + Op.CALLDATACOPY( + dest_offset=0, + offset=32, + size=initcode_size, + # Gas accounting + data_size=initcode_size, + old_memory_size=0, + new_memory_size=initcode_size, + ).gas_cost(fork) + ) deposit_cost = Op.RETURN( 0, runtime_size, code_deposit_size=runtime_size, ).gas_cost(fork) - base = intrinsic + create_cost + deposit_cost + base = intrinsic + factory_cost + create_cost + deposit_cost state = fork.create_state_gas(code_size=runtime_size) regular = base - state + base // 16 + EXECUTION_GAS_BUFFER return regular, state +@pytest.mark.valid_from("Amsterdam") def test_deploy_existing_contracts( benchmark_test: BenchmarkTestFiller, pre: Alloc,