1616 Bytecode ,
1717 Transaction ,
1818)
19+ from ethereum_test_tools import Macros as Om
1920from ethereum_test_tools import Opcodes as Op
2021from ethereum_test_types import Requests
2122
3233REFERENCE_SPEC_VERSION : str = ref_spec_7002 .version
3334
3435
35- def single_withdrawal_with_custom_fee (i : int ) -> WithdrawalRequest : # noqa: D103
36- return WithdrawalRequest (
37- validator_pubkey = i + 1 ,
38- amount = 0 ,
39- fee = Spec_EIP7002 .get_fee (0 ),
40- )
36+ def withdrawal_list_with_custom_fee (n : int ) -> List [WithdrawalRequest ]: # noqa: D103
37+ return [
38+ WithdrawalRequest (
39+ validator_pubkey = i + 1 ,
40+ amount = 0 ,
41+ fee = Spec_EIP7002 .get_fee (0 ),
42+ )
43+ for i in range (n )
44+ ]
4145
4246
4347@pytest .mark .parametrize (
@@ -48,54 +52,32 @@ def single_withdrawal_with_custom_fee(i: int) -> WithdrawalRequest: # noqa: D10
4852 id = "empty_request_list" ,
4953 ),
5054 pytest .param (
51- [single_withdrawal_with_custom_fee (0 )],
55+ [
56+ * withdrawal_list_with_custom_fee (1 ),
57+ ],
5258 id = "1_withdrawal_request" ,
5359 ),
5460 pytest .param (
5561 [
56- * [
57- single_withdrawal_with_custom_fee (i )
58- for i in range (
59- 0 ,
60- 15 ,
61- )
62- ],
62+ * withdrawal_list_with_custom_fee (15 ),
6363 ],
6464 id = "15_withdrawal_requests" ,
6565 ),
6666 pytest .param (
6767 [
68- * [
69- single_withdrawal_with_custom_fee (i )
70- for i in range (
71- 0 ,
72- 16 ,
73- )
74- ],
68+ * withdrawal_list_with_custom_fee (16 ),
7569 ],
7670 id = "16_withdrawal_requests" ,
7771 ),
7872 pytest .param (
7973 [
80- * [
81- single_withdrawal_with_custom_fee (i )
82- for i in range (
83- 0 ,
84- 17 ,
85- )
86- ],
74+ * withdrawal_list_with_custom_fee (17 ),
8775 ],
8876 id = "17_withdrawal_requests" ,
8977 ),
9078 pytest .param (
9179 [
92- * [
93- single_withdrawal_with_custom_fee (i )
94- for i in range (
95- 0 ,
96- 18 ,
97- )
98- ],
80+ * withdrawal_list_with_custom_fee (18 ),
9981 ],
10082 id = "18_withdrawal_requests" ,
10183 ),
@@ -106,7 +88,8 @@ def test_extra_withdrawals(
10688 pre : Alloc ,
10789 requests_list : List [WithdrawalRequest ],
10890):
109- """Test how clients were to behave when more than 16 withdrawals would be allowed per block."""
91+ """Test how clients were to behave when more than 16 withdrawals (here: 18 withdrawals) would be allowed per block.""" # noqa: E501
92+ # Source of code (change value of this line to 18 and re-compile with fjl/geas): https://github.com/lightclient/sys-asm/blob/f1c13e285b6aeef2b19793995e00861bf0f32c9a/src/withdrawals/main.eas#L37 # noqa: E501, W291
11093 modified_code : bytes = b"3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060121160df575060125b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd" # noqa: E501
11194 pre [Spec_EIP7002 .WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS ] = Account (
11295 code = modified_code ,
@@ -141,54 +124,32 @@ def test_extra_withdrawals(
141124 id = "empty_request_list" ,
142125 ),
143126 pytest .param (
144- [single_withdrawal_with_custom_fee (0 )],
127+ [
128+ * withdrawal_list_with_custom_fee (1 ),
129+ ],
145130 id = "1_withdrawal_request" ,
146131 ),
147132 pytest .param (
148133 [
149- * [
150- single_withdrawal_with_custom_fee (i )
151- for i in range (
152- 0 ,
153- 15 ,
154- )
155- ],
134+ * withdrawal_list_with_custom_fee (15 ),
156135 ],
157136 id = "15_withdrawal_requests" ,
158137 ),
159138 pytest .param (
160139 [
161- * [
162- single_withdrawal_with_custom_fee (i )
163- for i in range (
164- 0 ,
165- 16 ,
166- )
167- ],
140+ * withdrawal_list_with_custom_fee (16 ),
168141 ],
169142 id = "16_withdrawal_requests" ,
170143 ),
171144 pytest .param (
172145 [
173- * [
174- single_withdrawal_with_custom_fee (i )
175- for i in range (
176- 0 ,
177- 17 ,
178- )
179- ],
146+ * withdrawal_list_with_custom_fee (17 ),
180147 ],
181148 id = "17_withdrawal_requests" ,
182149 ),
183150 pytest .param (
184151 [
185- * [
186- single_withdrawal_with_custom_fee (i )
187- for i in range (
188- 0 ,
189- 18 ,
190- )
191- ],
152+ * withdrawal_list_with_custom_fee (18 ),
192153 ],
193154 id = "18_withdrawal_requests" ,
194155 ),
@@ -204,37 +165,24 @@ def test_extra_withdrawals_pseudo_contract(
204165 memory_offset : int = 0
205166 amount_of_requests : int = 0
206167
207- # Goal: Have contract return a bunch of withdrawal requests
208- # Problem: EVM has no concept of withdrawal request, it just return bytes from memory
209- # Problem: How to get __bytes__ from withdrawal request
210- # Problem: How to know exact size of withdrawal requests byte representation
211- # Problem: If size larger than 32 bytes how to split across multiple MSTOREs?
212168
213- # what size does a withdrawal_request bytes representation have?
214- # withdrawal_request.__bytes__:
215- # bytes(self.source_address) -> 20 bytes
216- # + bytes(self.validator_pubkey) -> 48 bytes
217- # + self.amount.to_bytes(8, "little") -> 8 bytes
218- # -> Total: 76 bytes
219169 for withdrawal_request in requests_list :
220- withdrawal_request_chunk_1_3_32bytes : bytes = withdrawal_request .__bytes__ ()[:32 ]
221- withdrawal_request_chunk_2_3_32bytes : bytes = withdrawal_request .__bytes__ ()[32 :64 ]
222- withdrawal_request_chunk_3_3_12bytes : bytes = withdrawal_request .__bytes__ ()[64 :]
223-
224- modified_code += Op .MSTORE (memory_offset , withdrawal_request_chunk_1_3_32bytes )
225- memory_offset += 32
226-
227- modified_code += Op .MSTORE (memory_offset , withdrawal_request_chunk_2_3_32bytes )
228- memory_offset += 32
229-
230- modified_code += Op .MSTORE (memory_offset , withdrawal_request_chunk_3_3_12bytes )
231- # memory_offset += 32 # MSTORE ALWAYS writes 32 bytes, no need to update memory offset tho
232-
170+ # update memory_offset with the correct value
171+ withdrawal_request_bytes_amount : int = len (bytes (withdrawal_request ))
172+ assert withdrawal_request_bytes_amount == 76 , f"Expected withdrawal request to be of size 76 but got size { withdrawal_request_bytes_amount } " # noqa: E501
173+ memory_offset += withdrawal_request_bytes_amount
174+
175+ # TODO: in opcodes.py the argument order and names of arguments are different from those
176+ # on evm.codes website. this is dangerous, especially since with the macro I am not allowed
177+ # to provide the parameters as named parameters like
178+ # Om.MSTORE(data=bytes(withdrawal_request), offset=memory_offset)
179+ # due to 'unexpected keyword argument.. for __call__ of'
180+ modified_code += Om .MSTORE (bytes (withdrawal_request ), memory_offset )
233181 amount_of_requests += 1
234182
235183 modified_code += Op .RETURN (
236184 0 , 76 * amount_of_requests
237- ) # don't care about the zeroes added by MSTORE at [76,96] bytes
185+ )
238186
239187 pre [Spec_EIP7002 .WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS ] = Account (
240188 code = modified_code ,
0 commit comments