Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
)

from .helpers import FACTORY_CANARY_SLOT, create_contract_via_factory
from .spec import ref_spec_8297
from .spec import Spec, ref_spec_8297

REFERENCE_SPEC_GIT_PATH = ref_spec_8297.git_path
REFERENCE_SPEC_VERSION = ref_spec_8297.version
Expand Down Expand Up @@ -314,3 +314,63 @@ def test_wrong_state_root_expectation_is_recorded_for_consumers(
)

blockchain_test(pre=pre, post={}, blocks=[block])


def test_consecutive_deploys_share_the_code_zone(
blockchain_test: BlockchainTestFiller,
pre: Alloc,
) -> None:
"""
Deploy three contracts spanning several code stems, one per block,
then call all three.

Code chunks are content-addressed, so every contract on the chain
shares one zone and each deploy after the first inserts beside stems
that are already there. A single-deploy test only ever reaches an
empty zone; what these blocks add is every deploy after it.

The three differ in length, so they occupy distinct stems and cannot
coincide by accident, and each writes its own marker on the final
block, which fails if a later deploy disturbed the code of one
deployed before it.
"""
sender = pre.fund_eoa()
marker_slot = 0
sizes = tuple(
Spec.CODE_CHUNK_SIZE * chunks
for chunks in (129, 137, Spec.STEM_SUBTREE_WIDTH)
)

runtimes: list[Bytecode] = []
deploys: list[Transaction] = []
for index, size in enumerate(sizes):
marker = index + 1
runtime = Op.SSTORE(marker_slot, marker) + Op.STOP
runtime += Op.INVALID * (size - len(runtime))
assert len(runtime) == size
runtimes.append(runtime)
deploys.append(
Transaction(
sender=sender,
to=None,
data=Initcode(deploy_code=runtime),
gas_limit=15_000_000,
)
)

deployed = [tx.created_contract for tx in deploys]
calls = [
Transaction(sender=sender, to=address, gas_limit=200_000)
for address in deployed
]

blocks = [Block(txs=[tx]) for tx in deploys]
blocks.append(Block(txs=calls))

post = {
address: Account(code=runtime, storage={marker_slot: index + 1})
for index, (address, runtime) in enumerate(
zip(deployed, runtimes, strict=True)
)
}
blockchain_test(pre=pre, blocks=blocks, post=post)
Loading