44""" # noqa: E501
55
66from enum import Enum
7+ from hashlib import sha256
78from itertools import count
89from typing import List
910
3233 Storage ,
3334 Transaction ,
3435 TransactionException ,
36+ call_return_code ,
3537 compute_create_address ,
3638)
3739from ethereum_test_tools .eof .v1 import Container , Section
3840
41+ from ..eip6110_deposits .helpers import DepositRequest
42+ from ..eip7002_el_triggerable_withdrawals .helpers import WithdrawalRequest
43+ from ..eip7251_consolidations .helpers import ConsolidationRequest
3944from .spec import Spec , ref_spec_7702
4045
4146REFERENCE_SPEC_GIT_PATH = ref_spec_7702 .git_path
@@ -2015,6 +2020,19 @@ def test_set_code_to_precompile(
20152020 )
20162021
20172022
2023+ def deposit_contract_initial_storage () -> Storage :
2024+ """
2025+ Return the initial storage of the deposit contract.
2026+ """
2027+ storage = Storage ()
2028+ DEPOSIT_CONTRACT_TREE_DEPTH = 32
2029+ next_hash = sha256 (b"\x00 " * 64 ).digest ()
2030+ for i in range (DEPOSIT_CONTRACT_TREE_DEPTH + 2 , DEPOSIT_CONTRACT_TREE_DEPTH * 2 + 1 ):
2031+ storage [i ] = next_hash
2032+ next_hash = sha256 (next_hash + next_hash ).digest ()
2033+ return storage
2034+
2035+
20182036@pytest .mark .with_all_call_opcodes (
20192037 lambda opcode : opcode
20202038 not in [Op .STATICCALL , Op .CALLCODE , Op .DELEGATECALL , Op .EXTDELEGATECALL , Op .EXTSTATICCALL ]
@@ -2029,48 +2047,94 @@ def test_set_code_to_system_contract(
20292047 """
20302048 Test setting the code of an account to a pre-compile address.
20312049 """
2032- auth_signer = pre .fund_eoa (auth_account_start_balance )
2033-
20342050 caller_code_storage = Storage ()
2035- call_return_code_slot = caller_code_storage .store_next (True )
2036- call_return_data_size_slot = caller_code_storage .store_next (0 )
2037- caller_code = (
2038- Op .SSTORE (call_return_code_slot , call_opcode (address = auth_signer ))
2039- + Op .SSTORE (call_return_data_size_slot , Op .RETURNDATASIZE )
2040- + Op .STOP
2051+ call_return_code_slot = caller_code_storage .store_next (
2052+ call_return_code (
2053+ call_opcode ,
2054+ True ,
2055+ )
20412056 )
2042- txs : List [Transaction ] = []
2057+ call_return_data_size_slot = caller_code_storage .store_next (0 )
2058+
2059+ call_value = 0
2060+
2061+ # Setup the initial storage of the account to mimic the system contract if required
20432062 match system_contract :
2063+ case Address (0x00000000219AB540356CBB839CBE05303D7705FA ): # EIP-6110
2064+ # Deposit contract needs specific storage values, so we set them on the account
2065+ auth_signer = pre .fund_eoa (
2066+ auth_account_start_balance , storage = deposit_contract_initial_storage ()
2067+ )
20442068 case Address (0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02 ): # EIP-4788
2045- caller_payload = Hash (0 )
2046- caller_code_storage [call_return_data_size_slot ] = 0
2069+ auth_signer = pre .fund_eoa (auth_account_start_balance , storage = Storage ({1 : 1 }))
2070+ case _:
2071+ # Pre-fund without storage
2072+ auth_signer = pre .fund_eoa (auth_account_start_balance )
2073+
2074+ # Fabricate the payload for the system contract
2075+ match system_contract :
2076+ case Address (0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02 ): # EIP-4788
2077+ caller_payload = Hash (1 )
2078+ caller_code_storage [call_return_data_size_slot ] = 32
20472079 case Address (0x00000000219AB540356CBB839CBE05303D7705FA ): # EIP-6110
2048- caller_payload = Hash (0 )
2049- caller_code_storage [call_return_data_size_slot ] = 0
2080+ # Fabricate a valid deposit request to the set-code account
2081+ deposit_request = DepositRequest (
2082+ pubkey = 0x01 ,
2083+ withdrawal_credentials = 0x02 ,
2084+ amount = 1_000_000_000 ,
2085+ signature = 0x03 ,
2086+ index = 0x0 ,
2087+ )
2088+ caller_payload = deposit_request .calldata
2089+ call_value = deposit_request .value
20502090 case Address (0x00A3CA265EBCB825B45F985A16CEFB49958CE017 ): # EIP-7002
2051- caller_payload = Hash (0 )
2052- caller_code_storage [call_return_data_size_slot ] = 0
2091+ # Fabricate a valid withdrawal request to the set-code account
2092+ withdrawal_request = WithdrawalRequest (
2093+ source_address = 0x01 ,
2094+ validator_pubkey = 0x02 ,
2095+ amount = 0x03 ,
2096+ fee = 0x01 ,
2097+ )
2098+ caller_payload = withdrawal_request .calldata
2099+ call_value = withdrawal_request .value
20532100 case Address (0x00B42DBF2194E931E80326D950320F7D9DBEAC02 ): # EIP-7251
2054- caller_payload = Hash (0 )
2055- caller_code_storage [call_return_data_size_slot ] = 0
2101+ # Fabricate a valid consolidation request to the set-code account
2102+ consolidation_request = ConsolidationRequest (
2103+ source_address = 0x01 ,
2104+ source_pubkey = 0x02 ,
2105+ target_pubkey = 0x03 ,
2106+ fee = 0x01 ,
2107+ )
2108+ caller_payload = consolidation_request .calldata
2109+ call_value = consolidation_request .value
20562110 case Address (0x0AAE40965E6800CD9B1F4B05FF21581047E3F91E ): # EIP-2935
20572111 caller_payload = Hash (0 )
2058- caller_code_storage [call_return_data_size_slot ] = 0
2112+ caller_code_storage [call_return_data_size_slot ] = 32
20592113 case _:
2060- raise ValueError (f"Unsupported system contract: { system_contract } " )
2114+ raise ValueError (f"Not implemented system contract: { system_contract } " )
20612115
2116+ caller_code = (
2117+ Op .CALLDATACOPY (0 , 0 , Op .CALLDATASIZE )
2118+ + Op .SSTORE (
2119+ call_return_code_slot ,
2120+ call_opcode (address = auth_signer , value = call_value , args_size = Op .CALLDATASIZE ),
2121+ )
2122+ + Op .SSTORE (call_return_data_size_slot , Op .RETURNDATASIZE )
2123+ + Op .STOP
2124+ )
20622125 caller_code_address = pre .deploy_contract (caller_code )
20632126
2064- txs + = [
2127+ txs = [
20652128 Transaction (
20662129 sender = pre .fund_eoa (),
20672130 gas_limit = 500_000 ,
20682131 to = caller_code_address ,
2132+ value = call_value ,
20692133 data = caller_payload ,
20702134 authorization_list = [
20712135 AuthorizationTuple (
20722136 address = Address (system_contract ),
2073- nonce = 0 ,
2137+ nonce = auth_signer . nonce ,
20742138 signer = auth_signer ,
20752139 ),
20762140 ],
@@ -2079,10 +2143,15 @@ def test_set_code_to_system_contract(
20792143
20802144 blockchain_test (
20812145 pre = pre ,
2082- blocks = [Block (txs = txs )],
2146+ blocks = [
2147+ Block (
2148+ txs = txs ,
2149+ requests_root = [], # Verify nothing slipped into the requests trie
2150+ )
2151+ ],
20832152 post = {
20842153 auth_signer : Account (
2085- nonce = 1 ,
2154+ nonce = auth_signer . nonce + 1 ,
20862155 code = b"" ,
20872156 ),
20882157 caller_code_address : Account (
0 commit comments