@@ -473,6 +473,57 @@ pub enum StakePoolInstruction {
473
473
/// seed used to create ephemeral account.
474
474
ephemeral_stake_seed : u64 ,
475
475
} ,
476
+
477
+ /// (Staker only) Redelegate active stake on a validator, eventually moving it to another
478
+ ///
479
+ /// Internally, this instruction splits a validator stake account into its
480
+ /// corresponding transient stake account, redelegates it to an ephemeral stake
481
+ /// account, then merges that stake into the destination transient stake account.
482
+ ///
483
+ /// In order to rebalance the pool without taking custody, the staker needs
484
+ /// a way of reducing the stake on a stake account. This instruction splits
485
+ /// some amount of stake, up to the total activated stake, from the canonical
486
+ /// validator stake account, into its "transient" stake account.
487
+ ///
488
+ /// The instruction only succeeds if the source transient stake account and
489
+ /// ephemeral stake account do not exist.
490
+ ///
491
+ /// The amount of lamports to move must be at least twice rent-exemption
492
+ /// plus the minimum delegation amount. Rent-exemption is required for the
493
+ /// source transient stake account, and rent-exemption plus minimum delegation
494
+ /// is required for the destination ephemeral stake account.
495
+ ///
496
+ /// 0. `[]` Stake pool
497
+ /// 1. `[s]` Stake pool staker
498
+ /// 2. `[]` Stake pool withdraw authority
499
+ /// 3. `[w]` Validator list
500
+ /// 4. `[w]` Source canonical stake account to split from
501
+ /// 5. `[w]` Source transient stake account to receive split and be redelegated
502
+ /// 6. `[w]` Uninitialized ephemeral stake account to receive redelegation
503
+ /// 7. `[w]` Destination transient stake account to receive ephemeral stake by merge
504
+ /// 8. `[]` Destination stake account to receive transient stake after activation
505
+ /// 9. `[]` Destination validator vote account
506
+ /// 10. `[]` Clock sysvar
507
+ /// 11. `[]` Stake History sysvar
508
+ /// 12. `[]` Stake Config sysvar
509
+ /// 13. `[]` System program
510
+ /// 14. `[]` Stake program
511
+ Redelegate {
512
+ /// Amount of lamports to redelegate
513
+ #[ allow( dead_code) ] // but it's not
514
+ lamports : u64 ,
515
+ /// Seed used to create source transient stake account
516
+ #[ allow( dead_code) ] // but it's not
517
+ source_transient_stake_seed : u64 ,
518
+ /// Seed used to create destination ephemeral account.
519
+ #[ allow( dead_code) ] // but it's not
520
+ ephemeral_stake_seed : u64 ,
521
+ /// Seed used to create destination transient stake account. If there is
522
+ /// already transient stake, this must match the current seed, otherwise
523
+ /// it can be anything
524
+ #[ allow( dead_code) ] // but it's not
525
+ destination_transient_stake_seed : u64 ,
526
+ } ,
476
527
}
477
528
478
529
/// Creates an 'initialize' instruction.
@@ -756,6 +807,55 @@ pub fn increase_additional_validator_stake(
756
807
}
757
808
}
758
809
810
+ /// Creates `Redelegate` instruction (rebalance from one validator account to another)
811
+ pub fn redelegate (
812
+ program_id : & Pubkey ,
813
+ stake_pool : & Pubkey ,
814
+ staker : & Pubkey ,
815
+ stake_pool_withdraw_authority : & Pubkey ,
816
+ validator_list : & Pubkey ,
817
+ source_validator_stake : & Pubkey ,
818
+ source_transient_stake : & Pubkey ,
819
+ ephemeral_stake : & Pubkey ,
820
+ destination_transient_stake : & Pubkey ,
821
+ destination_validator_stake : & Pubkey ,
822
+ validator : & Pubkey ,
823
+ lamports : u64 ,
824
+ source_transient_stake_seed : u64 ,
825
+ ephemeral_stake_seed : u64 ,
826
+ destination_transient_stake_seed : u64 ,
827
+ ) -> Instruction {
828
+ let accounts = vec ! [
829
+ AccountMeta :: new_readonly( * stake_pool, false ) ,
830
+ AccountMeta :: new_readonly( * staker, true ) ,
831
+ AccountMeta :: new_readonly( * stake_pool_withdraw_authority, false ) ,
832
+ AccountMeta :: new( * validator_list, false ) ,
833
+ AccountMeta :: new( * source_validator_stake, false ) ,
834
+ AccountMeta :: new( * source_transient_stake, false ) ,
835
+ AccountMeta :: new( * ephemeral_stake, false ) ,
836
+ AccountMeta :: new( * destination_transient_stake, false ) ,
837
+ AccountMeta :: new_readonly( * destination_validator_stake, false ) ,
838
+ AccountMeta :: new_readonly( * validator, false ) ,
839
+ AccountMeta :: new_readonly( sysvar:: clock:: id( ) , false ) ,
840
+ AccountMeta :: new_readonly( sysvar:: stake_history:: id( ) , false ) ,
841
+ AccountMeta :: new_readonly( stake:: config:: id( ) , false ) ,
842
+ AccountMeta :: new_readonly( system_program:: id( ) , false ) ,
843
+ AccountMeta :: new_readonly( stake:: program:: id( ) , false ) ,
844
+ ] ;
845
+ Instruction {
846
+ program_id : * program_id,
847
+ accounts,
848
+ data : StakePoolInstruction :: Redelegate {
849
+ lamports,
850
+ source_transient_stake_seed,
851
+ ephemeral_stake_seed,
852
+ destination_transient_stake_seed,
853
+ }
854
+ . try_to_vec ( )
855
+ . unwrap ( ) ,
856
+ }
857
+ }
858
+
759
859
/// Creates `SetPreferredDepositValidator` instruction
760
860
pub fn set_preferred_validator (
761
861
program_id : & Pubkey ,
0 commit comments