Allow destination or mint to be mint_authority in MintTo and MintTo2 (#436)
* Add failing test * No need to hold dest or mint RefMut in process_mint_to
This commit is contained in:
parent
179be4a590
commit
288b438868
|
@ -421,50 +421,49 @@ impl Processor {
|
|||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let owner_info = next_account_info(account_info_iter)?;
|
||||
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
Account::unpack_mut(&mut dest_account_data, &mut |dest_account: &mut Account| {
|
||||
if dest_account.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
let mut dest_account = Account::unpack(&dest_account_info.data.borrow())?;
|
||||
if dest_account.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
if dest_account.is_native() {
|
||||
return Err(TokenError::NativeNotSupported.into());
|
||||
}
|
||||
if mint_info.key != &dest_account.mint {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
let mut mint = Mint::unpack(&mint_info.data.borrow())?;
|
||||
if let Some(expected_decimals) = expected_decimals {
|
||||
if expected_decimals != mint.decimals {
|
||||
return Err(TokenError::MintDecimalsMismatch.into());
|
||||
}
|
||||
}
|
||||
|
||||
if dest_account.is_native() {
|
||||
return Err(TokenError::NativeNotSupported.into());
|
||||
}
|
||||
if mint_info.key != &dest_account.mint {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
match mint.mint_authority {
|
||||
COption::Some(mint_authority) => Self::validate_owner(
|
||||
program_id,
|
||||
&mint_authority,
|
||||
owner_info,
|
||||
account_info_iter.as_slice(),
|
||||
)?,
|
||||
COption::None => return Err(TokenError::FixedSupply.into()),
|
||||
}
|
||||
|
||||
let mut mint_data = mint_info.data.borrow_mut();
|
||||
Mint::unpack_mut(&mut mint_data, &mut |mint: &mut Mint| {
|
||||
if let Some(expected_decimals) = expected_decimals {
|
||||
if expected_decimals != mint.decimals {
|
||||
return Err(TokenError::MintDecimalsMismatch.into());
|
||||
}
|
||||
}
|
||||
dest_account.amount = dest_account
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
match mint.mint_authority {
|
||||
COption::Some(mint_authority) => Self::validate_owner(
|
||||
program_id,
|
||||
&mint_authority,
|
||||
owner_info,
|
||||
account_info_iter.as_slice(),
|
||||
)?,
|
||||
COption::None => return Err(TokenError::FixedSupply.into()),
|
||||
}
|
||||
mint.supply = mint
|
||||
.supply
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
dest_account.amount = dest_account
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
Account::pack(dest_account, &mut dest_account_info.data.borrow_mut())?;
|
||||
Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
|
||||
|
||||
mint.supply = mint
|
||||
.supply
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Processes a [Burn](enum.TokenInstruction.html) instruction.
|
||||
|
@ -2524,6 +2523,104 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mint_to_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 account1_info: AccountInfo = (&account1_key, true, &mut account1_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, true, &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, &mint_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, &owner_key).unwrap(),
|
||||
vec![
|
||||
account1_info.clone(),
|
||||
mint_info.clone(),
|
||||
owner_info.clone(),
|
||||
rent_info.clone(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// mint_to when mint_authority is self
|
||||
do_process_instruction_dups(
|
||||
mint_to(&program_id, &mint_key, &account1_key, &mint_key, &[], 42).unwrap(),
|
||||
vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// mint_to2 when mint_authority is self
|
||||
do_process_instruction_dups(
|
||||
mint_to2(&program_id, &mint_key, &account1_key, &mint_key, &[], 42, 2).unwrap(),
|
||||
vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// mint_to when mint_authority is account owner
|
||||
Mint::unpack_unchecked_mut(&mut mint_info.data.borrow_mut(), &mut |mint: &mut Mint| {
|
||||
mint.mint_authority = COption::Some(account1_key);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
do_process_instruction_dups(
|
||||
mint_to(
|
||||
&program_id,
|
||||
&mint_key,
|
||||
&account1_key,
|
||||
&account1_key,
|
||||
&[],
|
||||
42,
|
||||
)
|
||||
.unwrap(),
|
||||
vec![
|
||||
mint_info.clone(),
|
||||
account1_info.clone(),
|
||||
account1_info.clone(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// mint_to2 when mint_authority is account owner
|
||||
do_process_instruction_dups(
|
||||
mint_to(
|
||||
&program_id,
|
||||
&mint_key,
|
||||
&account1_key,
|
||||
&account1_key,
|
||||
&[],
|
||||
42,
|
||||
)
|
||||
.unwrap(),
|
||||
vec![
|
||||
mint_info.clone(),
|
||||
account1_info.clone(),
|
||||
account1_info.clone(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mint_to() {
|
||||
let program_id = pubkey_rand();
|
||||
|
|
Loading…
Reference in New Issue