Skip to content

test_sload_erc20_generic()

Documentation for tests/benchmark/stateful/bloatnet/test_erc20.py::test_sload_erc20_generic@5fa5938b.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/benchmark/stateful/bloatnet/test_erc20.py::test_sload_erc20_generic --gas-benchmark-values 1

Benchmark SLOAD using ERC20 balanceOf.

Source code in tests/benchmark/stateful/bloatnet/test_erc20.py
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
@pytest.mark.stub_parametrize(
    "erc20_stub", "test_sload_empty_erc20_balanceof_"
)
def test_sload_erc20_generic(
    benchmark_test: BenchmarkTestFiller,
    pre: Alloc,
    fork: Fork,
    gas_benchmark_value: int,
    tx_gas_limit: int,
    erc20_stub: str,
) -> None:
    """Benchmark SLOAD using ERC20 balanceOf."""
    # Stub Account
    erc20_address = pre.deploy_contract(
        code=Bytecode(),
        stub=erc20_stub,
    )
    threshold = 100000

    # MEM[0] = function selector
    # MEM[32] = starting address offset
    setup = Op.MSTORE(
        0,
        BALANCEOF_SELECTOR,
        # gas accounting
        old_memory_size=0,
        new_memory_size=32,
    ) + Op.MSTORE(
        32,
        Op.SLOAD(0),  # Address Offset
        # gas accounting
        old_memory_size=32,
        new_memory_size=64,
    )

    call_balance_of = Op.POP(
        Op.CALL(
            address=erc20_address,
            args_offset=32 - 4,
            args_size=32 + 4,
        )
    )

    loop = While(
        body=call_balance_of + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)),
        condition=Op.GT(Op.GAS, threshold),
    )

    teardown = Op.SSTORE(0, Op.MLOAD(32))

    # Contract Deployment
    code = setup + loop + teardown
    attack_contract_address = pre.deploy_contract(code=code)

    intrinsic_gas = fork.transaction_intrinsic_cost_calculator()()

    # Transaction Loops
    txs = []
    gas_remaining = gas_benchmark_value

    sender = pre.fund_eoa()

    while gas_remaining > intrinsic_gas:
        gas_available = min(gas_remaining, tx_gas_limit)

        if gas_available < intrinsic_gas:
            break

        with TestPhaseManager.execution():
            txs.append(
                Transaction(
                    gas_limit=gas_available,
                    to=attack_contract_address,
                    sender=sender,
                )
            )

        gas_remaining -= gas_available

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

Parametrized Test Cases

This test generates 1 parametrized test case across 3 forks.