Skip to content

Commit 9c75235

Browse files
authored
fix(tests): Fix test_worst_selfdestruct_created (#1741)
* fix(tests): test_worst_selfdestruct_created * fix: test_worst_selfdestruct_existing * Update tests/zkevm/test_worst_stateful_opcodes.py
1 parent 0c70094 commit 9c75235

File tree

1 file changed

+36
-24
lines changed

1 file changed

+36
-24
lines changed

tests/zkevm/test_worst_stateful_opcodes.py

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,23 @@ 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+
final_storage_gas = (
519+
gas_costs.G_STORAGE_RESET + gas_costs.G_COLD_SLOAD + (gas_costs.G_VERY_LOW * 2)
520+
)
521+
base_costs = intrinsic_gas_cost_calc() + (gas_costs.G_VERY_LOW * 4) + final_storage_gas
522+
num_contracts = (attack_gas_limit - base_costs) // loop_cost
523+
507524
# Create a factory that deployes a new SELFDESTRUCT contract instance pre-funded depending on
508525
# the value_bearing parameter. We use CREATE2 so the caller contract can easily reproduce
509526
# the addresses in a loop for CALLs.
@@ -526,29 +543,16 @@ def test_worst_selfdestruct_existing(
526543
+ Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1))
527544
+ Op.RETURN(0, 32)
528545
)
529-
factory_address = pre.deploy_contract(code=factory_code, balance=10**18)
546+
547+
required_balance = num_contracts if value_bearing else 0 # 1 wei per contract
548+
factory_address = pre.deploy_contract(code=factory_code, balance=required_balance)
530549

531550
factory_caller_code = Op.CALLDATALOAD(0) + While(
532551
body=Op.POP(Op.CALL(address=factory_address)),
533552
condition=Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO,
534553
)
535554
factory_caller_address = pre.deploy_contract(code=factory_caller_code)
536555

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-
552556
contracts_deployment_tx = Transaction(
553557
to=factory_caller_address,
554558
gas_limit=env.gas_limit,
@@ -568,9 +572,9 @@ def test_worst_selfdestruct_existing(
568572
+ While(
569573
body=Op.POP(Op.CALL(address=Op.SHA3(32 - 20 - 1, 85)))
570574
+ 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),
575+
# Only loop if we have enough gas to cover another iteration plus the
576+
# final storage gas.
577+
condition=Op.GT(Op.GAS, final_storage_gas + loop_cost),
574578
)
575579
+ Op.SSTORE(0, 42) # Done for successful tx execution assertion below.
576580
)
@@ -581,12 +585,12 @@ def test_worst_selfdestruct_existing(
581585
opcode_tx = Transaction(
582586
to=code_addr,
583587
gas_limit=attack_gas_limit,
584-
gas_price=10,
585588
sender=pre.fund_eoa(),
586589
)
587590

588591
post = {
589-
code_addr: Account(storage={0: 42}) # Check for successful execution.
592+
factory_address: Account(storage={0: num_contracts}),
593+
code_addr: Account(storage={0: 42}), # Check for successful execution.
590594
}
591595
deployed_contract_addresses = []
592596
for i in range(num_contracts):
@@ -616,6 +620,7 @@ def test_worst_selfdestruct_created(
616620
state_test: StateTestFiller,
617621
pre: Alloc,
618622
value_bearing: bool,
623+
fork: Fork,
619624
):
620625
"""
621626
Test running a block with as many SELFDESTRUCTs as possible for deployed contracts in
@@ -625,7 +630,11 @@ def test_worst_selfdestruct_created(
625630
pre.fund_address(env.fee_recipient, 1)
626631

627632
# SELFDESTRUCT(COINBASE) contract deployment
628-
initcode = Op.MSTORE8(0, 0x41) + Op.MSTORE8(1, 0xFF) + Op.RETURN(0, 2)
633+
initcode = (
634+
Op.MSTORE8(0, Op.COINBASE.int()) + Op.MSTORE8(1, Op.SELFDESTRUCT.int()) + Op.RETURN(0, 2)
635+
)
636+
gas_costs = fork.gas_costs()
637+
create_gas = gas_costs.G_CREATE + 20_000
629638
code = (
630639
Op.MSTORE(0, initcode.hex())
631640
+ While(
@@ -640,7 +649,7 @@ def test_worst_selfdestruct_created(
640649
),
641650
# Stop before we run out of gas for the whole tx execution.
642651
# The value was found by trial-error rounded to the next 1000 multiple.
643-
condition=Op.GT(Op.GAS, 10_000),
652+
condition=Op.GT(Op.GAS, create_gas),
644653
)
645654
+ Op.SSTORE(0, 42) # Done for successful tx execution assertion below.
646655
)
@@ -668,12 +677,15 @@ def test_worst_selfdestruct_initcode(
668677
state_test: StateTestFiller,
669678
pre: Alloc,
670679
value_bearing: bool,
680+
fork: Fork,
671681
):
672682
"""Test running a block with as many SELFDESTRUCTs as possible executed in initcode."""
673683
env = Environment()
674684
pre.fund_address(env.fee_recipient, 1)
675685

676686
initcode = Op.SELFDESTRUCT(Op.COINBASE)
687+
gas_costs = fork.gas_costs()
688+
create_gas = gas_costs.G_CREATE + 20_000
677689
code = (
678690
Op.MSTORE(0, initcode.hex())
679691
+ While(
@@ -686,7 +698,7 @@ def test_worst_selfdestruct_initcode(
686698
),
687699
# Stop before we run out of gas for the whole tx execution.
688700
# The value was found by trial-error rounded to the next 1000 multiple.
689-
condition=Op.GT(Op.GAS, 12_000),
701+
condition=Op.GT(Op.GAS, create_gas),
690702
)
691703
+ Op.SSTORE(0, 42) # Done for successful tx execution assertion below.
692704
)

0 commit comments

Comments
 (0)