1919from ethereum_test_tools .vm .opcode import Opcodes as Op
2020
2121
22- @pytest .mark .valid_from ("Osaka " )
23- def test_bloatnet_sstore_cold (
22+ @pytest .mark .valid_from ("Prague " )
23+ def test_bloatnet_sstore_0_to_1 (
2424 blockchain_test : BlockchainTestFiller , pre : Alloc , fork : Fork , gas_benchmark_value : int
2525):
2626 """
27- Benchmark test that maximizes cold SSTORE operations (0 -> 1) by filling
27+ Benchmark test that maximizes SSTORE operations (0 -> 1) by filling
2828 a block with multiple transactions, with each one containing a contract
29- that performs a set of cold SSTOREs.
29+ that performs a set of SSTOREs.
3030
3131 The test iteratively creates new transactions until the cumulative gas used
3232 reaches the block's gas benchmark value. Each transaction deploys a contract
@@ -58,39 +58,25 @@ def test_bloatnet_sstore_cold(
5858
5959 opcode_gas_budget = tx_gas_limit - intrinsic_gas
6060
61+ # Setup code to load value from calldata
6162 tx_contract_code = Op .PUSH0 + Op .CALLDATALOAD
62- tx_opcode_gas = (
63- gas_costs .G_BASE # PUSH0
64- + gas_costs .G_VERY_LOW # CALLDATALOAD
65- )
66- tx_sstores_count = 0
67-
68- current_slot = total_sstores
69-
70- pop_gas = gas_costs .G_BASE
71-
72- while True :
73- sstore_per_op_cost = (
74- gas_costs .G_VERY_LOW * 2 # PUSH + DUP1
75- + gas_costs .G_COLD_SLOAD
76- + gas_costs .G_STORAGE_SET # SSTORE
77- )
63+ tx_opcode_gas = gas_costs .G_BASE + gas_costs .G_VERY_LOW # PUSH0 + CALLDATALOAD
7864
79- if tx_opcode_gas + sstore_per_op_cost + pop_gas > opcode_gas_budget :
80- break
65+ sstore_per_op_cost = (
66+ gas_costs .G_VERY_LOW * 2 # PUSH + DUP1
67+ + gas_costs .G_COLD_SLOAD
68+ + gas_costs .G_STORAGE_SET # SSTORE
69+ )
8170
82- tx_opcode_gas += sstore_per_op_cost
83- tx_contract_code += Op .SSTORE (current_slot , Op .DUP1 )
84- tx_sstores_count += 1
85- current_slot += 1
71+ tx_sstores_count = (opcode_gas_budget - tx_opcode_gas ) // sstore_per_op_cost
8672
8773 # If no SSTOREs could be added, we've filled the block
8874 if tx_sstores_count == 0 :
8975 break
9076
91- # Add a POP to clean up the stack at the end
92- tx_contract_code += Op . POP
93- tx_opcode_gas += pop_gas
77+ tx_opcode_gas += sstore_per_op_cost * tx_sstores_count
78+ for slot in range ( total_sstores , total_sstores + tx_sstores_count ):
79+ tx_contract_code += Op . SSTORE ( slot , Op . DUP1 )
9480
9581 contract_address = pre .deploy_contract (code = tx_contract_code )
9682 tx = Transaction (
@@ -111,18 +97,18 @@ def test_bloatnet_sstore_cold(
11197 tx_gas_used = actual_intrinsic_consumed + tx_opcode_gas
11298 total_block_gas_used += tx_gas_used
11399
114- total_sstores += tx_sstores_count
115-
116100 # update expected storage state for each contract
117101 expected_storage_state [contract_address ] = Account (
118102 storage = Storage (
119103 {
120104 HashInt (slot ): HashInt (storage_value )
121- for slot in range (current_slot - tx_sstores_count , current_slot )
105+ for slot in range (total_sstores , total_sstores + tx_sstores_count )
122106 }
123107 )
124108 )
125109
110+ total_sstores += tx_sstores_count
111+
126112 blockchain_test (
127113 pre = pre ,
128114 blocks = [Block (txs = all_txs )],
@@ -131,16 +117,15 @@ def test_bloatnet_sstore_cold(
131117 )
132118
133119
134- @pytest .mark .valid_from ("Osaka " )
135- def test_bloatnet_sstore_warm (
120+ @pytest .mark .valid_from ("Prague " )
121+ def test_bloatnet_sstore_1_to_2 (
136122 blockchain_test : BlockchainTestFiller , pre : Alloc , fork : Fork , gas_benchmark_value : int
137123):
138124 """
139- Benchmark test that maximizes warm SSTORE operations (1 -> 2).
125+ Benchmark test that maximizes SSTORE operations (1 -> 2).
140126
141127 This test pre-fills storage slots with value=1, then overwrites them with value=2.
142128 This represents the case of changing a non-zero value to a different non-zero value,
143- which is cheaper than cold SSTORE but still significant.
144129 """
145130 gas_costs = fork .gas_costs ()
146131 intrinsic_gas_calc = fork .transaction_intrinsic_cost_calculator ()
@@ -165,36 +150,24 @@ def test_bloatnet_sstore_warm(
165150
166151 opcode_gas_budget = tx_gas_limit - intrinsic_gas
167152
153+ # Setup code to load value from calldata
168154 tx_contract_code = Op .PUSH0 + Op .CALLDATALOAD
169- tx_opcode_gas = (
170- gas_costs .G_BASE # PUSH0
171- + gas_costs .G_VERY_LOW # CALLDATALOAD
172- )
173- tx_sstores_count = 0
174-
175- current_slot = total_sstores
176- pop_gas = gas_costs .G_BASE
177-
178- warm_sstore_cost = gas_costs .G_COLD_SLOAD + gas_costs .G_STORAGE_RESET
179- while True :
180- sstore_per_op_cost = (
181- gas_costs .G_VERY_LOW * 2 # PUSH + DUP1
182- + warm_sstore_cost # SSTORE
183- )
155+ tx_opcode_gas = gas_costs .G_BASE + gas_costs .G_VERY_LOW # PUSH0 + CALLDATALOAD
184156
185- if tx_opcode_gas + sstore_per_op_cost + pop_gas > opcode_gas_budget :
186- break
157+ sstore_per_op_cost = (
158+ gas_costs .G_VERY_LOW * 2 # PUSH + DUP1
159+ + gas_costs .G_COLD_SLOAD
160+ + gas_costs .G_STORAGE_RESET # SSTORE
161+ )
187162
188- tx_opcode_gas += sstore_per_op_cost
189- tx_contract_code += Op .SSTORE (current_slot , Op .DUP1 )
190- tx_sstores_count += 1
191- current_slot += 1
163+ tx_sstores_count = (opcode_gas_budget - tx_opcode_gas ) // sstore_per_op_cost
192164
193165 if tx_sstores_count == 0 :
194166 break
195167
196- tx_contract_code += Op .POP
197- tx_opcode_gas += pop_gas
168+ tx_opcode_gas += sstore_per_op_cost * tx_sstores_count
169+ for slot in range (total_sstores , total_sstores + tx_sstores_count ):
170+ tx_contract_code += Op .SSTORE (slot , Op .DUP1 )
198171
199172 # Pre-fill storage with initial values
200173 initial_storage = {
@@ -219,17 +192,18 @@ def test_bloatnet_sstore_warm(
219192
220193 tx_gas_used = actual_intrinsic_consumed + tx_opcode_gas
221194 total_block_gas_used += tx_gas_used
222- total_sstores += tx_sstores_count
223195
224196 expected_storage_state [contract_address ] = Account (
225197 storage = Storage (
226198 {
227199 HashInt (slot ): HashInt (new_value )
228- for slot in range (current_slot - tx_sstores_count , current_slot )
200+ for slot in range (total_sstores , total_sstores + tx_sstores_count )
229201 }
230202 )
231203 )
232204
205+ total_sstores += tx_sstores_count
206+
233207 blockchain_test (
234208 pre = pre ,
235209 blocks = [Block (txs = all_txs )],
0 commit comments