1313 Alloc ,
1414 Block ,
1515 BlockchainTestFiller ,
16+ Bytecode ,
1617 Transaction ,
1718)
19+ from ethereum_test_tools import Opcodes as Op
1820from ethereum_test_types import Requests
1921
2022from .helpers import (
@@ -41,6 +43,26 @@ def single_withdrawal_with_custom_fee(i: int) -> WithdrawalRequest: # noqa: D10
4143@pytest .mark .parametrize (
4244 "requests_list" ,
4345 [
46+ pytest .param (
47+ [],
48+ id = "empty_request_list" ,
49+ ),
50+ pytest .param (
51+ [single_withdrawal_with_custom_fee (0 )],
52+ id = "1_withdrawal_request" ,
53+ ),
54+ pytest .param (
55+ [
56+ * [
57+ single_withdrawal_with_custom_fee (i )
58+ for i in range (
59+ 0 ,
60+ 15 ,
61+ )
62+ ],
63+ ],
64+ id = "15_withdrawal_requests" ,
65+ ),
4466 pytest .param (
4567 [
4668 * [
@@ -109,3 +131,126 @@ def test_extra_withdrawals(
109131 ],
110132 post = {},
111133 )
134+
135+
136+ @pytest .mark .parametrize (
137+ "requests_list" ,
138+ [
139+ pytest .param (
140+ [],
141+ id = "empty_request_list" ,
142+ ),
143+ pytest .param (
144+ [single_withdrawal_with_custom_fee (0 )],
145+ id = "1_withdrawal_request" ,
146+ ),
147+ pytest .param (
148+ [
149+ * [
150+ single_withdrawal_with_custom_fee (i )
151+ for i in range (
152+ 0 ,
153+ 15 ,
154+ )
155+ ],
156+ ],
157+ id = "15_withdrawal_requests" ,
158+ ),
159+ pytest .param (
160+ [
161+ * [
162+ single_withdrawal_with_custom_fee (i )
163+ for i in range (
164+ 0 ,
165+ 16 ,
166+ )
167+ ],
168+ ],
169+ id = "16_withdrawal_requests" ,
170+ ),
171+ pytest .param (
172+ [
173+ * [
174+ single_withdrawal_with_custom_fee (i )
175+ for i in range (
176+ 0 ,
177+ 17 ,
178+ )
179+ ],
180+ ],
181+ id = "17_withdrawal_requests" ,
182+ ),
183+ pytest .param (
184+ [
185+ * [
186+ single_withdrawal_with_custom_fee (i )
187+ for i in range (
188+ 0 ,
189+ 18 ,
190+ )
191+ ],
192+ ],
193+ id = "18_withdrawal_requests" ,
194+ ),
195+ ],
196+ )
197+ def test_extra_withdrawals_pseudo_contract (
198+ blockchain_test : BlockchainTestFiller ,
199+ pre : Alloc ,
200+ requests_list : List [WithdrawalRequest ],
201+ ):
202+ """Test how clients were to behave when more than 16 withdrawals would be allowed per block."""
203+ modified_code : Bytecode = Bytecode ()
204+ memory_offset : int = 0
205+
206+ # Goal: Have contract return a bunch of withdrawal requests
207+ # Problem: EVM has no concept of withdrawal request, it just return bytes from memory
208+ # Problem: How to get __bytes__ from withdrawal request
209+ # Problem: How to know exact size of withdrawal requests byte representation
210+ # Problem: If size larger than 32 bytes how to split across multiple MSTOREs?
211+
212+ # what size does a withdrawal_request bytes representation have?
213+ # withdrawal_request.__bytes__:
214+ # bytes(self.source_address) -> 20 bytes
215+ # + bytes(self.validator_pubkey) -> 48 bytes
216+ # + self.amount.to_bytes(8, "little") -> 8 bytes
217+ # -> Total: 76 bytes
218+ for withdrawal_request in requests_list :
219+ withdrawal_request_chunk_1_3_32bytes : bytes = withdrawal_request .__bytes__ ()[:32 ]
220+ withdrawal_request_chunk_2_3_32bytes : bytes = withdrawal_request .__bytes__ ()[32 :64 ]
221+ withdrawal_request_chunk_3_3_12bytes : bytes = withdrawal_request .__bytes__ ()[64 :]
222+
223+ modified_code += Op .MSTORE (memory_offset , withdrawal_request_chunk_1_3_32bytes )
224+ memory_offset += 32
225+
226+ modified_code += Op .MSTORE (memory_offset , withdrawal_request_chunk_2_3_32bytes )
227+ memory_offset += 32
228+
229+ modified_code += Op .MSTORE (memory_offset , withdrawal_request_chunk_3_3_12bytes )
230+ memory_offset += 12
231+
232+ modified_code += Op .RETURN (0 , 76 )
233+
234+ pre [Spec_EIP7002 .WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS ] = Account (
235+ code = modified_code ,
236+ nonce = 1 ,
237+ balance = 0 ,
238+ )
239+
240+ # given a list of withdrawal requests construct a withdrawal request transaction
241+ withdrawal_request_transaction = WithdrawalRequestTransaction (requests = requests_list )
242+ # prepare withdrawal senders
243+ withdrawal_request_transaction .update_pre (pre = pre )
244+ # get transaction list
245+ txs : List [Transaction ] = withdrawal_request_transaction .transactions ()
246+
247+ blockchain_test (
248+ pre = pre ,
249+ blocks = [
250+ Block (
251+ txs = txs ,
252+ requests_hash = Requests (* requests_list ),
253+ ),
254+ ],
255+ post = {},
256+ )
0 commit comments