Skip to content

test_bloatnet_call_value_new_account()

Documentation for tests/benchmark/stateful/bloatnet/test_multi_opcode.py::test_bloatnet_call_value_new_account@892e6d1e.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/benchmark/stateful/bloatnet/test_multi_opcode.py::test_bloatnet_call_value_new_account --gas-benchmark-values 1

Benchmark CALL with value transfer to non-existent accounts.

Generate unique addresses via keccak256(counter) and CALL each with value=1 wei. Since these addresses have no code, the subcall succeeds (via the 2300 gas stipend), transferring value and creating a new account in the trie. Each iteration costs ~36,600 gas: - GAS_COLD_ACCOUNT_ACCESS: 2,600 - CALL_VALUE: 9,000 - NEW_ACCOUNT: 25,000

This stresses trie expansion through massive new account creation.

Source code in tests/benchmark/stateful/bloatnet/test_multi_opcode.py
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
def test_bloatnet_call_value_new_account(
    benchmark_test: BenchmarkTestFiller,
    pre: Alloc,
    fork: Fork,
    gas_benchmark_value: int,
    tx_gas_limit: int,
) -> None:
    """
    Benchmark CALL with value transfer to non-existent accounts.

    Generate unique addresses via keccak256(counter) and CALL each with
    value=1 wei. Since these addresses have no code, the subcall succeeds
    (via the 2300 gas stipend), transferring value and creating a new
    account in the trie. Each iteration costs ~36,600 gas:
    - GAS_COLD_ACCOUNT_ACCESS: 2,600
    - CALL_VALUE: 9,000
    - NEW_ACCOUNT: 25,000

    This stresses trie expansion through massive new account creation.
    """
    # Memory layout: MEM[0..31] = counter (incremented each iteration)
    setup = (
        Op.MSTORE(
            0,
            Op.CALLDATALOAD(32),  # salt_offset (starting counter)
            # gas accounting
            old_memory_size=0,
            new_memory_size=32,
        )
        + Op.CALLDATALOAD(0)  # [num_calls]
    )

    # CALL with value=1 to keccak256-derived addresses.
    # gas=0: subcall gets 0 + 2300 stipend. No code at target → succeeds.
    # Value is transferred, new account is created in trie.
    call_value_op = Op.POP(
        Op.CALL(
            gas=0,
            address=Op.SHA3(0, 32, data_size=32),
            value=1,
            args_offset=0,
            args_size=0,
            ret_offset=0,
            ret_size=0,
            # gas accounting
            value_transfer=True,
            account_new=True,
        )
    )

    # Increment counter in memory for next address
    increment_counter = Op.MSTORE(0, Op.ADD(Op.MLOAD(0), 1))

    loop = While(
        body=(call_value_op + increment_counter),
        condition=DECREMENT_COUNTER_CONDITION,
    )

    # Contract Deployment — needs balance for value transfers (1 wei each)
    code = setup + loop
    attack_contract_address = pre.deploy_contract(
        code=code,
        balance=10**18,  # 1 ETH, enough for all iterations
    )

    # Gas Accounting
    txs, total_gas_consumed = build_benchmark_txs(
        pre=pre,
        fork=fork,
        gas_benchmark_value=gas_benchmark_value,
        tx_gas_limit=tx_gas_limit,
        attack_contract_address=attack_contract_address,
        setup_cost=setup.gas_cost(fork),
        iteration_cost=loop.gas_cost(fork),
    )

    benchmark_test(
        pre=pre,
        blocks=[Block(txs=txs)],
        expected_benchmark_gas_used=total_gas_consumed,
        skip_gas_used_validation=True,
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 3 forks.