14
14
input_validators:: { is_amount, is_keypair, is_parsable, is_pubkey, is_url} ,
15
15
keypair:: signer_from_path,
16
16
} ,
17
- solana_client:: { rpc_client:: RpcClient , rpc_response :: StakeActivationState } ,
17
+ solana_client:: rpc_client:: RpcClient ,
18
18
solana_program:: {
19
19
borsh:: get_packed_len, instruction:: Instruction , program_pack:: Pack , pubkey:: Pubkey ,
20
20
} ,
28
28
spl_stake_pool:: {
29
29
self ,
30
30
borsh:: get_instance_packed_len,
31
- find_deposit_authority_program_address , find_stake_program_address ,
32
- find_transient_stake_program_address , find_withdraw_authority_program_address,
33
- stake_program:: { self , StakeAuthorize , StakeState } ,
31
+ find_stake_program_address , find_transient_stake_program_address ,
32
+ find_withdraw_authority_program_address,
33
+ stake_program:: { self , StakeState } ,
34
34
state:: { Fee , StakePool , ValidatorList } ,
35
35
MAX_VALIDATORS_TO_UPDATE ,
36
36
} ,
@@ -42,6 +42,7 @@ struct Config {
42
42
verbose : bool ,
43
43
manager : Box < dyn Signer > ,
44
44
staker : Box < dyn Signer > ,
45
+ depositor : Option < Box < dyn Signer > > ,
45
46
token_owner : Box < dyn Signer > ,
46
47
fee_payer : Box < dyn Signer > ,
47
48
dry_run : bool ,
@@ -94,7 +95,12 @@ fn send_transaction(
94
95
Ok ( ( ) )
95
96
}
96
97
97
- fn command_create_pool ( config : & Config , fee : Fee , max_validators : u32 ) -> CommandResult {
98
+ fn command_create_pool (
99
+ config : & Config ,
100
+ deposit_authority : Option < Pubkey > ,
101
+ fee : Fee ,
102
+ max_validators : u32 ,
103
+ ) -> CommandResult {
98
104
let reserve_stake = Keypair :: new ( ) ;
99
105
println ! ( "Creating reserve stake {}" , reserve_stake. pubkey( ) ) ;
100
106
@@ -224,6 +230,7 @@ fn command_create_pool(config: &Config, fee: Fee, max_validators: u32) -> Comman
224
230
& mint_account. pubkey ( ) ,
225
231
& pool_fee_account. pubkey ( ) ,
226
232
& spl_token:: id ( ) ,
233
+ deposit_authority,
227
234
fee,
228
235
max_validators,
229
236
) ?,
@@ -286,7 +293,17 @@ fn command_vsa_create(
286
293
}
287
294
288
295
fn command_vsa_add ( config : & Config , stake_pool_address : & Pubkey , stake : & Pubkey ) -> CommandResult {
289
- if config. rpc_client . get_stake_activation ( * stake, None ) ?. state != StakeActivationState :: Active {
296
+ let stake_state = get_stake_state ( & config. rpc_client , & stake) ?;
297
+ if let stake_program:: StakeState :: Stake ( meta, _stake) = stake_state {
298
+ if meta. authorized . withdrawer != config. staker . pubkey ( ) {
299
+ let error = format ! (
300
+ "Stake account withdraw authority must be the staker {}, actual {}" ,
301
+ config. staker. pubkey( ) ,
302
+ meta. authorized. withdrawer
303
+ ) ;
304
+ return Err ( error. into ( ) ) ;
305
+ }
306
+ } else {
290
307
return Err ( "Stake account is not active." . into ( ) ) ;
291
308
}
292
309
@@ -299,34 +316,16 @@ fn command_vsa_add(config: &Config, stake_pool_address: &Pubkey, stake: &Pubkey)
299
316
let mut instructions: Vec < Instruction > = vec ! [ ] ;
300
317
let mut signers = vec ! [ config. fee_payer. as_ref( ) , config. staker. as_ref( ) ] ;
301
318
302
- // Calculate Deposit and Withdraw stake pool authorities
303
- let pool_deposit_authority =
304
- find_deposit_authority_program_address ( & spl_stake_pool:: id ( ) , stake_pool_address) . 0 ;
305
-
319
+ // Calculate Withdraw stake pool authorities
306
320
let pool_withdraw_authority =
307
321
find_withdraw_authority_program_address ( & spl_stake_pool:: id ( ) , stake_pool_address) . 0 ;
308
322
309
323
instructions. extend ( vec ! [
310
- // Set Withdrawer on stake account to Deposit authority of the stake pool
311
- stake_program:: authorize(
312
- & stake,
313
- & config. staker. pubkey( ) ,
314
- & pool_deposit_authority,
315
- StakeAuthorize :: Withdrawer ,
316
- ) ,
317
- // Set Staker on stake account to Deposit authority of the stake pool
318
- stake_program:: authorize(
319
- & stake,
320
- & config. staker. pubkey( ) ,
321
- & pool_deposit_authority,
322
- StakeAuthorize :: Staker ,
323
- ) ,
324
324
// Add validator stake account to the pool
325
325
spl_stake_pool:: instruction:: add_validator_to_pool(
326
326
& spl_stake_pool:: id( ) ,
327
327
& stake_pool_address,
328
328
& config. staker. pubkey( ) ,
329
- & pool_deposit_authority,
330
329
& pool_withdraw_authority,
331
330
& stake_pool. validator_list,
332
331
& stake,
@@ -588,42 +587,49 @@ fn command_deposit(
588
587
} ,
589
588
) ?;
590
589
591
- // Calculate Deposit and Withdraw stake pool authorities
592
- let pool_deposit_authority =
593
- find_deposit_authority_program_address ( & spl_stake_pool:: id ( ) , stake_pool_address) . 0 ;
594
-
595
590
let pool_withdraw_authority =
596
591
find_withdraw_authority_program_address ( & spl_stake_pool:: id ( ) , stake_pool_address) . 0 ;
597
592
598
- instructions. extend ( vec ! [
599
- // Set Withdrawer on stake account to Deposit authority of the stake pool
600
- stake_program:: authorize(
601
- & stake,
602
- & config. staker. pubkey( ) ,
603
- & pool_deposit_authority,
604
- StakeAuthorize :: Withdrawer ,
605
- ) ,
606
- // Set Staker on stake account to Deposit authority of the stake pool
607
- stake_program:: authorize(
593
+ let mut deposit_instructions = if let Some ( deposit_authority) = config. depositor . as_ref ( ) {
594
+ signers. push ( deposit_authority. as_ref ( ) ) ;
595
+ if deposit_authority. pubkey ( ) != stake_pool. deposit_authority {
596
+ let error = format ! (
597
+ "Invalid deposit authority specified, expected {}, received {}" ,
598
+ stake_pool. deposit_authority,
599
+ deposit_authority. pubkey( )
600
+ ) ;
601
+ return Err ( error. into ( ) ) ;
602
+ }
603
+
604
+ spl_stake_pool:: instruction:: deposit_with_authority (
605
+ & spl_stake_pool:: id ( ) ,
606
+ & stake_pool_address,
607
+ & stake_pool. validator_list ,
608
+ & deposit_authority. pubkey ( ) ,
609
+ & pool_withdraw_authority,
608
610
& stake,
609
611
& config. staker . pubkey ( ) ,
610
- & pool_deposit_authority,
611
- StakeAuthorize :: Staker ,
612
- ) ,
613
- // Add stake account to the pool
612
+ & validator_stake_account,
613
+ & token_receiver,
614
+ & stake_pool. pool_mint ,
615
+ & spl_token:: id ( ) ,
616
+ )
617
+ } else {
614
618
spl_stake_pool:: instruction:: deposit (
615
619
& spl_stake_pool:: id ( ) ,
616
620
& stake_pool_address,
617
621
& stake_pool. validator_list ,
618
- & pool_deposit_authority,
619
622
& pool_withdraw_authority,
620
623
& stake,
624
+ & config. staker . pubkey ( ) ,
621
625
& validator_stake_account,
622
626
& token_receiver,
623
627
& stake_pool. pool_mint ,
624
628
& spl_token:: id ( ) ,
625
- ) ?,
626
- ] ) ;
629
+ )
630
+ } ;
631
+
632
+ instructions. append ( & mut deposit_instructions) ;
627
633
628
634
let mut transaction =
629
635
Transaction :: new_with_payer ( & instructions, Some ( & config. fee_payer . pubkey ( ) ) ) ;
@@ -1130,6 +1136,17 @@ fn main() {
1130
1136
Defaults to the client keypair.",
1131
1137
) ,
1132
1138
)
1139
+ . arg (
1140
+ Arg :: with_name ( "depositor" )
1141
+ . long ( "depositor" )
1142
+ . value_name ( "KEYPAIR" )
1143
+ . validator ( is_keypair)
1144
+ . takes_value ( true )
1145
+ . help (
1146
+ "Specify the stake pool depositor. \
1147
+ This may be a keypair file, the ASK keyword.",
1148
+ ) ,
1149
+ )
1133
1150
. arg (
1134
1151
Arg :: with_name ( "token_owner" )
1135
1152
. long ( "token-owner" )
@@ -1186,6 +1203,15 @@ fn main() {
1186
1203
. required ( true )
1187
1204
. help ( "Max number of validators included in the stake pool" ) ,
1188
1205
)
1206
+ . arg (
1207
+ Arg :: with_name ( "deposit_authority" )
1208
+ . long ( "deposit-authority" )
1209
+ . short ( "a" )
1210
+ . validator ( is_pubkey)
1211
+ . value_name ( "DEPOSIT_AUTHORITY_ADDRESS" )
1212
+ . takes_value ( true )
1213
+ . help ( "Deposit authority required to sign all deposits into the stake pool" ) ,
1214
+ )
1189
1215
)
1190
1216
. subcommand ( SubCommand :: with_name ( "create-validator-stake" )
1191
1217
. about ( "Create a new stake account to use with the pool. Must be signed by the pool staker." )
@@ -1515,6 +1541,22 @@ fn main() {
1515
1541
eprintln ! ( "error: {}" , e) ;
1516
1542
exit ( 1 ) ;
1517
1543
} ) ;
1544
+ let depositor = if matches. is_present ( "depositor" ) {
1545
+ Some (
1546
+ signer_from_path (
1547
+ & matches,
1548
+ & cli_config. keypair_path ,
1549
+ "depositor" ,
1550
+ & mut wallet_manager,
1551
+ )
1552
+ . unwrap_or_else ( |e| {
1553
+ eprintln ! ( "error: {}" , e) ;
1554
+ exit ( 1 ) ;
1555
+ } ) ,
1556
+ )
1557
+ } else {
1558
+ None
1559
+ } ;
1518
1560
let manager = signer_from_path (
1519
1561
& matches,
1520
1562
& cli_config. keypair_path ,
@@ -1554,6 +1596,7 @@ fn main() {
1554
1596
verbose,
1555
1597
manager,
1556
1598
staker,
1599
+ depositor,
1557
1600
token_owner,
1558
1601
fee_payer,
1559
1602
dry_run,
@@ -1563,11 +1606,13 @@ fn main() {
1563
1606
1564
1607
let _ = match matches. subcommand ( ) {
1565
1608
( "create-pool" , Some ( arg_matches) ) => {
1609
+ let deposit_authority = pubkey_of ( arg_matches, "deposit_authority" ) ;
1566
1610
let numerator = value_t_or_exit ! ( arg_matches, "fee_numerator" , u64 ) ;
1567
1611
let denominator = value_t_or_exit ! ( arg_matches, "fee_denominator" , u64 ) ;
1568
1612
let max_validators = value_t_or_exit ! ( arg_matches, "max_validators" , u32 ) ;
1569
1613
command_create_pool (
1570
1614
& config,
1615
+ deposit_authority,
1571
1616
Fee {
1572
1617
denominator,
1573
1618
numerator,
0 commit comments