22 super :: {
33 execution:: ExecutionWithChecks ,
44 lifecycle:: StakeLifecycle ,
5- utils:: { add_sysvars, STAKE_RENT_EXEMPTION } ,
5+ utils:: { add_sysvars, create_vote_account , STAKE_RENT_EXEMPTION } ,
66 } ,
77 mollusk_svm:: { result:: Check , Mollusk } ,
88 solana_account:: AccountSharedData ,
@@ -25,7 +25,7 @@ pub struct StakeAccountBuilder<'a> {
2525 stake_pubkey : Option < Pubkey > ,
2626}
2727
28- impl < ' a > StakeAccountBuilder < ' a > {
28+ impl StakeAccountBuilder < ' _ > {
2929 /// Set the staked amount (lamports delegated to validator)
3030 pub fn staked_amount ( mut self , amount : u64 ) -> Self {
3131 self . staked_amount = amount;
@@ -65,7 +65,24 @@ impl<'a> StakeAccountBuilder<'a> {
6565 /// Build the stake account and return (pubkey, account_data)
6666 pub fn build ( self ) -> ( Pubkey , AccountSharedData ) {
6767 let stake_pubkey = self . stake_pubkey . unwrap_or_else ( Pubkey :: new_unique) ;
68- let account = self . lifecycle . create_uninitialized_account ( ) ;
68+ let vote_account_ref = self . vote_account . as_ref ( ) . unwrap_or_else ( || {
69+ self . ctx
70+ . vote_account
71+ . as_ref ( )
72+ . map ( |( pk, _) | pk)
73+ . expect ( "vote_account required for this lifecycle" )
74+ } ) ;
75+ let account = self . lifecycle . create_stake_account_fully_specified (
76+ & mut self . ctx . mollusk ,
77+ & stake_pubkey,
78+ vote_account_ref,
79+ self . staked_amount ,
80+ self . stake_authority . as_ref ( ) . unwrap_or ( & self . ctx . staker ) ,
81+ self . withdraw_authority
82+ . as_ref ( )
83+ . unwrap_or ( & self . ctx . withdrawer ) ,
84+ self . lockup . as_ref ( ) . unwrap_or ( & Lockup :: default ( ) ) ,
85+ ) ;
6986 ( stake_pubkey, account)
7087 }
7188}
@@ -75,6 +92,9 @@ pub struct StakeTestContext {
7592 pub rent_exempt_reserve : u64 ,
7693 pub staker : Pubkey ,
7794 pub withdrawer : Pubkey ,
95+ pub minimum_delegation : Option < u64 > ,
96+ /// Vote account (pubkey, account_data) for delegation tests
97+ pub vote_account : Option < ( Pubkey , AccountSharedData ) > ,
7898}
7999
80100impl StakeTestContext {
@@ -85,6 +105,21 @@ impl StakeTestContext {
85105 rent_exempt_reserve : STAKE_RENT_EXEMPTION ,
86106 staker : Pubkey :: new_unique ( ) ,
87107 withdrawer : Pubkey :: new_unique ( ) ,
108+ minimum_delegation : None ,
109+ vote_account : None ,
110+ }
111+ }
112+
113+ pub fn with_delegation ( ) -> Self {
114+ let mollusk = Mollusk :: new ( & id ( ) , "solana_stake_program" ) ;
115+ let minimum_delegation = solana_stake_program:: get_minimum_delegation ( ) ;
116+ Self {
117+ mollusk,
118+ rent_exempt_reserve : STAKE_RENT_EXEMPTION ,
119+ staker : Pubkey :: new_unique ( ) ,
120+ withdrawer : Pubkey :: new_unique ( ) ,
121+ minimum_delegation : Some ( minimum_delegation) ,
122+ vote_account : Some ( ( Pubkey :: new_unique ( ) , create_vote_account ( ) ) ) ,
88123 }
89124 }
90125
@@ -95,6 +130,8 @@ impl StakeTestContext {
95130 /// let (stake, account) = ctx
96131 /// .stake_account(StakeLifecycle::Active)
97132 /// .staked_amount(1_000_000)
133+ /// .stake_account(StakeLifecycle::Active)
134+ /// .staked_amount(1_000_000)
98135 /// .build();
99136 /// ```
100137 pub fn stake_account ( & mut self , lifecycle : StakeLifecycle ) -> StakeAccountBuilder < ' _ > {
@@ -117,6 +154,25 @@ impl StakeTestContext {
117154 ExecutionWithChecks :: new ( self , checks)
118155 }
119156
157+ /// Create a lockup that expires in the future
158+ pub fn create_future_lockup ( & self , epochs_ahead : u64 ) -> Lockup {
159+ Lockup {
160+ unix_timestamp : 0 ,
161+ epoch : self . mollusk . sysvars . clock . epoch + epochs_ahead,
162+ custodian : Pubkey :: new_unique ( ) ,
163+ }
164+ }
165+
166+ /// Create a lockup that's currently in force (far future)
167+ pub fn create_in_force_lockup ( & self ) -> Lockup {
168+ self . create_future_lockup ( 1_000_000 )
169+ }
170+
171+ /// Create a second vote account (for testing different vote accounts)
172+ pub fn create_second_vote_account ( & self ) -> ( Pubkey , AccountSharedData ) {
173+ ( Pubkey :: new_unique ( ) , create_vote_account ( ) )
174+ }
175+
120176 /// Execute an instruction with default success checks and missing signer testing
121177 ///
122178 /// Usage: `ctx.execute(instruction, accounts)`
@@ -154,7 +210,7 @@ impl StakeTestContext {
154210
155211impl Default for StakeTestContext {
156212 fn default ( ) -> Self {
157- Self :: new ( )
213+ Self :: with_delegation ( )
158214 }
159215}
160216
0 commit comments