1
1
from hexbytes import HexBytes
2
2
from ethproto import aa_bundler
3
3
from web3 .constants import HASH_ZERO
4
- from unittest .mock import MagicMock
4
+ from unittest .mock import MagicMock , patch
5
5
6
6
7
7
def test_pack_two ():
@@ -21,9 +21,10 @@ def test_pack_two():
21
21
CHAIN_ID = 31337
22
22
ENTRYPOINT = "0x0000000071727De22E5E9d8BAf0edAc6f37da032"
23
23
24
+ TEST_SENDER = "0x8961423b54f06bf6D57F8dD3dD1184FA6F3aac3f"
24
25
25
26
user_operation = {
26
- "sender" : "0x515f3Db6c4249919B74eA55915969944fEA4B311" ,
27
+ "sender" : TEST_SENDER ,
27
28
"nonce" : 0 ,
28
29
"initCode" : "0x" ,
29
30
"callData" : TEST_CALL_DATA ,
@@ -41,7 +42,7 @@ def test_pack_two():
41
42
42
43
def test_pack_user_operation ():
43
44
expected = {
44
- "sender" : "0x515f3Db6c4249919B74eA55915969944fEA4B311" ,
45
+ "sender" : TEST_SENDER ,
45
46
"nonce" : 0 ,
46
47
"initCode" : "0x" ,
47
48
"callData" : TEST_CALL_DATA ,
@@ -57,20 +58,126 @@ def test_pack_user_operation():
57
58
def test_hash_packed_user_operation ():
58
59
packed = aa_bundler .pack_user_operation (user_operation )
59
60
hash = aa_bundler .hash_packed_user_operation_only (packed )
60
- assert hash == "0xb3c6cda6d25de5a793bc280200673119f76f92017c97dacd26bc1329771b96a4 "
61
+ assert hash == "0xa2c19765d18b0d690c05b20061bd23d066201aff1833a51bd28af115fbd4bcd9 "
61
62
hash = aa_bundler .hash_packed_user_operation (packed , CHAIN_ID , ENTRYPOINT )
62
- assert hash == "0x213b6b5f785983fa3310d6ae06e63ff883915ad5454dd422e15d9778a9e1da48 "
63
+ assert hash == "0xb365ad4d366e9081718e926912da7a78a2faae592286fda0cc11923bd141b7cf "
63
64
64
65
65
66
def test_sign_user_operation ():
66
67
signature = aa_bundler .sign_user_operation (TEST_PRIVATE_KEY , user_operation , CHAIN_ID , ENTRYPOINT )
67
68
assert (
68
69
signature
69
- == "0x9a2e58cbe1d7c79b933c115e6d041fca080c5a1f572b78116c36b956faf9bf660b4fc10f339fd608d11b56072407bb29d311edb3a79f312f6f8375a97692870d1b " # noqa
70
+ == "0xb9b872bfe4e90f4628e8ec24879a5b01045f91da8457f3ce2b417d2e5774b508261ec1147a820e75a141cb61b884a78d7e88996ceddafb9a7016cfe7a48a1f4f1b " # noqa
70
71
)
71
72
72
73
73
- def test_send_transaction ():
74
+ def test_sign_user_operation_gas_diff ():
75
+ user_operation_2 = dict (user_operation )
76
+ user_operation_2 ["maxPriorityFeePerGas" ] -= 1
77
+ signature = aa_bundler .sign_user_operation (TEST_PRIVATE_KEY , user_operation_2 , CHAIN_ID , ENTRYPOINT )
78
+ assert (
79
+ signature
80
+ == "0x8162479d2dbd18d7fe93a2f51e283021d6e4eae4f57d20cdd553042723a0b0ea690ab3903d45126b0047da08ab53dfdf86656e4f258ac4936ba96a759ccb77f61b" # noqa
81
+ )
82
+
83
+
84
+ def test_make_nonce ():
85
+ assert aa_bundler .make_nonce (0 , 0 ) == 0
86
+ assert aa_bundler .make_nonce (0 , 1 ) == 1
87
+ assert aa_bundler .make_nonce (1 , 1 ) == (1 << 64 ) + 1
88
+
89
+
90
+ FAIL_IF_USED = object ()
91
+
92
+
93
+ @patch .object (aa_bundler .random , "randint" )
94
+ @patch .object (aa_bundler , "fetch_nonce" )
95
+ def test_get_nonce_force_fetch (fetch_nonce_mock , randint_mock ):
96
+ # Test fetch=True
97
+ fetch_nonce_mock .return_value = 123
98
+ assert aa_bundler .get_nonce_and_key (
99
+ FAIL_IF_USED ,
100
+ {"nonceKey" : 12 , "from" : TEST_SENDER },
101
+ nonce_mode = aa_bundler .NonceMode .FIXED_KEY_LOCAL_NONCE ,
102
+ fetch = True ,
103
+ ) == (12 , 123 )
104
+ fetch_nonce_mock .assert_called_once_with (FAIL_IF_USED , TEST_SENDER , ENTRYPOINT , 12 )
105
+ randint_mock .assert_not_called ()
106
+
107
+
108
+ @patch .object (aa_bundler .random , "randint" )
109
+ @patch .object (aa_bundler , "fetch_nonce" )
110
+ def test_get_nonce_fetch_always_mode (fetch_nonce_mock , randint_mock ):
111
+ # Test nonce_mode=NonceMode.FIXED_KEY_FETCH_ALWAYS
112
+ fetch_nonce_mock .return_value = 111
113
+ assert aa_bundler .get_nonce_and_key (
114
+ FAIL_IF_USED ,
115
+ {"nonceKey" : 22 , "from" : TEST_SENDER },
116
+ nonce_mode = aa_bundler .NonceMode .FIXED_KEY_FETCH_ALWAYS ,
117
+ ) == (22 , 111 )
118
+ fetch_nonce_mock .assert_called_once_with (FAIL_IF_USED , TEST_SENDER , ENTRYPOINT , 22 )
119
+ randint_mock .assert_not_called ()
120
+ fetch_nonce_mock .reset_mock ()
121
+
122
+
123
+ @patch .object (aa_bundler .random , "randint" )
124
+ @patch .object (aa_bundler , "fetch_nonce" )
125
+ def test_get_nonce_nonce_key_in_tx (fetch_nonce_mock , randint_mock ):
126
+ # Test nonce_mode=NonceMode.FIXED_KEY_LOCAL_NONCE
127
+ assert aa_bundler .get_nonce_and_key (
128
+ FAIL_IF_USED ,
129
+ {"nonceKey" : 22 , "from" : TEST_SENDER },
130
+ nonce_mode = aa_bundler .NonceMode .FIXED_KEY_LOCAL_NONCE ,
131
+ ) == (22 , 0 )
132
+ randint_mock .assert_not_called ()
133
+ fetch_nonce_mock .assert_not_called ()
134
+
135
+ # Same if nonce_mode=NonceMode.RANDOM_KEY but nonceKey in the tx
136
+ assert aa_bundler .get_nonce_and_key (
137
+ FAIL_IF_USED ,
138
+ {"nonceKey" : 22 , "from" : TEST_SENDER },
139
+ nonce_mode = aa_bundler .NonceMode .RANDOM_KEY ,
140
+ ) == (22 , 0 )
141
+ randint_mock .assert_not_called ()
142
+ fetch_nonce_mock .assert_not_called ()
143
+
144
+
145
+ @patch .object (aa_bundler .random , "randint" )
146
+ @patch .object (aa_bundler , "fetch_nonce" )
147
+ def test_get_nonce_random_key_mode (fetch_nonce_mock , randint_mock ):
148
+ # If nonce_mode=NonceMode.RANDOM_KEY creates a random key and stores it
149
+ randint_mock .return_value = 444
150
+ assert aa_bundler .get_nonce_and_key (
151
+ FAIL_IF_USED ,
152
+ {"from" : TEST_SENDER },
153
+ nonce_mode = aa_bundler .NonceMode .RANDOM_KEY ,
154
+ ) == (444 , 0 )
155
+ fetch_nonce_mock .assert_not_called ()
156
+ randint_mock .assert_called_with (1 , 2 ** 192 - 1 )
157
+ randint_mock .reset_mock ()
158
+ assert aa_bundler .RANDOM_NONCE_KEY == 444
159
+ aa_bundler .RANDOM_NONCE_KEY = None # cleanup
160
+
161
+
162
+ @patch .object (aa_bundler .random , "randint" )
163
+ @patch .object (aa_bundler , "fetch_nonce" )
164
+ def test_get_nonce_with_local_cache (fetch_nonce_mock , randint_mock ):
165
+ with patch .object (aa_bundler , "AA_BUNDLER_NONCE_KEY" , new = 55 ), patch .object (
166
+ aa_bundler , "NONCE_CACHE" , new = {55 : 33 }
167
+ ):
168
+ # Test nonce_mode=NonceMode.FIXED_KEY_LOCAL_NONCE
169
+ assert aa_bundler .get_nonce_and_key (
170
+ FAIL_IF_USED ,
171
+ {"from" : TEST_SENDER },
172
+ nonce_mode = aa_bundler .NonceMode .FIXED_KEY_LOCAL_NONCE ,
173
+ ) == (55 , 33 )
174
+ randint_mock .assert_not_called ()
175
+ fetch_nonce_mock .assert_not_called ()
176
+
177
+
178
+ @patch .object (aa_bundler , "get_base_fee" )
179
+ def test_send_transaction (get_base_fee_mock ):
180
+ get_base_fee_mock .return_value = 0
74
181
w3 = MagicMock ()
75
182
w3 .eth .chain_id = CHAIN_ID
76
183
@@ -91,8 +198,8 @@ def make_request(method, params):
91
198
assert params [0 ] == {
92
199
"sender" : "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9" ,
93
200
"nonce" : "0x0" ,
94
- "callData" : "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000" ,
95
- "signature" : "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c" ,
201
+ "callData" : "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000" , # noqa
202
+ "signature" : "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c" , # noqa
96
203
}
97
204
return {
98
205
"jsonrpc" : "2.0" ,
@@ -113,13 +220,13 @@ def make_request(method, params):
113
220
assert params [0 ] == {
114
221
"sender" : "0xE8B412158c205B0F605e0FC09dCdA27d3F140FE9" ,
115
222
"nonce" : "0x0" ,
116
- "callData" : "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000" ,
223
+ "callData" : "0xb61d27f60000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007ace242f32208d836a2245df957c08547059bf45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000" , # noqa
117
224
"callGasLimit" : "0xcbb8" ,
118
225
"verificationGasLimit" : "0x13664" ,
119
226
"preVerificationGas" : "0xb430" ,
120
227
"maxFeePerGas" : "0x7ffffffff" ,
121
228
"maxPriorityFeePerGas" : "0x7ffffffff" ,
122
- "signature" : "0x7980544d044bc1202fed7edec96f2fa795ab8670b439935e6bbb5104e95d84ea32af8bff187913ff7eb2b442baab06d0c300273942e312332659ab0a194bbbe81c" ,
229
+ "signature" : "0x7980544d044bc1202fed7edec96f2fa795ab8670b439935e6bbb5104e95d84ea32af8bff187913ff7eb2b442baab06d0c300273942e312332659ab0a194bbbe81c" , # noqa
123
230
}
124
231
return {
125
232
"jsonrpc" : "2.0" ,
@@ -130,4 +237,6 @@ def make_request(method, params):
130
237
w3 .provider .make_request .side_effect = make_request
131
238
132
239
ret = aa_bundler .send_transaction (w3 , tx )
240
+ get_base_fee_mock .assert_called_once_with (w3 )
241
+ assert aa_bundler .NONCE_CACHE [0 ] == 1
133
242
assert ret == "0xa950a17ca1ed83e974fb1aa227360a007cb65f566518af117ffdbb04d8d2d524"
0 commit comments