backport #433 to v2

This commit is contained in:
Jack May 2020-09-21 12:43:32 -07:00
parent 08fe8307f0
commit 449d74ba90
1 changed files with 328 additions and 9 deletions

View File

@ -161,19 +161,18 @@ impl Processor {
return Ok(());
}
let mut source_data = source_account_info.data.borrow_mut();
let mut dest_data = dest_account_info.data.borrow_mut();
Account::unpack_mut(&mut source_data, &mut |source_account: &mut Account| {
Account::unpack_mut(&mut dest_data, &mut |dest_account: &mut Account| {
let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
let mut dest_account = Account::unpack(&dest_account_info.data.borrow())?;
if source_account.amount < amount {
return Err(TokenError::InsufficientFunds.into());
}
if source_account.mint != dest_account.mint {
return Err(TokenError::MintMismatch.into());
}
if source_account.is_frozen() || dest_account.is_frozen() {
return Err(TokenError::AccountFrozen.into());
}
if source_account.mint != dest_account.mint {
return Err(TokenError::MintMismatch.into());
}
if let Some((mint_info, expected_decimals)) = expected_mint_info {
if source_account.mint != *mint_info.key {
@ -234,9 +233,10 @@ impl Processor {
.ok_or(TokenError::Overflow)?;
}
Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
Account::pack(dest_account, &mut dest_account_info.data.borrow_mut())?;
Ok(())
})
})
}
/// Processes an [Approve](enum.TokenInstruction.html) instruction.
@ -815,6 +815,13 @@ mod tests {
Processor::process(&instruction.program_id, &account_infos, &instruction.data)
}
fn do_process_instruction_dups(
instruction: Instruction,
account_infos: Vec<AccountInfo>,
) -> ProgramResult {
Processor::process(&instruction.program_id, &account_infos, &instruction.data)
}
fn return_token_error_as_program_error() -> ProgramError {
TokenError::MintMismatch.into()
}
@ -1089,6 +1096,318 @@ mod tests {
);
}
#[test]
fn test_transfer_dups() {
let program_id = pubkey_rand();
let account1_key = pubkey_rand();
let mut account1_account = SolanaAccount::new(
account_minimum_balance(),
Account::get_packed_len(),
&program_id,
);
let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
let account2_key = pubkey_rand();
let mut account2_account = SolanaAccount::new(
account_minimum_balance(),
Account::get_packed_len(),
&program_id,
);
let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
let account3_key = pubkey_rand();
let mut account3_account = SolanaAccount::new(
account_minimum_balance(),
Account::get_packed_len(),
&program_id,
);
let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
let account4_key = pubkey_rand();
let mut account4_account = SolanaAccount::new(
account_minimum_balance(),
Account::get_packed_len(),
&program_id,
);
let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
let multisig_key = pubkey_rand();
let mut multisig_account = SolanaAccount::new(
multisig_minimum_balance(),
Multisig::get_packed_len(),
&program_id,
);
let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
let owner_key = pubkey_rand();
let mut owner_account = SolanaAccount::default();
let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
let mint_key = pubkey_rand();
let mut mint_account =
SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
let rent_key = rent::id();
let mut rent_sysvar = rent_sysvar();
let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
// create mint
do_process_instruction_dups(
initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
vec![mint_info.clone(), rent_info.clone()],
)
.unwrap();
// create account
do_process_instruction_dups(
initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
vec![
account1_info.clone(),
mint_info.clone(),
account1_info.clone(),
rent_info.clone(),
],
)
.unwrap();
// create another account
do_process_instruction_dups(
initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
vec![
account2_info.clone(),
mint_info.clone(),
owner_info.clone(),
rent_info.clone(),
],
)
.unwrap();
// mint to account
do_process_instruction_dups(
mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
)
.unwrap();
// source-owner transfer
do_process_instruction_dups(
transfer(
&program_id,
&account1_key,
&account2_key,
&account1_key,
&[],
500,
)
.unwrap(),
vec![
account1_info.clone(),
account2_info.clone(),
account1_info.clone(),
],
)
.unwrap();
// source-owner transfer2
do_process_instruction_dups(
transfer2(
&program_id,
&account1_key,
&mint_key,
&account2_key,
&account1_key,
&[],
500,
2,
)
.unwrap(),
vec![
account1_info.clone(),
mint_info.clone(),
account2_info.clone(),
account1_info.clone(),
],
)
.unwrap();
// source-delegate transfer
Account::unpack_unchecked_mut(
&mut account1_info.data.borrow_mut(),
&mut |account: &mut Account| {
account.amount = 1000;
account.delegated_amount = 1000;
account.delegate = COption::Some(account1_key);
account.owner = owner_key;
Ok(())
},
)
.unwrap();
do_process_instruction_dups(
transfer(
&program_id,
&account1_key,
&account2_key,
&account1_key,
&[],
500,
)
.unwrap(),
vec![
account1_info.clone(),
account2_info.clone(),
account1_info.clone(),
],
)
.unwrap();
// source-delegate transfer2
do_process_instruction_dups(
transfer2(
&program_id,
&account1_key,
&mint_key,
&account2_key,
&account1_key,
&[],
500,
2,
)
.unwrap(),
vec![
account1_info.clone(),
mint_info.clone(),
account2_info.clone(),
account1_info.clone(),
],
)
.unwrap();
// test destination-owner transfer
do_process_instruction_dups(
initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
vec![
account3_info.clone(),
mint_info.clone(),
account2_info.clone(),
rent_info.clone(),
],
)
.unwrap();
do_process_instruction_dups(
mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
)
.unwrap();
account1_info.is_signer = false;
account2_info.is_signer = true;
do_process_instruction_dups(
transfer(
&program_id,
&account3_key,
&account2_key,
&account2_key,
&[],
500,
)
.unwrap(),
vec![
account3_info.clone(),
account2_info.clone(),
account2_info.clone(),
],
)
.unwrap();
// destination-owner transfer2
do_process_instruction_dups(
transfer2(
&program_id,
&account3_key,
&mint_key,
&account2_key,
&account2_key,
&[],
500,
2,
)
.unwrap(),
vec![
account3_info.clone(),
mint_info.clone(),
account2_info.clone(),
account2_info.clone(),
],
)
.unwrap();
// test source-multisig signer
do_process_instruction_dups(
initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
vec![
multisig_info.clone(),
rent_info.clone(),
account4_info.clone(),
],
)
.unwrap();
do_process_instruction_dups(
initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
vec![
account4_info.clone(),
mint_info.clone(),
multisig_info.clone(),
rent_info.clone(),
],
)
.unwrap();
do_process_instruction_dups(
mint_to(&program_id, &mint_key, &account4_key, &owner_key, &[], 1000).unwrap(),
vec![mint_info.clone(), account4_info.clone(), owner_info.clone()],
)
.unwrap();
// source-multisig-signer transfer
do_process_instruction_dups(
transfer(
&program_id,
&account4_key,
&account2_key,
&multisig_key,
&[&account4_key],
500,
)
.unwrap(),
vec![
account4_info.clone(),
account2_info.clone(),
multisig_info.clone(),
account4_info.clone(),
],
)
.unwrap();
// source-multisig-signer transfer2
do_process_instruction_dups(
transfer2(
&program_id,
&account4_key,
&mint_key,
&account2_key,
&multisig_key,
&[&account4_key],
500,
2,
)
.unwrap(),
vec![
account4_info.clone(),
mint_info.clone(),
account2_info.clone(),
multisig_info.clone(),
account4_info.clone(),
],
)
.unwrap();
}
#[test]
fn test_transfer() {
let program_id = pubkey_rand();