Skip to content

Commit bd645af

Browse files
committed
fix: test_worst_selfdestruct_existing
1 parent c2c5667 commit bd645af

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

tests/zkevm/test_worst_stateful_opcodes.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,24 @@ def test_worst_selfdestruct_existing(
504504
) + Op.RETURN(0, Op.EXTCODESIZE(selfdestructable_contract_addr))
505505
initcode_address = pre.deploy_contract(code=initcode)
506506

507+
# Calculate the number of contracts that can be deployed with the available gas.
508+
gas_costs = fork.gas_costs()
509+
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
510+
loop_cost = (
511+
gas_costs.G_KECCAK_256 # KECCAK static cost
512+
+ math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic cost for CREATE2
513+
+ gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs
514+
+ gas_costs.G_COLD_ACCOUNT_ACCESS # CALL to self-destructing contract
515+
+ gas_costs.G_SELF_DESTRUCT
516+
+ 63 # ~Gluing opcodes
517+
)
518+
assert loop_cost == 7720
519+
final_storage_gas = (
520+
gas_costs.G_STORAGE_RESET + gas_costs.G_COLD_SLOAD + (gas_costs.G_VERY_LOW * 2)
521+
)
522+
base_costs = intrinsic_gas_cost_calc() + (gas_costs.G_VERY_LOW * 4) + final_storage_gas
523+
num_contracts = (attack_gas_limit - base_costs) // loop_cost
524+
507525
# Create a factory that deployes a new SELFDESTRUCT contract instance pre-funded depending on
508526
# the value_bearing parameter. We use CREATE2 so the caller contract can easily reproduce
509527
# the addresses in a loop for CALLs.
@@ -526,29 +544,16 @@ def test_worst_selfdestruct_existing(
526544
+ Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1))
527545
+ Op.RETURN(0, 32)
528546
)
529-
factory_address = pre.deploy_contract(code=factory_code, balance=10**18)
547+
548+
required_balance = num_contracts if value_bearing else 0 # 1 wei per contract
549+
factory_address = pre.deploy_contract(code=factory_code, balance=required_balance)
530550

531551
factory_caller_code = Op.CALLDATALOAD(0) + While(
532552
body=Op.POP(Op.CALL(address=factory_address)),
533553
condition=Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
534554
)
535555
factory_caller_address = pre.deploy_contract(code=factory_caller_code)
536556

537-
gas_costs = fork.gas_costs()
538-
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
539-
loop_cost = (
540-
gas_costs.G_KECCAK_256 # KECCAK static cost
541-
+ math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic cost for CREATE2
542-
+ gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs
543-
+ gas_costs.G_COLD_ACCOUNT_ACCESS # CALL to self-destructing contract
544-
+ gas_costs.G_SELF_DESTRUCT
545-
+ 30 # ~Gluing opcodes
546-
)
547-
num_contracts = (
548-
# Base available gas = GAS_LIMIT - intrinsic - (out of loop MSTOREs)
549-
attack_gas_limit - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4
550-
) // loop_cost
551-
552557
contracts_deployment_tx = Transaction(
553558
to=factory_caller_address,
554559
gas_limit=env.gas_limit,
@@ -568,9 +573,9 @@ def test_worst_selfdestruct_existing(
568573
+ While(
569574
body=Op.POP(Op.CALL(address=Op.SHA3(32 - 20 - 1, 85)))
570575
+ Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)),
571-
# Stop before we run out of gas for the whole tx execution.
572-
# The value was found by trial-error rounded to the next 1000 multiple.
573-
condition=Op.GT(Op.GAS, 12_000),
576+
# Only loop if we have enough gas to cover another iteration plus the
577+
# final storage gas.
578+
condition=Op.GT(Op.GAS, final_storage_gas + loop_cost),
574579
)
575580
+ Op.SSTORE(0, 42) # Done for successful tx execution assertion below.
576581
)
@@ -581,12 +586,12 @@ def test_worst_selfdestruct_existing(
581586
opcode_tx = Transaction(
582587
to=code_addr,
583588
gas_limit=attack_gas_limit,
584-
gas_price=10,
585589
sender=pre.fund_eoa(),
586590
)
587591

588592
post = {
589-
code_addr: Account(storage={0: 42}) # Check for successful execution.
593+
factory_address: Account(storage={0: num_contracts}),
594+
code_addr: Account(storage={0: 42}), # Check for successful execution.
590595
}
591596
deployed_contract_addresses = []
592597
for i in range(num_contracts):

0 commit comments

Comments
 (0)