Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 11a5551

Browse files
fix: stake-pool require signature in SetManager (#2273)
* add check for new_manager's signature in SetManager * cli arg edit
1 parent 974541c commit 11a5551

File tree

4 files changed

+74
-17
lines changed

4 files changed

+74
-17
lines changed

stake-pool/cli/src/main.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,15 +1311,15 @@ fn command_withdraw(
13111311
fn command_set_manager(
13121312
config: &Config,
13131313
stake_pool_address: &Pubkey,
1314-
new_manager: &Option<Pubkey>,
1314+
new_manager: &Option<Keypair>,
13151315
new_fee_receiver: &Option<Pubkey>,
13161316
) -> CommandResult {
13171317
let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
13181318

13191319
// If new accounts are missing in the arguments use the old ones
1320-
let new_manager = match new_manager {
1321-
None => stake_pool.manager,
1322-
Some(value) => *value,
1320+
let (new_manager_pubkey, mut signers): (Pubkey, Vec<&dyn Signer>) = match new_manager {
1321+
None => (stake_pool.manager, vec![]),
1322+
Some(value) => (value.pubkey(), vec![value]),
13231323
};
13241324
let new_fee_receiver = match new_fee_receiver {
13251325
None => stake_pool.manager_fee_account,
@@ -1336,15 +1336,18 @@ fn command_set_manager(
13361336
}
13371337
};
13381338

1339-
let mut signers = vec![config.fee_payer.as_ref(), config.manager.as_ref()];
1339+
signers.append(&mut vec![
1340+
config.fee_payer.as_ref(),
1341+
config.manager.as_ref(),
1342+
]);
13401343
unique_signers!(signers);
13411344
let transaction = checked_transaction_with_signers(
13421345
config,
13431346
&[spl_stake_pool::instruction::set_manager(
13441347
&spl_stake_pool::id(),
13451348
stake_pool_address,
13461349
&config.manager.pubkey(),
1347-
&new_manager,
1350+
&new_manager_pubkey,
13481351
&new_fee_receiver,
13491352
)],
13501353
&signers,
@@ -1999,10 +2002,10 @@ fn main() {
19992002
.arg(
20002003
Arg::with_name("new_manager")
20012004
.long("new-manager")
2002-
.validator(is_pubkey)
2003-
.value_name("ADDRESS")
2005+
.validator(is_keypair)
2006+
.value_name("KEYPAIR")
20042007
.takes_value(true)
2005-
.help("Public key for the new stake pool manager."),
2008+
.help("Keypair for the new stake pool manager."),
20062009
)
20072010
.arg(
20082011
Arg::with_name("new_fee_receiver")
@@ -2360,7 +2363,7 @@ fn main() {
23602363
}
23612364
("set-manager", Some(arg_matches)) => {
23622365
let stake_pool_address = pubkey_of(arg_matches, "pool").unwrap();
2363-
let new_manager: Option<Pubkey> = pubkey_of(arg_matches, "new_manager");
2366+
let new_manager: Option<Keypair> = keypair_of(arg_matches, "new_manager");
23642367
let new_fee_receiver: Option<Pubkey> = pubkey_of(arg_matches, "new_fee_receiver");
23652368
command_set_manager(
23662369
&config,

stake-pool/program/src/instruction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,7 @@ pub fn set_manager(
11031103
let accounts = vec![
11041104
AccountMeta::new(*stake_pool, false),
11051105
AccountMeta::new_readonly(*manager, true),
1106-
AccountMeta::new_readonly(*new_manager, false),
1106+
AccountMeta::new_readonly(*new_manager, true),
11071107
AccountMeta::new_readonly(*new_fee_receiver, false),
11081108
];
11091109
Instruction {

stake-pool/program/src/processor.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2366,6 +2366,10 @@ impl Processor {
23662366
}
23672367

23682368
stake_pool.check_manager(manager_info)?;
2369+
if !new_manager_info.is_signer {
2370+
msg!("New manager signature missing");
2371+
return Err(StakePoolError::SignatureMissing.into());
2372+
}
23692373

23702374
if stake_pool.pool_mint
23712375
!= spl_token::state::Account::unpack_from_slice(&new_manager_fee_info.data.borrow())?
@@ -2412,7 +2416,7 @@ impl Processor {
24122416
Ok(())
24132417
}
24142418

2415-
/// Processes [SetManager](enum.Instruction.html).
2419+
/// Processes [SetStaker](enum.Instruction.html).
24162420
fn process_set_staker(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
24172421
let account_info_iter = &mut accounts.iter();
24182422
let stake_pool_info = next_account_info(account_info_iter)?;

stake-pool/program/tests/set_manager.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ async fn test_set_manager() {
7171
)],
7272
Some(&payer.pubkey()),
7373
);
74-
transaction.sign(&[&payer, &stake_pool_accounts.manager], recent_blockhash);
74+
transaction.sign(
75+
&[&payer, &stake_pool_accounts.manager, &new_manager],
76+
recent_blockhash,
77+
);
7578
banks_client.process_transaction(transaction).await.unwrap();
7679

7780
let stake_pool = get_account(&mut banks_client, &stake_pool_accounts.stake_pool.pubkey()).await;
@@ -116,7 +119,7 @@ async fn test_set_manager_by_malicious() {
116119
}
117120

118121
#[tokio::test]
119-
async fn test_set_manager_without_signature() {
122+
async fn test_set_manager_without_existing_signature() {
120123
let (mut banks_client, payer, recent_blockhash, stake_pool_accounts, new_pool_fee, new_manager) =
121124
setup().await;
122125

@@ -126,6 +129,48 @@ async fn test_set_manager_without_signature() {
126129
let accounts = vec![
127130
AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false),
128131
AccountMeta::new_readonly(stake_pool_accounts.manager.pubkey(), false),
132+
AccountMeta::new_readonly(new_manager.pubkey(), true),
133+
AccountMeta::new_readonly(new_pool_fee.pubkey(), false),
134+
];
135+
let instruction = Instruction {
136+
program_id: id(),
137+
accounts,
138+
data,
139+
};
140+
141+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
142+
transaction.sign(&[&payer, &new_manager], recent_blockhash);
143+
let transaction_error = banks_client
144+
.process_transaction(transaction)
145+
.await
146+
.err()
147+
.unwrap();
148+
149+
match transaction_error {
150+
TransportError::TransactionError(TransactionError::InstructionError(
151+
_,
152+
InstructionError::Custom(error_index),
153+
)) => {
154+
let program_error = error::StakePoolError::SignatureMissing as u32;
155+
assert_eq!(error_index, program_error);
156+
}
157+
_ => panic!(
158+
"Wrong error occurs while try to set new manager without existing manager signature"
159+
),
160+
}
161+
}
162+
163+
#[tokio::test]
164+
async fn test_set_manager_without_new_signature() {
165+
let (mut banks_client, payer, recent_blockhash, stake_pool_accounts, new_pool_fee, new_manager) =
166+
setup().await;
167+
168+
let data = instruction::StakePoolInstruction::SetManager
169+
.try_to_vec()
170+
.unwrap();
171+
let accounts = vec![
172+
AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false),
173+
AccountMeta::new_readonly(stake_pool_accounts.manager.pubkey(), true),
129174
AccountMeta::new_readonly(new_manager.pubkey(), false),
130175
AccountMeta::new_readonly(new_pool_fee.pubkey(), false),
131176
];
@@ -136,7 +181,7 @@ async fn test_set_manager_without_signature() {
136181
};
137182

138183
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
139-
transaction.sign(&[&payer], recent_blockhash);
184+
transaction.sign(&[&payer, &stake_pool_accounts.manager], recent_blockhash);
140185
let transaction_error = banks_client
141186
.process_transaction(transaction)
142187
.await
@@ -151,7 +196,9 @@ async fn test_set_manager_without_signature() {
151196
let program_error = error::StakePoolError::SignatureMissing as u32;
152197
assert_eq!(error_index, program_error);
153198
}
154-
_ => panic!("Wrong error occurs while try to set new manager without signature"),
199+
_ => {
200+
panic!("Wrong error occurs while try to set new manager without new manager signature")
201+
}
155202
}
156203
}
157204

@@ -199,7 +246,10 @@ async fn test_set_manager_with_wrong_mint_for_pool_fee_acc() {
199246
)],
200247
Some(&payer.pubkey()),
201248
);
202-
transaction.sign(&[&payer, &stake_pool_accounts.manager], recent_blockhash);
249+
transaction.sign(
250+
&[&payer, &stake_pool_accounts.manager, &new_manager],
251+
recent_blockhash,
252+
);
203253
let transaction_error = banks_client
204254
.process_transaction(transaction)
205255
.await

0 commit comments

Comments
 (0)