fix: stake-pool require signature in SetManager (#2273)
* add check for new_manager's signature in SetManager * cli arg edit
This commit is contained in:
parent
974541c158
commit
11a5551446
|
@ -1311,15 +1311,15 @@ fn command_withdraw(
|
||||||
fn command_set_manager(
|
fn command_set_manager(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
stake_pool_address: &Pubkey,
|
stake_pool_address: &Pubkey,
|
||||||
new_manager: &Option<Pubkey>,
|
new_manager: &Option<Keypair>,
|
||||||
new_fee_receiver: &Option<Pubkey>,
|
new_fee_receiver: &Option<Pubkey>,
|
||||||
) -> CommandResult {
|
) -> CommandResult {
|
||||||
let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
|
let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
|
||||||
|
|
||||||
// If new accounts are missing in the arguments use the old ones
|
// If new accounts are missing in the arguments use the old ones
|
||||||
let new_manager = match new_manager {
|
let (new_manager_pubkey, mut signers): (Pubkey, Vec<&dyn Signer>) = match new_manager {
|
||||||
None => stake_pool.manager,
|
None => (stake_pool.manager, vec![]),
|
||||||
Some(value) => *value,
|
Some(value) => (value.pubkey(), vec![value]),
|
||||||
};
|
};
|
||||||
let new_fee_receiver = match new_fee_receiver {
|
let new_fee_receiver = match new_fee_receiver {
|
||||||
None => stake_pool.manager_fee_account,
|
None => stake_pool.manager_fee_account,
|
||||||
|
@ -1336,7 +1336,10 @@ fn command_set_manager(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.manager.as_ref()];
|
signers.append(&mut vec![
|
||||||
|
config.fee_payer.as_ref(),
|
||||||
|
config.manager.as_ref(),
|
||||||
|
]);
|
||||||
unique_signers!(signers);
|
unique_signers!(signers);
|
||||||
let transaction = checked_transaction_with_signers(
|
let transaction = checked_transaction_with_signers(
|
||||||
config,
|
config,
|
||||||
|
@ -1344,7 +1347,7 @@ fn command_set_manager(
|
||||||
&spl_stake_pool::id(),
|
&spl_stake_pool::id(),
|
||||||
stake_pool_address,
|
stake_pool_address,
|
||||||
&config.manager.pubkey(),
|
&config.manager.pubkey(),
|
||||||
&new_manager,
|
&new_manager_pubkey,
|
||||||
&new_fee_receiver,
|
&new_fee_receiver,
|
||||||
)],
|
)],
|
||||||
&signers,
|
&signers,
|
||||||
|
@ -1999,10 +2002,10 @@ fn main() {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("new_manager")
|
Arg::with_name("new_manager")
|
||||||
.long("new-manager")
|
.long("new-manager")
|
||||||
.validator(is_pubkey)
|
.validator(is_keypair)
|
||||||
.value_name("ADDRESS")
|
.value_name("KEYPAIR")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Public key for the new stake pool manager."),
|
.help("Keypair for the new stake pool manager."),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("new_fee_receiver")
|
Arg::with_name("new_fee_receiver")
|
||||||
|
@ -2360,7 +2363,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
("set-manager", Some(arg_matches)) => {
|
("set-manager", Some(arg_matches)) => {
|
||||||
let stake_pool_address = pubkey_of(arg_matches, "pool").unwrap();
|
let stake_pool_address = pubkey_of(arg_matches, "pool").unwrap();
|
||||||
let new_manager: Option<Pubkey> = pubkey_of(arg_matches, "new_manager");
|
let new_manager: Option<Keypair> = keypair_of(arg_matches, "new_manager");
|
||||||
let new_fee_receiver: Option<Pubkey> = pubkey_of(arg_matches, "new_fee_receiver");
|
let new_fee_receiver: Option<Pubkey> = pubkey_of(arg_matches, "new_fee_receiver");
|
||||||
command_set_manager(
|
command_set_manager(
|
||||||
&config,
|
&config,
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ pub fn set_manager(
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new(*stake_pool, false),
|
AccountMeta::new(*stake_pool, false),
|
||||||
AccountMeta::new_readonly(*manager, true),
|
AccountMeta::new_readonly(*manager, true),
|
||||||
AccountMeta::new_readonly(*new_manager, false),
|
AccountMeta::new_readonly(*new_manager, true),
|
||||||
AccountMeta::new_readonly(*new_fee_receiver, false),
|
AccountMeta::new_readonly(*new_fee_receiver, false),
|
||||||
];
|
];
|
||||||
Instruction {
|
Instruction {
|
||||||
|
|
|
@ -2366,6 +2366,10 @@ impl Processor {
|
||||||
}
|
}
|
||||||
|
|
||||||
stake_pool.check_manager(manager_info)?;
|
stake_pool.check_manager(manager_info)?;
|
||||||
|
if !new_manager_info.is_signer {
|
||||||
|
msg!("New manager signature missing");
|
||||||
|
return Err(StakePoolError::SignatureMissing.into());
|
||||||
|
}
|
||||||
|
|
||||||
if stake_pool.pool_mint
|
if stake_pool.pool_mint
|
||||||
!= spl_token::state::Account::unpack_from_slice(&new_manager_fee_info.data.borrow())?
|
!= spl_token::state::Account::unpack_from_slice(&new_manager_fee_info.data.borrow())?
|
||||||
|
@ -2412,7 +2416,7 @@ impl Processor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Processes [SetManager](enum.Instruction.html).
|
/// Processes [SetStaker](enum.Instruction.html).
|
||||||
fn process_set_staker(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
|
fn process_set_staker(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
|
||||||
let account_info_iter = &mut accounts.iter();
|
let account_info_iter = &mut accounts.iter();
|
||||||
let stake_pool_info = next_account_info(account_info_iter)?;
|
let stake_pool_info = next_account_info(account_info_iter)?;
|
||||||
|
|
|
@ -71,7 +71,10 @@ async fn test_set_manager() {
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
);
|
);
|
||||||
transaction.sign(&[&payer, &stake_pool_accounts.manager], recent_blockhash);
|
transaction.sign(
|
||||||
|
&[&payer, &stake_pool_accounts.manager, &new_manager],
|
||||||
|
recent_blockhash,
|
||||||
|
);
|
||||||
banks_client.process_transaction(transaction).await.unwrap();
|
banks_client.process_transaction(transaction).await.unwrap();
|
||||||
|
|
||||||
let stake_pool = get_account(&mut banks_client, &stake_pool_accounts.stake_pool.pubkey()).await;
|
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() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_set_manager_without_signature() {
|
async fn test_set_manager_without_existing_signature() {
|
||||||
let (mut banks_client, payer, recent_blockhash, stake_pool_accounts, new_pool_fee, new_manager) =
|
let (mut banks_client, payer, recent_blockhash, stake_pool_accounts, new_pool_fee, new_manager) =
|
||||||
setup().await;
|
setup().await;
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ async fn test_set_manager_without_signature() {
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false),
|
AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false),
|
||||||
AccountMeta::new_readonly(stake_pool_accounts.manager.pubkey(), false),
|
AccountMeta::new_readonly(stake_pool_accounts.manager.pubkey(), false),
|
||||||
AccountMeta::new_readonly(new_manager.pubkey(), false),
|
AccountMeta::new_readonly(new_manager.pubkey(), true),
|
||||||
AccountMeta::new_readonly(new_pool_fee.pubkey(), false),
|
AccountMeta::new_readonly(new_pool_fee.pubkey(), false),
|
||||||
];
|
];
|
||||||
let instruction = Instruction {
|
let instruction = Instruction {
|
||||||
|
@ -136,7 +139,7 @@ async fn test_set_manager_without_signature() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
||||||
transaction.sign(&[&payer], recent_blockhash);
|
transaction.sign(&[&payer, &new_manager], recent_blockhash);
|
||||||
let transaction_error = banks_client
|
let transaction_error = banks_client
|
||||||
.process_transaction(transaction)
|
.process_transaction(transaction)
|
||||||
.await
|
.await
|
||||||
|
@ -151,7 +154,51 @@ async fn test_set_manager_without_signature() {
|
||||||
let program_error = error::StakePoolError::SignatureMissing as u32;
|
let program_error = error::StakePoolError::SignatureMissing as u32;
|
||||||
assert_eq!(error_index, program_error);
|
assert_eq!(error_index, program_error);
|
||||||
}
|
}
|
||||||
_ => panic!("Wrong error occurs while try to set new manager without signature"),
|
_ => panic!(
|
||||||
|
"Wrong error occurs while try to set new manager without existing manager signature"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_set_manager_without_new_signature() {
|
||||||
|
let (mut banks_client, payer, recent_blockhash, stake_pool_accounts, new_pool_fee, new_manager) =
|
||||||
|
setup().await;
|
||||||
|
|
||||||
|
let data = instruction::StakePoolInstruction::SetManager
|
||||||
|
.try_to_vec()
|
||||||
|
.unwrap();
|
||||||
|
let accounts = vec![
|
||||||
|
AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false),
|
||||||
|
AccountMeta::new_readonly(stake_pool_accounts.manager.pubkey(), true),
|
||||||
|
AccountMeta::new_readonly(new_manager.pubkey(), false),
|
||||||
|
AccountMeta::new_readonly(new_pool_fee.pubkey(), false),
|
||||||
|
];
|
||||||
|
let instruction = Instruction {
|
||||||
|
program_id: id(),
|
||||||
|
accounts,
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
||||||
|
transaction.sign(&[&payer, &stake_pool_accounts.manager], recent_blockhash);
|
||||||
|
let transaction_error = banks_client
|
||||||
|
.process_transaction(transaction)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match transaction_error {
|
||||||
|
TransportError::TransactionError(TransactionError::InstructionError(
|
||||||
|
_,
|
||||||
|
InstructionError::Custom(error_index),
|
||||||
|
)) => {
|
||||||
|
let program_error = error::StakePoolError::SignatureMissing as u32;
|
||||||
|
assert_eq!(error_index, program_error);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Wrong error occurs while try to set new manager without new manager signature")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +246,10 @@ async fn test_set_manager_with_wrong_mint_for_pool_fee_acc() {
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
);
|
);
|
||||||
transaction.sign(&[&payer, &stake_pool_accounts.manager], recent_blockhash);
|
transaction.sign(
|
||||||
|
&[&payer, &stake_pool_accounts.manager, &new_manager],
|
||||||
|
recent_blockhash,
|
||||||
|
);
|
||||||
let transaction_error = banks_client
|
let transaction_error = banks_client
|
||||||
.process_transaction(transaction)
|
.process_transaction(transaction)
|
||||||
.await
|
.await
|
||||||
|
|
Loading…
Reference in New Issue