Skip to content

test_factory_absent_across_transition()

Documentation for tests/amsterdam/eip7997_deterministic_factory_predeploy/test_fork_transition.py::test_factory_absent_across_transition@26332146.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip7997_deterministic_factory_predeploy/test_fork_transition.py::test_factory_absent_across_transition --fork Amsterdam

A chain that never deployed the factory transitions to Amsterdam through valid blocks, and the factory address stays nonexistent.

The client MUST NOT check for the existence of the contract at the fork boundary. Therefore, we verify that the BAL does not contain the factory account read. The block itself is valid. It is the responsibility of the chain activating EIP-7997 to ensure the factory is valid at the start of the fork block.

Source code in tests/amsterdam/eip7997_deterministic_factory_predeploy/test_fork_transition.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
@pytest.mark.valid_at_transition_to("Amsterdam")
@pytest.mark.pre_alloc_mutable
def test_factory_absent_across_transition(
    blockchain_test: BlockchainTestFiller,
    pre: Alloc,
) -> None:
    """
    A chain that never deployed the factory transitions to Amsterdam
    through valid blocks, and the factory address stays nonexistent.

    The client MUST NOT check for the existence of the contract at
    the fork boundary. Therefore, we verify that the BAL does
    not contain the factory account read.
    The block itself is valid. It is the responsibility of the
    chain activating EIP-7997 to ensure the factory is valid
    at the start of the fork block.
    """
    factory = Address(Spec.FACTORY_ADDRESS)
    # Merging an all-zero account into the fork's pre-allocation removes
    # the factory predeploy from the genesis allocation entirely.
    pre[factory] = Account(nonce=0, balance=0, code=b"")

    sender = pre.fund_eoa()
    receiver = pre.fund_eoa(amount=0)
    transfer_value = 1

    timestamps = [FORK_TIMESTAMP - 1, FORK_TIMESTAMP, FORK_TIMESTAMP + 1]

    blocks = []
    for i, timestamp in enumerate(timestamps):
        blocks.append(
            Block(
                timestamp=timestamp,
                txs=[
                    Transaction(
                        sender=sender,
                        to=receiver,
                        value=transfer_value,
                    )
                ],
                expected_block_access_list=BlockAccessListExpectation(
                    account_expectations={
                        factory: None,
                        sender: BalAccountExpectation(
                            nonce_changes=[
                                BalNonceChange(
                                    block_access_index=1,
                                    post_nonce=i + 1,
                                )
                            ],
                        ),
                    }
                )
                if timestamp >= FORK_TIMESTAMP
                else None,
            )
        )

    blockchain_test(
        pre=pre,
        blocks=blocks,
        post={
            factory: Account.NONEXISTENT,
            receiver: Account(balance=len(timestamps) * transfer_value),
        },
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.