1111 EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY ,
1212)
1313from utils .dsm import UnvetArgs , to_bytes , set_single_guardian
14- from utils .evm_script import encode_error
1514from utils .staking_module import calc_module_reward_shares
1615from utils .test .csm_helpers import csm_add_node_operator , csm_upload_keys , get_ics_members , csm_add_ics_node_operator
1716from utils .test .deposits_helpers import fill_deposit_buffer
@@ -82,9 +81,28 @@ def strikes():
8281
8382
8483@pytest .fixture
85- def node_operator (csm , permissionless_gate , accounting , accounts ) -> int :
86- address = accounts [7 ].address
87- return csm_add_node_operator (csm , permissionless_gate , accounting , address )
84+ def depositable_node_operator (csm , accounting , permissionless_gate , stranger ):
85+ increase_staking_module_share (module_id = CSM_MODULE_ID , share_multiplier = 2 )
86+ csm .cleanDepositQueue (2 * csm .getNonce (), {"from" : stranger .address })
87+ for queue_priority in range (1 , 6 ):
88+ deposit_batch = csm .depositQueueItem (queue_priority , csm .depositQueuePointers (queue_priority )["head" ])
89+ if deposit_batch :
90+ node_operator_id = (deposit_batch >> 192 ) & ((1 << 64 ) - 1 )
91+ keys_count = (deposit_batch >> 128 ) & ((1 << 64 ) - 1 )
92+ break
93+ else :
94+ address = accounts [7 ].address
95+ keys_count = 5
96+ node_operator_id = csm_add_node_operator (csm , permissionless_gate , accounting , address , keys_count = keys_count )
97+ return node_operator_id , keys_count
98+
99+
100+ @pytest .fixture
101+ def node_operator (depositable_node_operator , csm , accounting ) -> int :
102+ node_operator , keys_count = depositable_node_operator
103+ fill_deposit_buffer (keys_count )
104+ contracts .lido .deposit (keys_count , CSM_MODULE_ID , "0x" , {"from" : contracts .deposit_security_module })
105+ return node_operator
88106
89107
90108@pytest .fixture
@@ -103,28 +121,6 @@ def remove_stake_limit():
103121 contracts .lido .removeStakingLimit ({"from" : accounts .at (contracts .agent , force = True )})
104122
105123
106- @pytest .fixture
107- def deposits_to_csm (csm , pause_modules , node_operator , remove_stake_limit ):
108- (_ , _ , depositable ) = csm .getStakingModuleSummary ()
109- fill_deposit_buffer (depositable )
110- increase_staking_module_share (module_id = CSM_MODULE_ID , share_multiplier = 2 )
111-
112- if contracts .withdrawal_queue .isBunkerModeActive ():
113- # Disable bunker mode to allow deposits
114- web3 .provider .make_request (
115- "hardhat_setStorageAt" ,
116- [
117- contracts .withdrawal_queue .address ,
118- web3 .keccak (text = "lido.WithdrawalQueue.bunkerModeSinceTimestamp" ).hex (),
119- web3 .to_hex (2 ** 256 - 1 ) # type(uint256).max
120- ],
121- )
122- assert not contracts .withdrawal_queue .isBunkerModeActive ()
123-
124- for i in range (0 , depositable , MAX_DEPOSITS ):
125- contracts .lido .deposit (MAX_DEPOSITS , CSM_MODULE_ID , "0x" , {"from" : contracts .deposit_security_module })
126-
127-
128124@pytest .fixture
129125def ref_slot ():
130126 wait_to_next_available_report_time (contracts .csm_hash_consensus )
@@ -135,14 +131,15 @@ def ref_slot():
135131def distribute_reward_tree (node_operator , ref_slot ):
136132 consensus_version = contracts .cs_fee_oracle .getConsensusVersion ()
137133 oracle_version = contracts .cs_fee_oracle .getContractVersion ()
138- claimable_shares = contracts .cs_fee_distributor .totalClaimableShares ()
134+ distributed_before = contracts .lido .sharesOf (contracts .cs_fee_distributor )
135+ claimed_before = contracts .cs_fee_distributor .distributedShares (node_operator )
139136
140137 rewards = ETH (0.05 )
141138 oracle_report (cl_diff = rewards )
142- distributed_shares = contracts .lido .sharesOf (contracts .cs_fee_distributor ) - claimable_shares
139+ distributed_shares = contracts .lido .sharesOf (contracts .cs_fee_distributor ) - distributed_before
143140 assert distributed_shares > 0
144141
145- report , report_hash , tree = prepare_csm_report ({node_operator : distributed_shares }, ref_slot )
142+ report , report_hash , tree = prepare_csm_report ({node_operator : claimed_before + distributed_shares }, ref_slot , distributed_shares )
146143
147144 submitter = reach_consensus (
148145 ref_slot ,
@@ -152,7 +149,7 @@ def distribute_reward_tree(node_operator, ref_slot):
152149 )
153150
154151 contracts .cs_fee_oracle .submitReportData (report , oracle_version , {"from" : submitter })
155- return tree
152+ return distributed_shares , tree . tree
156153
157154
158155def get_sys_fee_to_eject ():
@@ -185,20 +182,16 @@ def test_add_node_operator_permissionless(csm, permissionless_gate, accounting,
185182
186183
187184@pytest .mark .usefixtures ("pause_modules" )
188- def test_deposit (node_operator , csm , remove_stake_limit ):
189- (_ , _ , depositable_validators_count ) = csm .getStakingModuleSummary ()
190- deposits_count = depositable_validators_count
191- fill_deposit_buffer (deposits_count )
192- increase_staking_module_share (module_id = CSM_MODULE_ID , share_multiplier = 2 )
193-
194- for i in range (0 , deposits_count , MAX_DEPOSITS ):
195- contracts .lido .deposit (MAX_DEPOSITS , CSM_MODULE_ID , "0x" , {"from" : contracts .deposit_security_module })
185+ def test_deposit (depositable_node_operator , csm , remove_stake_limit ):
186+ (node_operator , keys_count ) = depositable_node_operator
187+ fill_deposit_buffer (keys_count )
188+ total_deposited_before = csm .getNodeOperator (node_operator )["totalDepositedKeys" ]
189+ contracts .lido .deposit (keys_count , CSM_MODULE_ID , "0x" , {"from" : contracts .deposit_security_module })
196190
197191 no = csm .getNodeOperator (node_operator )
198- assert no ["totalDepositedKeys" ] == no [ "totalAddedKeys" ]
192+ assert no ["totalDepositedKeys" ] == total_deposited_before + keys_count
199193
200194
201- @pytest .mark .usefixtures ("deposits_to_csm" )
202195def test_mint_rewards_happy_path (csm , fee_distributor ):
203196 csm_shares_before = contracts .lido .sharesOf (csm )
204197 fee_distributor_shares_before = contracts .lido .sharesOf (fee_distributor )
@@ -222,7 +215,6 @@ def test_csm_target_limits(csm, node_operator):
222215 assert no ["targetLimit" ] == target_limit
223216
224217
225- @pytest .mark .usefixtures ("deposits_to_csm" )
226218def test_csm_report_exited (csm , node_operator , extra_data_service ):
227219 total_exited = csm .getStakingModuleSummary ()["totalExitedValidators" ]
228220 exited_keys = 5
@@ -240,7 +232,6 @@ def test_csm_report_exited(csm, node_operator, extra_data_service):
240232 assert no ["totalExitedKeys" ] == exited_keys
241233
242234
243- @pytest .mark .usefixtures ("deposits_to_csm" )
244235def test_csm_get_staking_module_summary (csm , accounting , node_operator , extra_data_service , remove_stake_limit ):
245236 (exited_before , deposited_before , depositable_before ) = contracts .staking_router .getStakingModuleSummary (
246237 CSM_MODULE_ID
@@ -276,11 +267,10 @@ def test_csm_get_staking_module_summary(csm, accounting, node_operator, extra_da
276267 assert depositable_after == depositable_before + new_depositable
277268
278269
279- @pytest .mark .usefixtures ("deposits_to_csm" )
280270def test_csm_get_node_operator_summary (csm , node_operator , extra_data_service ):
281271 total_exited = csm .getStakingModuleSummary ()["totalExitedValidators" ]
282272 no = csm .getNodeOperator (node_operator )
283- exited_keys = 1
273+ exited_keys = no [ "totalExitedKeys" ] + 1
284274 extra_data = extra_data_service .collect (
285275 {(CSM_MODULE_ID , node_operator ): exited_keys }, exited_keys , exited_keys
286276 )
@@ -294,19 +284,21 @@ def test_csm_get_node_operator_summary(csm, node_operator, extra_data_service):
294284 )
295285
296286 summary = contracts .staking_router .getNodeOperatorSummary (CSM_MODULE_ID , node_operator )
297- assert summary ["targetLimitMode" ] == 0
298- assert summary ["targetValidatorsCount" ] == 0
287+ assert summary ["targetLimitMode" ] == no [ "targetLimitMode" ]
288+ assert summary ["targetValidatorsCount" ] == no [ "targetLimit" ]
299289 # DEPRECATED #
300290 assert summary ["stuckValidatorsCount" ] == 0
301291 assert summary ["refundedValidatorsCount" ] == 0
302292 assert summary ["stuckPenaltyEndTimestamp" ] == 0
303293 ##############
304294 assert summary ["totalExitedValidators" ] == exited_keys
305295 assert summary ["totalDepositedValidators" ] == no ["totalDepositedKeys" ]
306- assert summary ["depositableValidatorsCount" ] == 0
296+ assert summary ["depositableValidatorsCount" ] == no [ "depositableValidatorsCount" ]
307297
308298
309- def test_csm_decrease_vetted_keys (csm , node_operator , stranger ):
299+ def test_csm_decrease_vetted_keys (csm , depositable_node_operator , stranger ):
300+ (node_operator , keys_count ) = depositable_node_operator
301+ total_added_keys = csm .getNodeOperator (node_operator )["totalAddedKeys" ]
310302 block_number = web3 .eth .get_block_number ()
311303 block = web3 .eth .get_block (block_number )
312304 staking_module_nonce = contracts .staking_router .getStakingModuleNonce (CSM_MODULE_ID )
@@ -316,18 +308,17 @@ def test_csm_decrease_vetted_keys(csm, node_operator, stranger):
316308 staking_module_id = CSM_MODULE_ID ,
317309 nonce = staking_module_nonce ,
318310 node_operator_ids = to_bytes (node_operator , 16 ),
319- vetted_signing_keys_counts = to_bytes (1 , 32 ),
311+ vetted_signing_keys_counts = to_bytes (total_added_keys - keys_count , 32 ),
320312 )
321313
322314 set_single_guardian (contracts .deposit_security_module , contracts .agent , stranger )
323315
324316 contracts .deposit_security_module .unvetSigningKeys (* unvet_args .to_tuple (), (0 , 0 ), {"from" : stranger .address })
325317
326318 no = csm .getNodeOperator (node_operator )
327- assert no ["totalVettedKeys" ] == 1
319+ assert no ["totalVettedKeys" ] == total_added_keys - keys_count
328320
329321
330- @pytest .mark .usefixtures ("deposits_to_csm" )
331322def test_csm_penalize_node_operator (csm , accounting , node_operator , helpers ):
332323 bond_shares_before = accounting .getBondShares (node_operator )
333324 withdrawal_info = (node_operator , 0 , ETH (30 ))
@@ -337,7 +328,6 @@ def test_csm_penalize_node_operator(csm, accounting, node_operator, helpers):
337328 assert accounting .getBondShares (node_operator ) == bond_shares_before - burnt_shares
338329
339330
340- @pytest .mark .usefixtures ("deposits_to_csm" )
341331def test_csm_eth_bond (csm , accounting , node_operator ):
342332 manager_address = csm .getNodeOperator (node_operator )["managerAddress" ]
343333 set_balance_in_wei (manager_address , ETH (2 ))
@@ -348,7 +338,6 @@ def test_csm_eth_bond(csm, accounting, node_operator):
348338 assert accounting .getBondShares (node_operator ) == bond_shares_before + shares
349339
350340
351- @pytest .mark .usefixtures ("deposits_to_csm" )
352341def test_csm_steth_bond (csm , accounting , node_operator ):
353342 manager_address = csm .getNodeOperator (node_operator )["managerAddress" ]
354343 set_balance_in_wei (manager_address , ETH (2 ))
@@ -362,7 +351,6 @@ def test_csm_steth_bond(csm, accounting, node_operator):
362351 assert accounting .getBondShares (node_operator ) == bond_shares_before + shares
363352
364353
365- @pytest .mark .usefixtures ("deposits_to_csm" )
366354def test_csm_wsteth_bond (csm , accounting , node_operator ):
367355 manager_address = csm .getNodeOperator (node_operator )["managerAddress" ]
368356 set_balance_in_wei (manager_address , ETH (2 ))
@@ -381,25 +369,23 @@ def test_csm_wsteth_bond(csm, accounting, node_operator):
381369 assert accounting .getBondShares (node_operator ) == bond_shares_before + shares
382370
383371
384- @pytest .mark .usefixtures ("deposits_to_csm" )
385372def test_csm_claim_rewards_steth (csm , accounting , node_operator , ref_slot ):
386373 reward_address = csm .getNodeOperator (node_operator )["rewardAddress" ]
387374 shares_before = contracts .lido .sharesOf (reward_address )
388- accounting_shares_before = contracts .lido .sharesOf (contracts .cs_accounting )
389375
390- tree = distribute_reward_tree (node_operator , ref_slot ).tree
391- shares = tree .values [0 ]["value" ][1 ]
392- proof = list (tree .get_proof (tree .find (tree .leaf ((node_operator , shares )))))
376+ distributed_shares , tree = distribute_reward_tree (node_operator , ref_slot )
377+ cumulative_shares = tree .values [0 ]["value" ][1 ]
378+ proof = list (tree .get_proof (tree .find (tree .leaf ((node_operator , cumulative_shares )))))
379+ claimable_bond_shares_before = accounting .getClaimableBondShares (node_operator )
380+
381+ accounting .claimRewardsStETH (node_operator , ETH (999 ), cumulative_shares , proof , {"from" : reward_address })
393382
394- accounting .claimRewardsStETH (node_operator , ETH (1 ), shares , proof , {"from" : reward_address })
395383 shares_after = contracts .lido .sharesOf (reward_address )
396- accounting_shares_after = contracts .lido .sharesOf (contracts .cs_accounting )
397- assert shares_after == shares_before + (accounting_shares_before + shares - accounting_shares_after )
384+ assert shares_after == shares_before + distributed_shares + claimable_bond_shares_before
398385
399386
400- @pytest .mark .usefixtures ("deposits_to_csm" )
401387def test_csm_claim_rewards_wsteth (csm , accounting , node_operator , ref_slot ):
402- tree = distribute_reward_tree (node_operator , ref_slot ). tree
388+ _ , tree = distribute_reward_tree (node_operator , ref_slot )
403389 shares = tree .values [0 ]["value" ][1 ]
404390 proof = list (tree .get_proof (tree .find (tree .leaf ((node_operator , shares )))))
405391 reward_address = csm .getNodeOperator (node_operator )["rewardAddress" ]
@@ -409,9 +395,8 @@ def test_csm_claim_rewards_wsteth(csm, accounting, node_operator, ref_slot):
409395 assert contracts .wsteth .balanceOf (reward_address ) > wsteth_before
410396
411397
412- @pytest .mark .usefixtures ("deposits_to_csm" )
413398def test_csm_claim_rewards_eth (csm , accounting , node_operator , ref_slot ):
414- tree = distribute_reward_tree (node_operator , ref_slot ). tree
399+ _ , tree = distribute_reward_tree (node_operator , ref_slot )
415400 shares = tree .values [0 ]["value" ][1 ]
416401 proof = list (tree .get_proof (tree .find (tree .leaf ((node_operator , shares )))))
417402 reward_address = csm .getNodeOperator (node_operator )["rewardAddress" ]
@@ -423,10 +408,12 @@ def test_csm_claim_rewards_eth(csm, accounting, node_operator, ref_slot):
423408
424409
425410def test_csm_remove_key (csm , parameters_registry , accounting , node_operator ):
411+ csm_upload_keys (csm , accounting , node_operator , 1 )
412+
426413 no = csm .getNodeOperator (node_operator )
427414 keys_before = no ["totalAddedKeys" ]
428415 manager_address = csm .getNodeOperator (node_operator )["managerAddress" ]
429- tx = csm .removeKeys (node_operator , 0 , 1 , {"from" : manager_address })
416+ tx = csm .removeKeys (node_operator , keys_before - 1 , 1 , {"from" : manager_address })
430417
431418 assert "KeyRemovalChargeApplied" in tx .events
432419 assert "BondCharged" in tx .events
@@ -439,7 +426,6 @@ def test_csm_remove_key(csm, parameters_registry, accounting, node_operator):
439426 assert no ["totalAddedKeys" ] == keys_before - 1
440427
441428
442- @pytest .mark .usefixtures ("deposits_to_csm" )
443429def test_eject_bad_performer (csm , ejector , strikes , node_operator , stranger ):
444430 index_to_eject = 0
445431 pubkey_to_eject = csm .getSigningKeys (node_operator , index_to_eject , 1 )
@@ -480,7 +466,6 @@ def test_eject_bad_performer(csm, ejector, strikes, node_operator, stranger):
480466 assert tx .events ["TriggeredExitFeeRecorded" ]["withdrawalRequestRecordedFee" ] == eject_payment_value
481467
482468
483- @pytest .mark .usefixtures ("deposits_to_csm" )
484469def test_voluntary_eject (csm , ejector , node_operator ):
485470 eject_payment_value = get_sys_fee_to_eject ()
486471 operator_address = csm .getNodeOperator (node_operator )["rewardAddress" ]
@@ -517,7 +502,6 @@ def test_on_validator_exit_triggered(csm, node_operator):
517502 assert tx .events ["TriggeredExitFeeRecorded" ]["withdrawalRequestRecordedFee" ] == eject_payment_value
518503
519504
520- @pytest .mark .usefixtures ("deposits_to_csm" )
521505def test_easy_track_csm_settle_el_stealing_penalty (csm , accounting , node_operator , stranger ):
522506 manager_address = csm .getNodeOperator (node_operator )["managerAddress" ]
523507 set_balance_in_wei (manager_address , ETH (2 ))
0 commit comments