@@ -7205,6 +7205,99 @@ mod staking_unchecked {
72057205 assert_eq ! ( SlashObserver :: get( ) . get( & 101 ) . unwrap( ) , & nominator_share) ;
72067206 } )
72077207 }
7208+
7209+ #[ test]
7210+ fn virtual_stakers_cannot_be_reaped ( ) {
7211+ ExtBuilder :: default ( )
7212+ // we need enough validators such that disables are allowed.
7213+ . validator_count ( 7 )
7214+ . set_status ( 41 , StakerStatus :: Validator )
7215+ . set_status ( 51 , StakerStatus :: Validator )
7216+ . set_status ( 201 , StakerStatus :: Validator )
7217+ . set_status ( 202 , StakerStatus :: Validator )
7218+ . build_and_execute ( || {
7219+ // make 101 only nominate 11.
7220+ assert_ok ! ( Staking :: nominate( RuntimeOrigin :: signed( 101 ) , vec![ 11 ] ) ) ;
7221+
7222+ mock:: start_active_era ( 1 ) ;
7223+
7224+ // slash all stake.
7225+ let slash_percent = Perbill :: from_percent ( 100 ) ;
7226+ let initial_exposure = Staking :: eras_stakers ( active_era ( ) , & 11 ) ;
7227+ // 101 is a nominator for 11
7228+ assert_eq ! ( initial_exposure. others. first( ) . unwrap( ) . who, 101 ) ;
7229+ // make 101 a virtual nominator
7230+ <Staking as StakingUnchecked >:: migrate_to_virtual_staker ( & 101 ) ;
7231+ // set payee different to self.
7232+ assert_ok ! ( <Staking as StakingInterface >:: update_payee( & 101 , & 102 ) ) ;
7233+
7234+ // cache values
7235+ let validator_balance = Balances :: free_balance ( & 11 ) ;
7236+ let validator_stake = Staking :: ledger ( 11 . into ( ) ) . unwrap ( ) . total ;
7237+ let nominator_balance = Balances :: free_balance ( & 101 ) ;
7238+ let nominator_stake = Staking :: ledger ( 101 . into ( ) ) . unwrap ( ) . total ;
7239+
7240+ // 11 goes offline
7241+ on_offence_now (
7242+ & [ OffenceDetails {
7243+ offender : ( 11 , initial_exposure. clone ( ) ) ,
7244+ reporters : vec ! [ ] ,
7245+ } ] ,
7246+ & [ slash_percent] ,
7247+ ) ;
7248+
7249+ // both stakes must have been decreased to 0.
7250+ assert_eq ! ( Staking :: ledger( 101 . into( ) ) . unwrap( ) . active, 0 ) ;
7251+ assert_eq ! ( Staking :: ledger( 11 . into( ) ) . unwrap( ) . active, 0 ) ;
7252+
7253+ // all validator stake is slashed
7254+ assert_eq_error_rate ! (
7255+ validator_balance - validator_stake,
7256+ Balances :: free_balance( & 11 ) ,
7257+ 1
7258+ ) ;
7259+ // Because slashing happened.
7260+ assert ! ( is_disabled( 11 ) ) ;
7261+
7262+ // Virtual nominator's balance is not slashed.
7263+ assert_eq ! ( Balances :: free_balance( & 101 ) , nominator_balance) ;
7264+ // Slash is broadcasted to slash observers.
7265+ assert_eq ! ( SlashObserver :: get( ) . get( & 101 ) . unwrap( ) , & nominator_stake) ;
7266+
7267+ // validator can be reaped.
7268+ assert_ok ! ( Staking :: reap_stash( RuntimeOrigin :: signed( 10 ) , 11 , u32 :: MAX ) ) ;
7269+ // nominator is a virtual staker and cannot be reaped.
7270+ assert_noop ! (
7271+ Staking :: reap_stash( RuntimeOrigin :: signed( 10 ) , 101 , u32 :: MAX ) ,
7272+ Error :: <Test >:: VirtualStakerNotAllowed
7273+ ) ;
7274+ } )
7275+ }
7276+
7277+ #[ test]
7278+ fn restore_ledger_not_allowed_for_virtual_stakers ( ) {
7279+ ExtBuilder :: default ( ) . has_stakers ( true ) . build_and_execute ( || {
7280+ setup_double_bonded_ledgers ( ) ;
7281+ assert_eq ! ( Staking :: inspect_bond_state( & 333 ) . unwrap( ) , LedgerIntegrityState :: Ok ) ;
7282+ set_controller_no_checks ( & 444 ) ;
7283+ // 333 is corrupted
7284+ assert_eq ! ( Staking :: inspect_bond_state( & 333 ) . unwrap( ) , LedgerIntegrityState :: Corrupted ) ;
7285+ // migrate to virtual staker.
7286+ <Staking as StakingUnchecked >:: migrate_to_virtual_staker ( & 333 ) ;
7287+
7288+ // recover the ledger won't work for virtual staker
7289+ assert_noop ! (
7290+ Staking :: restore_ledger( RuntimeOrigin :: root( ) , 333 , None , None , None ) ,
7291+ Error :: <Test >:: VirtualStakerNotAllowed
7292+ ) ;
7293+
7294+ // migrate 333 back to normal staker
7295+ <VirtualStakers < Test > >:: remove ( 333 ) ;
7296+
7297+ // try restore again
7298+ assert_ok ! ( Staking :: restore_ledger( RuntimeOrigin :: root( ) , 333 , None , None , None ) ) ;
7299+ } )
7300+ }
72087301}
72097302mod ledger {
72107303 use super :: * ;
0 commit comments