@@ -2777,12 +2777,103 @@ fn deferred_slashes_are_deferred() {
27772777 assert_eq ! ( Balances :: free_balance( 11 ) , 1000 ) ;
27782778 assert_eq ! ( Balances :: free_balance( 101 ) , 2000 ) ;
27792779
2780+ System :: reset_events ( ) ;
2781+
27802782 // at the start of era 4, slashes from era 1 are processed,
27812783 // after being deferred for at least 2 full eras.
27822784 mock:: start_active_era ( 4 ) ;
27832785
27842786 assert_eq ! ( Balances :: free_balance( 11 ) , 900 ) ;
27852787 assert_eq ! ( Balances :: free_balance( 101 ) , 2000 - ( nominated_value / 10 ) ) ;
2788+
2789+ assert_eq ! (
2790+ staking_events_since_last_call( ) ,
2791+ vec![
2792+ Event :: StakersElected ,
2793+ Event :: EraPaid ( 3 , 11075 , 33225 ) ,
2794+ Event :: Slashed ( 11 , 100 ) ,
2795+ Event :: Slashed ( 101 , 12 )
2796+ ]
2797+ ) ;
2798+ } )
2799+ }
2800+
2801+ #[ test]
2802+ fn retroactive_deferred_slashes_two_eras_before ( ) {
2803+ ExtBuilder :: default ( ) . slash_defer_duration ( 2 ) . build_and_execute ( || {
2804+ assert_eq ! ( BondingDuration :: get( ) , 3 ) ;
2805+
2806+ mock:: start_active_era ( 1 ) ;
2807+ let exposure_11_at_era1 = Staking :: eras_stakers ( active_era ( ) , 11 ) ;
2808+
2809+ mock:: start_active_era ( 3 ) ;
2810+ on_offence_in_era (
2811+ & [ OffenceDetails { offender : ( 11 , exposure_11_at_era1) , reporters : vec ! [ ] } ] ,
2812+ & [ Perbill :: from_percent ( 10 ) ] ,
2813+ 1 , // should be deferred for two full eras, and applied at the beginning of era 4.
2814+ DisableStrategy :: Never ,
2815+ ) ;
2816+ System :: reset_events ( ) ;
2817+
2818+ mock:: start_active_era ( 4 ) ;
2819+
2820+ assert_eq ! (
2821+ staking_events_since_last_call( ) ,
2822+ vec![
2823+ Event :: StakersElected ,
2824+ Event :: EraPaid ( 3 , 7100 , 21300 ) ,
2825+ Event :: Slashed ( 11 , 100 ) ,
2826+ Event :: Slashed ( 101 , 12 )
2827+ ]
2828+ ) ;
2829+ } )
2830+ }
2831+
2832+ #[ test]
2833+ fn retroactive_deferred_slashes_one_before ( ) {
2834+ ExtBuilder :: default ( ) . slash_defer_duration ( 2 ) . build_and_execute ( || {
2835+ assert_eq ! ( BondingDuration :: get( ) , 3 ) ;
2836+
2837+ mock:: start_active_era ( 1 ) ;
2838+ let exposure_11_at_era1 = Staking :: eras_stakers ( active_era ( ) , 11 ) ;
2839+
2840+ // unbond at slash era.
2841+ mock:: start_active_era ( 2 ) ;
2842+ assert_ok ! ( Staking :: chill( Origin :: signed( 10 ) ) ) ;
2843+ assert_ok ! ( Staking :: unbond( Origin :: signed( 10 ) , 100 ) ) ;
2844+
2845+ mock:: start_active_era ( 3 ) ;
2846+ on_offence_in_era (
2847+ & [ OffenceDetails { offender : ( 11 , exposure_11_at_era1) , reporters : vec ! [ ] } ] ,
2848+ & [ Perbill :: from_percent ( 10 ) ] ,
2849+ 2 , // should be deferred for two full eras, and applied at the beginning of era 5.
2850+ DisableStrategy :: Never ,
2851+ ) ;
2852+ System :: reset_events ( ) ;
2853+
2854+ mock:: start_active_era ( 4 ) ;
2855+ assert_eq ! (
2856+ staking_events_since_last_call( ) ,
2857+ vec![ Event :: StakersElected , Event :: EraPaid ( 3 , 11075 , 33225 ) ]
2858+ ) ;
2859+
2860+ assert_eq ! ( Staking :: ledger( 10 ) . unwrap( ) . total, 1000 ) ;
2861+ // slash happens after the next line.
2862+ mock:: start_active_era ( 5 ) ;
2863+ assert_eq ! (
2864+ staking_events_since_last_call( ) ,
2865+ vec![
2866+ Event :: StakersElected ,
2867+ Event :: EraPaid ( 4 , 11075 , 33225 ) ,
2868+ Event :: Slashed ( 11 , 100 ) ,
2869+ Event :: Slashed ( 101 , 12 )
2870+ ]
2871+ ) ;
2872+
2873+ // their ledger has already been slashed.
2874+ assert_eq ! ( Staking :: ledger( 10 ) . unwrap( ) . total, 900 ) ;
2875+ assert_ok ! ( Staking :: unbond( Origin :: signed( 10 ) , 1000 ) ) ;
2876+ assert_eq ! ( Staking :: ledger( 10 ) . unwrap( ) . total, 900 ) ;
27862877 } )
27872878}
27882879
@@ -2871,6 +2962,7 @@ fn remove_deferred() {
28712962 assert_eq ! ( Balances :: free_balance( 101 ) , 2000 ) ;
28722963 let nominated_value = exposure. others . iter ( ) . find ( |o| o. who == 101 ) . unwrap ( ) . value ;
28732964
2965+ // deferred to start of era 4.
28742966 on_offence_now (
28752967 & [ OffenceDetails { offender : ( 11 , exposure. clone ( ) ) , reporters : vec ! [ ] } ] ,
28762968 & [ Perbill :: from_percent ( 10 ) ] ,
@@ -2881,6 +2973,7 @@ fn remove_deferred() {
28812973
28822974 mock:: start_active_era ( 2 ) ;
28832975
2976+ // reported later, but deferred to start of era 4 as well.
28842977 on_offence_in_era (
28852978 & [ OffenceDetails { offender : ( 11 , exposure. clone ( ) ) , reporters : vec ! [ ] } ] ,
28862979 & [ Perbill :: from_percent ( 15 ) ] ,
@@ -2894,7 +2987,8 @@ fn remove_deferred() {
28942987 Error :: <Test >:: EmptyTargets
28952988 ) ;
28962989
2897- assert_ok ! ( Staking :: cancel_deferred_slash( Origin :: root( ) , 1 , vec![ 0 ] ) ) ;
2990+ // cancel one of them.
2991+ assert_ok ! ( Staking :: cancel_deferred_slash( Origin :: root( ) , 4 , vec![ 0 ] ) ) ;
28982992
28992993 assert_eq ! ( Balances :: free_balance( 11 ) , 1000 ) ;
29002994 assert_eq ! ( Balances :: free_balance( 101 ) , 2000 ) ;
@@ -2906,13 +3000,19 @@ fn remove_deferred() {
29063000
29073001 // at the start of era 4, slashes from era 1 are processed,
29083002 // after being deferred for at least 2 full eras.
3003+ System :: reset_events ( ) ;
29093004 mock:: start_active_era ( 4 ) ;
29103005
2911- // the first slash for 10% was cancelled, so no effect.
2912- assert_eq ! ( Balances :: free_balance( 11 ) , 1000 ) ;
2913- assert_eq ! ( Balances :: free_balance( 101 ) , 2000 ) ;
2914-
2915- mock:: start_active_era ( 5 ) ;
3006+ // the first slash for 10% was cancelled, but the 15% one
3007+ assert_eq ! (
3008+ staking_events_since_last_call( ) ,
3009+ vec![
3010+ Event :: StakersElected ,
3011+ Event :: EraPaid ( 3 , 11075 , 33225 ) ,
3012+ Event :: Slashed ( 11 , 50 ) ,
3013+ Event :: Slashed ( 101 , 7 )
3014+ ]
3015+ ) ;
29163016
29173017 let slash_10 = Perbill :: from_percent ( 10 ) ;
29183018 let slash_15 = Perbill :: from_percent ( 15 ) ;
@@ -2965,7 +3065,7 @@ fn remove_multi_deferred() {
29653065 & [ Perbill :: from_percent ( 25 ) ] ,
29663066 ) ;
29673067
2968- assert_eq ! ( <Staking as Store >:: UnappliedSlashes :: get( & 1 ) . len( ) , 5 ) ;
3068+ assert_eq ! ( <Staking as Store >:: UnappliedSlashes :: get( & 4 ) . len( ) , 5 ) ;
29693069
29703070 // fails if list is not sorted
29713071 assert_noop ! (
@@ -2983,9 +3083,9 @@ fn remove_multi_deferred() {
29833083 Error :: <Test >:: InvalidSlashIndex
29843084 ) ;
29853085
2986- assert_ok ! ( Staking :: cancel_deferred_slash( Origin :: root( ) , 1 , vec![ 0 , 2 , 4 ] ) ) ;
3086+ assert_ok ! ( Staking :: cancel_deferred_slash( Origin :: root( ) , 4 , vec![ 0 , 2 , 4 ] ) ) ;
29873087
2988- let slashes = <Staking as Store >:: UnappliedSlashes :: get ( & 1 ) ;
3088+ let slashes = <Staking as Store >:: UnappliedSlashes :: get ( & 4 ) ;
29893089 assert_eq ! ( slashes. len( ) , 2 ) ;
29903090 assert_eq ! ( slashes[ 0 ] . validator, 21 ) ;
29913091 assert_eq ! ( slashes[ 1 ] . validator, 42 ) ;
0 commit comments