@@ -256,6 +256,35 @@ async fn test_rewards_base_inactivity_leak_justification_epoch() {
256
256
) ;
257
257
}
258
258
259
+ #[ tokio:: test]
260
+ async fn test_rewards_electra_slashings ( ) {
261
+ let spec = ForkName :: Electra . make_genesis_spec ( E :: default_spec ( ) ) ;
262
+ let harness = get_electra_harness ( spec) ;
263
+ let state = harness. get_current_state ( ) ;
264
+
265
+ harness. extend_slots ( E :: slots_per_epoch ( ) as usize ) . await ;
266
+
267
+ let mut initial_balances = harness. get_current_state ( ) . balances ( ) . to_vec ( ) ;
268
+
269
+ // add an attester slashing and calculate slashing penalties
270
+ harness. add_attester_slashing ( vec ! [ 0 ] ) . unwrap ( ) ;
271
+ let slashed_balance_1 = initial_balances. get_mut ( 0 ) . unwrap ( ) ;
272
+ let validator_1_effective_balance = state. get_effective_balance ( 0 ) . unwrap ( ) ;
273
+ let delta_1 = validator_1_effective_balance
274
+ / harness. spec . min_slashing_penalty_quotient_for_state ( & state) ;
275
+ * slashed_balance_1 -= delta_1;
276
+
277
+ // add a proposer slashing and calculating slashing penalties
278
+ harness. add_proposer_slashing ( 1 ) . unwrap ( ) ;
279
+ let slashed_balance_2 = initial_balances. get_mut ( 1 ) . unwrap ( ) ;
280
+ let validator_2_effective_balance = state. get_effective_balance ( 1 ) . unwrap ( ) ;
281
+ let delta_2 = validator_2_effective_balance
282
+ / harness. spec . min_slashing_penalty_quotient_for_state ( & state) ;
283
+ * slashed_balance_2 -= delta_2;
284
+
285
+ check_all_electra_rewards ( & harness, initial_balances) . await ;
286
+ }
287
+
259
288
#[ tokio:: test]
260
289
async fn test_rewards_base_slashings ( ) {
261
290
let spec = ForkName :: Base . make_genesis_spec ( E :: default_spec ( ) ) ;
@@ -696,6 +725,75 @@ async fn test_rewards_base_subset_only() {
696
725
check_all_base_rewards_for_subset ( & harness, initial_balances, validators_subset) . await ;
697
726
}
698
727
728
+ async fn check_all_electra_rewards (
729
+ harness : & BeaconChainHarness < EphemeralHarnessType < E > > ,
730
+ mut balances : Vec < u64 > ,
731
+ ) {
732
+ let mut proposal_rewards_map = HashMap :: new ( ) ;
733
+ let mut sync_committee_rewards_map = HashMap :: new ( ) ;
734
+ for _ in 0 ..E :: slots_per_epoch ( ) {
735
+ let state = harness. get_current_state ( ) ;
736
+ let slot = state. slot ( ) + Slot :: new ( 1 ) ;
737
+
738
+ // calculate beacon block rewards / penalties
739
+ let ( ( signed_block, _maybe_blob_sidecars) , mut state) =
740
+ harness. make_block_return_pre_state ( state, slot) . await ;
741
+ let beacon_block_reward = harness
742
+ . chain
743
+ . compute_beacon_block_reward ( signed_block. message ( ) , & mut state)
744
+ . unwrap ( ) ;
745
+
746
+ let total_proposer_reward = proposal_rewards_map
747
+ . entry ( beacon_block_reward. proposer_index )
748
+ . or_insert ( 0 ) ;
749
+ * total_proposer_reward += beacon_block_reward. total as i64 ;
750
+
751
+ // calculate sync committee rewards / penalties
752
+ let reward_payload = harness
753
+ . chain
754
+ . compute_sync_committee_rewards ( signed_block. message ( ) , & mut state)
755
+ . unwrap ( ) ;
756
+
757
+ for reward in reward_payload {
758
+ let total_sync_reward = sync_committee_rewards_map
759
+ . entry ( reward. validator_index )
760
+ . or_insert ( 0 ) ;
761
+ * total_sync_reward += reward. reward ;
762
+ }
763
+
764
+ harness. extend_slots ( 1 ) . await ;
765
+ }
766
+
767
+ // compute reward deltas for all validators in epoch 0
768
+ let StandardAttestationRewards {
769
+ ideal_rewards,
770
+ total_rewards,
771
+ } = harness
772
+ . chain
773
+ . compute_attestation_rewards ( Epoch :: new ( 0 ) , vec ! [ ] )
774
+ . unwrap ( ) ;
775
+
776
+ // assert ideal rewards are greater than 0
777
+ assert_eq ! (
778
+ ideal_rewards. len( ) as u64 ,
779
+ harness. spec. max_effective_balance_electra / harness. spec. effective_balance_increment
780
+ ) ;
781
+
782
+ assert ! ( ideal_rewards
783
+ . iter( )
784
+ . all( |reward| reward. head > 0 && reward. target > 0 && reward. source > 0 ) ) ;
785
+
786
+ // apply attestation, proposal, and sync committee rewards and penalties to initial balances
787
+ apply_attestation_rewards ( & mut balances, total_rewards) ;
788
+ apply_other_rewards ( & mut balances, & proposal_rewards_map) ;
789
+ apply_other_rewards ( & mut balances, & sync_committee_rewards_map) ;
790
+
791
+ // verify expected balances against actual balances
792
+ let actual_balances: Vec < u64 > = harness. get_current_state ( ) . balances ( ) . to_vec ( ) ;
793
+
794
+ assert_eq ! ( balances, actual_balances) ;
795
+ }
796
+
699
797
async fn check_all_base_rewards (
700
798
harness : & BeaconChainHarness < EphemeralHarnessType < E > > ,
701
799
balances : Vec < u64 > ,
0 commit comments